vscode’s markdown preview is a function we use all day long. Have you ever thought about how it is implemented? Maybe one day you will receive a request for customized markdown preview. What should you do? [Recommended learning: "vscode tutorial"]
In fact, the overall idea is relatively simple, which is to create a webview panel, set the content to the HTML generated by markdown, and then modify the webview simultaneously when markdown is updated. html will do.
Create a webview through vscode.window.createWebviewPanel, specify it to be opened on the side, and then set the html through the webview.html attribute of the panel object.
html is generated through the markdown content of the editor. The editor content is obtained through editor.document.getText(), and then a third-party markdown to html conversion library is called to generate it.
This completes the markdown preview.
After the preview needs to be updated, listen to the events of vscode.workspace.onDidSaveTextDocument and vscode.workspace.onDidChangeTextDocument. When the document is updated and saved, get the content of the editor, regenerate the html, and then set it to the webview.
WebviewPanel supports webview.postMessage(message); to pass messages, and supports a series of commands such as updateHTML, which can be triggered by passing messages.
But how do you know which document updates which webview?
You can maintain a map and record it into the map when creating the webviewPanel. The key is the file path, so that when updating, the corresponding webview can be found and updated.
In this way, the update of markdown content is completed.
In fact, the overall idea is relatively simple. Let’s write down the code.
Let’s take a look at the code of the vscode-markdown-preview-enhanced plug-in. This is It is also a plug-in for previewing markdown. The code is quite simple and can be used for learning.
(The following code is simplified code)
First, the plug-in must specify the triggering conditions, that is, specify activationEvents in package.json:
"activationEvents": [ "onLanguage:markdown", "onCommand:markdown-preview-enhanced.openPreviewToTheSide" ],
Here is It is activated when editing markdown content, and one is activated when command is executed.
The specific activation logic is in the active method:
export function activate(context: vscode.ExtensionContext) { const contentProvider = new MarkdownPreviewEnhancedView(context); context.subscriptions.push( vscode.commands.registerCommand( "markdown-preview-enhanced.openPreviewToTheSide", openPreviewToTheSide, ), ); function openPreviewToTheSide(uri?: vscode.Uri) { let resource = uri; if (!(resource instanceof vscode.Uri)) { if (vscode.window.activeTextEditor) { resource = vscode.window.activeTextEditor.document.uri; } } contentProvider.initPreview(resource, vscode.window.activeTextEditor, { viewColumn: vscode.ViewColumn.Two, preserveFocus: true, }); } }
We registered the command, and executing the command will get the url of the current editor, and then preview the markdown.
All the logic of preview is centrally defined in the instance object of MarkdownPreviewEnhancedView, and initPreivew is executed when the command is triggered.
public async initPreview( sourceUri: vscode.Uri, editor: vscode.TextEditor, viewOptions: { viewColumn: vscode.ViewColumn; preserveFocus?: boolean }, ) { // 创建 webview let previewPanel: vscode.WebviewPanel = vscode.window.createWebviewPanel( "markdown-preview-enhanced", `Preview ${path.basename(sourceUri.fsPath)}`, viewOptions ); // 监听 webview 的消息 previewPanel.webview.onDidReceiveMessage((message) => {}); // 记录 webview 到 map 中 this.previewMaps[sourceUri.fsPath] = previewPanel; // 拿到编辑器的文本,生成 html const text = editor.document.getText(); engine .generateHTMLTemplateForPreview({inputString: text}) .then((html) => { // 设置 html 到 previewPanel previewPanel.webview.html = html; }); }
Create the webviewPanel in initWebivew and save the webviewPanel to the map. The key is the file path of the document. Get the editor text to generate html and set it to webview.html, thus completing the markdown preview.
After this path is passed, we will realize the preview of markdown.
But only previewing once is not enough. After updating the document, it needs to be updated automatically. We continue to add event monitoring in the active method:
context.subscriptions.push( vscode.workspace.onDidSaveTextDocument((document) => { if (isMarkdownFile(document)) { contentProvider.updateMarkdown(document.uri, true); } }), ); context.subscriptions.push( vscode.workspace.onDidChangeTextDocument((event) => { if (isMarkdownFile(event.document)) { contentProvider.update(event.document.uri); } }), );
When monitoring text modification and saving, call the update method to update.
public updateMarkdown(sourceUri: Uri) { // 从 map 中根据文件路径取出对应的 webviewPanel const previewPanel = this.previewMaps[sourceUri.fsPath]; // 生成最新的 html 传递给 webview const text = document.getText(); engine .parseMD(text) .then(({ markdown, html }) => { previewPanel.webview.postMessage({ command: "updateHTML", html }); } }
Here is to pass the updateHTML command message to the html content through webview.postMessage, triggering the update of the html content.
In this way, we achieve synchronous refresh of markdown.
The preview of markdown in vscode is a commonly used but not difficult function to implement. We looked at the source code of the vscode-markdown-preview-enhanced plug-in and clarified the overall Process:
Markdown preview is a common but It is not a difficult requirement and is more suitable for entry-level vscode plug-in development. I hope this article can help you clarify your ideas.
For more programming-related knowledge, please visit: Introduction to Programming! !
The above is the detailed content of In-depth understanding of the implementation principle of markdown preview in vscode. For more information, please follow other related articles on the PHP Chinese website!