网易首页 > 网易号 > 正文 申请入驻

教你实现Vscode的Markdown预览

0
分享至

vscode 的 markdown 预览是我们整天都在用的功能,有没有想过它是怎么实现的。或许有一天你会接到个定制 markdown 预览的需求,应该怎么做呢?

vscode 的 markdown 预览是我们整天都在用的功能,有没有想过它是怎么实现的。或许有一天你会接到个定制 markdown 预览的需求,应该怎么做呢?

有什么思路么?思考五秒钟。

5

4

3

2

1

其实整体思路比较简单,就是创建一个 webview panel,设置内容为 markdown 生成的 html,之后在 markdown 更新的时候同步修改 webview 的 html 就可以了。

思路分析

通过 vscode.window.createWebviewPanel 创建一个 webview,指定在侧边打开,之后通过该 panel 对象的 webview.html 属性来设置 html。

html 是通过编辑器的 markdown 内容生成的, 编辑器内容通过 editor.document.getText() 拿到,然后调用第三方的 markdown 转 html 的库来生成。

这样就完成了 markdown 的预览。

预览之后需要更新,监听 vscode.workspace.onDidSaveTextDocument 和 vscode.workspace.onDidChangeTextDocument 的事件,在文档更新和保存的时候,拿到编辑器的内容,重新生成 html,然后设置到 webview。

webviewPanel 支持 webview.postMessage(message); 的方式传递消息,支持 updateHTML 等一系列 command,可以通过传递消息来触发。

但是怎么知道哪个文档更新哪个 webview 呢?

可以维护一个 map,在创建 webviewPanel 的时候记录到 map 中,key 为文件路径,这样更新的时候就能查找到对应的 webview 进行更新。

这样,就完成了 markdown 内容的更新。

其实整体思路还是比较简单的,下面我们来写下代码:

代码实现

我们看下 vscode-markdown-preview-enhanced 的插件的代码,这也是一个预览 markdown 的插件,代码还算简洁,可以用来学习。

(以下代码是简化后的代码)

首先,插件要指定触发的条件,也就是在 package.json 里面指定 activationEvents:

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

这里一个是编辑 markdown 内容的时候激活,一个是执行 command 的时候激活。

具体激活的逻辑在 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, }); } }

我们注册了那个 command,执行 command 会拿到当前 editor 的 url,然后进行 markdown 的 preview。

preview 的所有逻辑都集中定义在了 MarkdownPreviewEnhancedView 的实例对象中,在 command 触发时执行 initPreivew。

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

在 initWebivew 里面创建 webviewPanel,同时把 webviewPanel 保存到 map 中,key 为文档的文件路径。拿到编辑器文本来生成 html,设置到 webview.html,这样就完成了 markdown 的预览。

这条路径走通之后,我们就实现了 markdown 的预览。

但是只预览一次不行,更新文档之后需要自动更新,我们继续在 active 方法里添加事件监听:

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

监听文本修改和保存的时候,调用 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 }); } }

这里是通过 webview.postMessage 给 html 内容传递 updateHTML 的 command 消息,触发 html 内容的更新。

这样,我们就实现了 markdown 的同步刷新。

总结

vscode 里面 markdown 的预览是一个常用但实现起来并不难的功能,我们看了下 vscode-markdown-preview-enhanced 插件的源码,理清了整体的流程:

  1. 1. 通过 vscode.window.createWebviewPanel 创建 webviewPanel 来显示 html
  2. 2. html 通过 editor.document.getText() 拿到文本内容之后通过第三方包生成,设置到 webviewPanel
  3. 3. 监听 workspace.onDidSaveTextDocument 和 workspace.onDidChangeTextDocument,来拿到最新内容,之后生成 html 通过 webview.postMessage 传递 udpateHTML 的消息来更新到 webview。
  4. 4. 要注意的是,需要记录一个 map 来保存 uri.fsPath 和 webviewPanel 的对应关系,实现文本内容改变更新对应的 webview

markdown 的预览是一个常见但是并不难的需求,也比较适合入门 vscode 插件的开发,希望这篇文章能够帮大家理清思路。

原文来自:https://mp.weixin.qq.com/s/hLqx5RXxCHNfRE9ahvBsxg
本文地址:https://www.linuxprobe.com/vscode-markdown.html编辑:姜 一 一,审核员:逄增宝
Linux命令大全:https://www.linuxcool.com/

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
讣告!于2024年3月28日去世!

讣告!于2024年3月28日去世!

莫问先生
2024-04-22 20:51:44
标准3D!赫伯特-琼斯三分7中4高效得到18分2板1助

标准3D!赫伯特-琼斯三分7中4高效得到18分2板1助

直播吧
2024-04-25 12:11:47
下雨天,女同事在我家留宿一晚,半夜她却突然躺在我旁边

下雨天,女同事在我家留宿一晚,半夜她却突然躺在我旁边

缓缓说事吖
2024-04-25 07:05:50
光刻机“闹剧”结束了!荷兰正式宣布,人民日报的呼吁该重视了

光刻机“闹剧”结束了!荷兰正式宣布,人民日报的呼吁该重视了

疯狂小菠萝
2024-04-23 21:04:18
荒唐透顶!清华大学院长阎学通竟宣称:投降是维护和平的最快途径

荒唐透顶!清华大学院长阎学通竟宣称:投降是维护和平的最快途径

蝴蝶花雨话教育
2024-04-23 10:56:19
勇士铁三角正式解散! 克莱今夏远赴湖人, 库里加盟西部新贵!

勇士铁三角正式解散! 克莱今夏远赴湖人, 库里加盟西部新贵!

欧雄谈生活
2024-04-25 05:33:21
1700亿打了水漂?菲律宾“急召”中方大使,我方态度让人害怕

1700亿打了水漂?菲律宾“急召”中方大使,我方态度让人害怕

星辰故事屋
2024-04-24 13:49:16
曝缅北亨利集团女董事长去世,因病赴西班牙医治无果,评论区炸锅

曝缅北亨利集团女董事长去世,因病赴西班牙医治无果,评论区炸锅

小眉小眼
2024-04-24 11:02:53
北方人没有野餐权

北方人没有野餐权

穷游网
2024-04-24 12:04:12
房价崩溃预警!专家惊人预测:明年或将迎来20%-40%的疯狂下跌!

房价崩溃预警!专家惊人预测:明年或将迎来20%-40%的疯狂下跌!

简约装修设计美图
2024-04-24 15:01:52
越闹越大!专家指责董宇辉只会空洞鸡汤话,讲解质量差,这是咋了

越闹越大!专家指责董宇辉只会空洞鸡汤话,讲解质量差,这是咋了

娱乐八卦木木子
2024-04-25 11:39:08
25张难得一见的精彩照片,你没见过的世界,看后眼界都提高了

25张难得一见的精彩照片,你没见过的世界,看后眼界都提高了

农人老寓
2024-04-23 19:55:20
动真格了!干部拦春耕后续,通告已发,纪委介入:幕后故事被扒出

动真格了!干部拦春耕后续,通告已发,纪委介入:幕后故事被扒出

坦然风云
2024-04-24 15:11:44
五月天宣布鸟巢连开十场!假唱调查5个月没结果,话题冲上热搜

五月天宣布鸟巢连开十场!假唱调查5个月没结果,话题冲上热搜

萌神木木
2024-04-24 21:59:07
准90后李聪成为神舟十八号航天员,家庭背景曝光,父母职业不一般

准90后李聪成为神舟十八号航天员,家庭背景曝光,父母职业不一般

时时有聊
2024-04-24 22:02:02
柳岩美醉了

柳岩美醉了

农人老寓
2024-04-23 19:59:50
“长城炮”网红提车!30w定制版外观曝光太用心,评论区不淡定了

“长城炮”网红提车!30w定制版外观曝光太用心,评论区不淡定了

户外小阿隋
2024-04-24 21:27:33
2025世俱杯亚洲4名额已确定3席,艾因、横滨水手将争夺最后一名额

2025世俱杯亚洲4名额已确定3席,艾因、横滨水手将争夺最后一名额

直播吧
2024-04-25 09:42:24
重大消息!人社部公布6大养老金好消息,涉及重大关系!

重大消息!人社部公布6大养老金好消息,涉及重大关系!

饭桶说史
2024-04-23 22:40:53
钓鱼佬们的奇妙经历,钓鱼遇一女子问有口吗?她回答口200元

钓鱼佬们的奇妙经历,钓鱼遇一女子问有口吗?她回答口200元

解说阿洎
2024-04-23 15:50:49
2024-04-25 12:24:49
孙有匪
孙有匪
科技
1595文章数 2009关注度
往期回顾 全部

科技要闻

美总统拜登签署剥离法案 TikTok发声明反对

头条要闻

"陌生人"闯民进党记者会狂批4分多钟 民进党切断直播

头条要闻

"陌生人"闯民进党记者会狂批4分多钟 民进党切断直播

体育要闻

足智多谋的哈姆,温水里的青蛙

娱乐要闻

心疼!伊能静曝儿子曾被狗仔追到洗手间

财经要闻

先涨价再降价,特斯拉“打脸”只用20天?

汽车要闻

这灯效我能看半小时 奥迪Q6L e-tron有备而来

态度原创

家居
本地
艺术
房产
公开课

家居要闻

光影之间 空间暖意打造生活律动

本地新闻

荒野求生贝爷都得靠边站,真求生还得看留子

艺术要闻

艺术名画︱爱尔兰画家大卫·科因的刀画作品

房产要闻

涉及黄埔、番禺、增城!广州新一轮大规模征地启动

公开课

睡前进食会让你发胖吗?

无障碍浏览 进入关怀版