vscode-texinfo/src/preview.ts

101 lines
3.1 KiB
TypeScript
Raw Normal View History

2020-10-03 18:04:18 +00:00
/**
* preview.ts
*
* @author CismonX <admin@cismon.net>
* @license MIT
*/
import * as path from 'path';
import * as vscode from 'vscode';
2020-10-14 19:22:32 +00:00
import Converter from './converter';
2020-10-20 20:07:44 +00:00
import Document from './document';
2020-10-14 19:22:32 +00:00
import Options from './options';
import * as utils from './utils';
2020-10-03 18:04:18 +00:00
/**
* Texinfo document preview.
*/
2020-10-14 19:22:32 +00:00
export default class Preview {
2020-10-03 18:04:18 +00:00
/**
* Create (if not yet created) and show preview for a Texinfo document.
*
* @param editor The editor where the document is being held.
*/
static async show(editor: vscode.TextEditor) {
const document = editor.document;
2020-10-20 20:07:44 +00:00
const documentContext = Document.get(document);
if (documentContext === undefined) {
return;
}
2020-10-03 18:04:18 +00:00
if (document.isUntitled) {
2020-10-20 20:07:44 +00:00
if (!await utils.prompt('Save this document to display preview.', 'Save')) return;
if (!await document.save()) return;
2020-10-03 18:04:18 +00:00
}
2020-10-20 20:07:44 +00:00
documentContext.initPreview().panel.reveal();
2020-10-03 18:04:18 +00:00
}
2020-10-20 20:07:44 +00:00
private readonly document = this.documentContext.document;
2020-10-03 18:04:18 +00:00
private readonly panel: vscode.WebviewPanel;
2020-10-04 12:40:54 +00:00
private readonly disposables = <vscode.Disposable[]>[];
2020-10-03 18:04:18 +00:00
/**
* Whether the preview is updating.
*/
private updating = false;
/**
* Whether a preview update request is pending.
*/
private pendingUpdate = false;
2020-10-20 20:07:44 +00:00
constructor(private readonly documentContext: Document) {
2020-10-03 18:04:18 +00:00
this.panel = vscode.window.createWebviewPanel('texinfo.preview', '', vscode.ViewColumn.Beside);
2020-10-20 20:07:44 +00:00
this.disposables.push(this.panel.onDidDispose(() => this.close()));
2020-10-03 18:04:18 +00:00
this.updateWebview();
}
2020-10-04 12:40:54 +00:00
private updateTitle() {
2020-10-03 18:04:18 +00:00
const updating = this.updating ? '(Updating) ' : '';
const fileName = path.basename(this.document.fileName);
2020-10-04 12:40:54 +00:00
this.panel.title = `${updating}Preview ${fileName}`;
2020-10-03 18:04:18 +00:00
}
2020-10-20 20:07:44 +00:00
close() {
this.disposables.forEach(event => event.dispose());
2020-10-03 18:04:18 +00:00
this.panel.dispose();
2020-10-20 20:07:44 +00:00
this.documentContext.closePreview();
2020-10-03 18:04:18 +00:00
}
2020-10-20 20:07:44 +00:00
async updateWebview() {
2020-10-03 18:04:18 +00:00
if (this.updating) {
this.pendingUpdate = true;
return;
}
this.updating = true;
this.pendingUpdate = false;
2020-10-04 12:40:54 +00:00
this.updateTitle();
let htmlCode = await Converter.convertToHtml(this.document.fileName);
2020-10-03 18:04:18 +00:00
if (htmlCode === undefined) {
2020-10-04 12:40:54 +00:00
vscode.window.showErrorMessage(`Failed to show preview for ${this.document.fileName}.`);
2020-10-03 18:04:18 +00:00
} else {
if (Options.displayImage) {
const pathName = path.dirname(this.document.fileName);
// To display images in webviews, image URIs in HTML should be converted to VSCode-recognizable ones.
2020-10-20 20:07:44 +00:00
htmlCode = utils.transformHtmlImageUri(htmlCode, src => {
const srcUri = vscode.Uri.file(pathName + '/' + src);
return this.panel.webview.asWebviewUri(srcUri).toString();
});
}
2020-10-03 18:04:18 +00:00
this.panel.webview.html = htmlCode;
}
this.updating = false;
2020-10-04 12:40:54 +00:00
this.updateTitle();
2020-10-15 20:16:13 +00:00
this.pendingUpdate && this.updateWebview();
2020-10-03 18:04:18 +00:00
}
}