vscode中markdown預(yù)覽的實(shí)現(xiàn)原理

這篇文章主要講解了“vscode中markdown預(yù)覽的實(shí)現(xiàn)原理”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“vscode中markdown預(yù)覽的實(shí)現(xiàn)原理”吧!

十余年建站經(jīng)驗(yàn), 網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì)客戶的見(jiàn)證與正確選擇。創(chuàng)新互聯(lián)提供完善的營(yíng)銷型網(wǎng)頁(yè)建站明細(xì)報(bào)價(jià)表。后期開(kāi)發(fā)更加便捷高效,我們致力于追求更美、更快、更規(guī)范。

思路分析

通過(guò) vscode.window.createWebviewPanel 創(chuàng)建一個(gè) webview,指定在側(cè)邊打開(kāi),之后通過(guò)該  panel 對(duì)象的 webview.html 屬性來(lái)設(shè)置 html。

html 是通過(guò)編輯器的 markdown 內(nèi)容生成的, 編輯器內(nèi)容通過(guò) editor.document.getText() 拿到,然后調(diào)用第三方的 markdown 轉(zhuǎn) html 的庫(kù)來(lái)生成。

這樣就完成了 markdown 的預(yù)覽。

預(yù)覽之后需要更新,監(jiān)聽(tīng) vscode.workspace.onDidSaveTextDocument 和 vscode.workspace.onDidChangeTextDocument 的事件,在文檔更新和保存的時(shí)候,拿到編輯器的內(nèi)容,重新生成 html,然后設(shè)置到 webview。

webviewPanel 支持 webview.postMessage(message); 的方式傳遞消息,支持 updateHTML 等一系列 command,可以通過(guò)傳遞消息來(lái)觸發(fā)。

但是怎么知道哪個(gè)文檔更新哪個(gè) webview 呢?

可以維護(hù)一個(gè) map,在創(chuàng)建 webviewPanel 的時(shí)候記錄到 map 中,key 為文件路徑,這樣更新的時(shí)候就能查找到對(duì)應(yīng)的 webview 進(jìn)行更新。

這樣,就完成了 markdown 內(nèi)容的更新。

其實(shí)整體思路還是比較簡(jiǎn)單的,下面我們來(lái)寫(xiě)下代碼

代碼實(shí)現(xiàn)

我們看下 vscode-markdown-preview-enhanced 的插件的代碼,這也是一個(gè)預(yù)覽 markdown 的插件,代碼還算簡(jiǎn)潔,可以用來(lái)學(xué)習(xí)。

(以下代碼是簡(jiǎn)化后的代碼)

首先,插件要指定觸發(fā)的條件,也就是在 package.json 里面指定 activationEvents:

"activationEvents": [
    "onLanguage:markdown",
    "onCommand:markdown-preview-enhanced.openPreviewToTheSide"
],

這里一個(gè)是編輯 markdown 內(nèi)容的時(shí)候激活,一個(gè)是執(zhí)行 command 的時(shí)候激活。

具體激活的邏輯在 active 方法里:

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,
    });
  }
}

我們注冊(cè)了那個(gè) command,執(zhí)行 command 會(huì)拿到當(dāng)前 editor 的 url,然后進(jìn)行 markdown 的 preview。

preview 的所有邏輯都集中定義在了 MarkdownPreviewEnhancedView 的實(shí)例對(duì)象中,在 command 觸發(fā)時(shí)執(zhí)行 initPreivew。

public async initPreview(
    sourceUri: vscode.Uri,
    editor: vscode.TextEditor,
    viewOptions: { viewColumn: vscode.ViewColumn; preserveFocus?: boolean },
) {
    // 創(chuàng)建 webview
    let previewPanel: vscode.WebviewPanel = vscode.window.createWebviewPanel(
        "markdown-preview-enhanced",
        `Preview ${path.basename(sourceUri.fsPath)}`,
        viewOptions
    );

    // 監(jiān)聽(tīng) webview 的消息
    previewPanel.webview.onDidReceiveMessage((message) => {});

    // 記錄 webview 到 map 中
    this.previewMaps[sourceUri.fsPath] = previewPanel;
    
    // 拿到編輯器的文本,生成 html
    const text = editor.document.getText();
    engine
      .generateHTMLTemplateForPreview({inputString: text})
      .then((html) => {
        // 設(shè)置 html 到 previewPanel
        previewPanel.webview.html = html;
      });
}

在 initWebivew 里面創(chuàng)建 webviewPanel,同時(shí)把 webviewPanel 保存到 map 中,key 為文檔的文件路徑。拿到編輯器文本來(lái)生成 html,設(shè)置到 webview.html,這樣就完成了 markdown 的預(yù)覽。

這條路徑走通之后,我們就實(shí)現(xiàn)了 markdown 的預(yù)覽。

但是只預(yù)覽一次不行,更新文檔之后需要自動(dòng)更新,我們繼續(xù)在 active 方法里添加事件監(jiān)聽(tīng):

  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);
      }
    }),
  );

監(jiān)聽(tīng)文本修改和保存的時(shí)候,調(diào)用 update 方法來(lái)更新。

public updateMarkdown(sourceUri: Uri) {

    // 從 map 中根據(jù)文件路徑取出對(duì)應(yīng)的 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
            });
        }

}

這里是通過(guò) webview.postMessage 給 html 內(nèi)容傳遞 updateHTML 的 command 消息,觸發(fā) html 內(nèi)容的更新。

這樣,我們就實(shí)現(xiàn)了 markdown 的同步刷新。

總結(jié)

vscode 里面 markdown 的預(yù)覽是一個(gè)常用但實(shí)現(xiàn)起來(lái)并不難的功能,我們看了下 vscode-markdown-preview-enhanced 插件的源碼,理清了整體的流程:

  • 通過(guò) vscode.window.createWebviewPanel 創(chuàng)建 webviewPanel 來(lái)顯示 html

  • html 通過(guò) editor.document.getText() 拿到文本內(nèi)容之后通過(guò)第三方包生成,設(shè)置到 webviewPanel

  • 監(jiān)聽(tīng) workspace.onDidSaveTextDocument 和 workspace.onDidChangeTextDocument,來(lái)拿到最新內(nèi)容,之后生成 html 通過(guò) webview.postMessage 傳遞 udpateHTML 的消息來(lái)更新到 webview。

  • 要注意的是,需要記錄一個(gè) map 來(lái)保存 uri.fsPath 和 webviewPanel 的對(duì)應(yīng)關(guān)系,實(shí)現(xiàn)文本內(nèi)容改變更新對(duì)應(yīng)的 webview

感謝各位的閱讀,以上就是“vscode中markdown預(yù)覽的實(shí)現(xiàn)原理”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)vscode中markdown預(yù)覽的實(shí)現(xiàn)原理這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

文章名稱:vscode中markdown預(yù)覽的實(shí)現(xiàn)原理
文章轉(zhuǎn)載:http://muchs.cn/article34/gphjse.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站制作、網(wǎng)站營(yíng)銷、網(wǎng)站制作、App開(kāi)發(fā)、域名注冊(cè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁(yè)設(shè)計(jì)公司