mirror of
https://github.com/microsoft/vscode.git
synced 2026-06-29 10:56:24 +01:00
5b839e0737
* updates markdown editor * fixes class names
120 lines
3.6 KiB
TypeScript
120 lines
3.6 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import { EditorController, EditorModel, EditorView, StringEdit, StringValue, findNodeOffsetById, taskCheckboxRange } from '@vscode/markdown-editor';
|
|
import { Disposable, autorun } from '@vscode/markdown-editor/observables';
|
|
import mermaid from 'mermaid';
|
|
import 'katex/dist/katex.min.css';
|
|
import '@vscode/markdown-editor/editor.css';
|
|
import '@vscode/markdown-editor/themes/vscode.css';
|
|
import './markdownEditor.css';
|
|
import { WebviewSyntaxHighlighter } from './syntaxHighlighter';
|
|
|
|
interface VsCodeApi {
|
|
postMessage(message: unknown): void;
|
|
getState(): unknown;
|
|
setState(state: unknown): void;
|
|
}
|
|
|
|
declare function acquireVsCodeApi(): VsCodeApi;
|
|
|
|
class Editor extends Disposable {
|
|
readonly model = new EditorModel();
|
|
isUpdatingFromExtension = false;
|
|
#mermaidCounter = 0;
|
|
#initialized = false;
|
|
|
|
readonly #vscode = acquireVsCodeApi();
|
|
readonly #syntaxHighlighter = new WebviewSyntaxHighlighter((message) => this.#vscode.postMessage(message));
|
|
|
|
constructor(host: HTMLElement) {
|
|
super();
|
|
|
|
mermaid.initialize({ startOnLoad: false, theme: 'default' });
|
|
|
|
window.addEventListener('message', (event) => {
|
|
const message = event.data;
|
|
if (this.#syntaxHighlighter.handleMessage(message)) {
|
|
return;
|
|
}
|
|
switch (message.type) {
|
|
case 'init': {
|
|
if (!this.#initialized) {
|
|
this.#initialized = true;
|
|
this.#createView(host, !!message.readonly);
|
|
this.model.sourceText.set(new StringValue(message.content), undefined);
|
|
}
|
|
break;
|
|
}
|
|
case 'update': {
|
|
this.isUpdatingFromExtension = true;
|
|
this.model.sourceText.set(new StringValue(message.content), undefined);
|
|
this.isUpdatingFromExtension = false;
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
|
|
this.#vscode.postMessage({ type: 'ready' });
|
|
}
|
|
|
|
#createView(host: HTMLElement, readonly: boolean): void {
|
|
const model = this.model;
|
|
|
|
const view = this._register(new EditorView(model, {
|
|
classNames: ['md-theme-vscode'],
|
|
syntaxHighlighter: this.#syntaxHighlighter,
|
|
onToggleCheckbox: (item, newChecked) => {
|
|
if (readonly) {
|
|
return;
|
|
}
|
|
const doc = model.document.get();
|
|
const itemOffset = findNodeOffsetById(doc, item);
|
|
if (itemOffset === undefined) { return; }
|
|
const range = taskCheckboxRange(item);
|
|
if (!range) { return; }
|
|
model.applyEdit(
|
|
StringEdit.replace(
|
|
range.delta(itemOffset),
|
|
newChecked ? '[x]' : '[ ]'
|
|
)
|
|
);
|
|
},
|
|
renderCustomCodeBlock: (language, content) => {
|
|
if (language !== 'mermaid') {
|
|
return undefined;
|
|
}
|
|
const div = document.createElement('div');
|
|
div.className = 'md-mermaid';
|
|
const id = `mermaid-${this.#mermaidCounter++}`;
|
|
mermaid
|
|
.render(id, content)
|
|
.then(({ svg }) => {
|
|
div.innerHTML = svg;
|
|
})
|
|
.catch(() => {
|
|
div.textContent = content;
|
|
});
|
|
return div;
|
|
},
|
|
}));
|
|
this._register(new EditorController(model, view));
|
|
host.appendChild(view.element);
|
|
|
|
if (!readonly) {
|
|
let firstTime = true;
|
|
this._register(autorun((reader) => {
|
|
const text = reader.readObservable(this.model.sourceText).value;
|
|
if (!this.isUpdatingFromExtension && !firstTime) {
|
|
this.#vscode.postMessage({ type: 'edit', content: text });
|
|
}
|
|
firstTime = false;
|
|
}));
|
|
}
|
|
}
|
|
}
|
|
|
|
new Editor(document.getElementById('editor')!);
|