平时写文档的时候,一些简单的文档都用 markdown
来写,编辑工具自然是随便用的,记事本、vs code或者专门的 md编辑器都可以,但是想要预览的时候,却有一定的限制,例如我想用 vs code预览 md文件,就必须装一个专门的插件,或者干脆就要开启一个 md编辑器才行,而我的本意其实仅仅是想预览一个写好的 md文档,不会做任何的改动,上面几种做法也不费什么事,但未免有些多余,毕竟,代码编辑器是用来写代码的,而且是本就已经开了很多个窗口了,不想再开一个了,至于专门的 md编辑器更是要开启一个编辑器,更麻烦。
而浏览器几乎是时时刻刻开着的,并且在浏览器上预览更敞亮,于是想着能不能找一个浏览器的md预览插件,结果找了半天没找到(可能是我找的方法有问题),于是还是决定自己写一个吧。
参考文档:
Chrome扩展程序的相关资料:
- Chrome扩展及应用开发(首发版)
- 360极速浏览器应用开发平台
manifest.json 配置文件
首先,一个 Chrome
插件,肯定要有 manifest.json
这个文件,此文件可以看做是插件的配置文件,插件所需加载的脚本文件、样式文件、图标、启动时刻、版本号等都在此文件中定义,一个最简单的 Chrome
插件,只需要一个 manifest.json
就足够了。
所以,在项目根目录新建 manifest.json
,写入以下基本配置:
{
"manifest_version": 2,
"name": "MdPriview",
"version": "1.0",
"description": "预览本地 markdown文件",
"content_scripts": [
{
"matches": ["file:///*.md"],
"js": ["js/index.js"],
"run_at": "document_end",
}
],
"icons": {
"16": "img/16.png",
"48": "img/48.png",
"128": "img/128.png"
},
"browser_action": {
"default_icon": {
"19": "img/16.png",
"38": "img/48.png"
},
"default_title": "MdPriview"
}
}
其中,content_scripts
配置项中,matches
属性用于指示插件在什么类型的页面上运行,可选值参照模式匹配。
本文所要解析是本地的 mardown
文件,所以选用 file:///*.md
,意思是只有当前页面的访问协议为 file
,后缀为 .md
的时候,才启动插件。
js
配置了插件在运行的时候,向页面注入的脚本所在路径,此配置项比较重要,插件的功能大部分由脚本实现。
run_at
指示插件运行的时刻,可选值有 document_start
、document_end
、document_idle
,这里选取 document_end
,意思是在创建完DOM之后,在还没有加载类似于图片或frame等的子资源前立即运行。
icons
用于指示插件在不同场景的 size
下 icon
图标的所在地址路径。
其他配置项都是辅助功能,就不详细说明了,具体含义可见Manifest文件
插件脚本
上面在 manifest.json
的 content_scripts
配置项中定义了插件的脚本路径 js/index.js
,所以需要在根目录建立一个 js
文件夹,并且在其中创建一个 index.js
文件。 90
想要将 mardown
源文件,转化为可预览的界面形式,流程很清晰,一共分三步:
第一步,把冰箱门打开
- 读取
mardown
文件的内容 - 解析内容,将
md
文本内容转化为DOM
形式,方便定制 - 将解析好并且设置好样式的
DOM
内容替换掉原本页面上的mardown
源文本
读取 mardown
文件的内容
使用 Chrome
浏览器打开一个 markdown
文件,F12
插件源码,如下:
可以看到,浏览器实际上就是把 markdown
文件的内容当成一整段文本内容(string
),在这段文本内容外面加了一层 <pre>
标签,然后显示在<body>
元素中,<pre>
元素中的内容就是所需要获取的 md
文件内容。
读取元素内容很简单:
document.querySelector('pre').textContent
解析内容,将 md
文本内容转化为 DOM
形式,方便定制
读取到的内容是 md
源文件内容,需要将其转换为 DOM
内容,至于如何把 md
转化为 DOM
形式,也不是什么有难度的事情,功能类似于模板字符串,就是比较复杂,这里就不自己去写这个东西了,有现成的东西可用:marked
marked是一个
markdown
解析和编译器,专注于速度。
将此插件引入到插件项目中,可以直接引用此插件的网络地址 https://cdn.jsdelivr.net/npm/marked/marked.min.js
,但考虑到插件可能需要在无网络的状态下也能正常使用,所以将插件代码下载到本地,放入 /js
文件夹下,并在 manifest.json
文件中配置引入:
"content_scripts": [
{
// ...
"js": ["js/marked.min.js", "js/index.js"],
}
],
然后就可以在 /js/index.js
中使用此插件了:
// marked 就是引入的 `js/marked.min.js`插件暴露出来的全局方法名
"<div id='wrapper'>" + marked(document.querySelector('pre').textContent) + "</div>";
使用 marked
解析获取到的 md
文本内容,为了方便后面对其的控制,额外在解析出来的 DOM
内容外包了一层 div
这里主要功能已经实现了,不过还有个小问题,一些可以预览 makdown
文件的网站,例如 Github
,不仅可以预览正常的文本内容,甚至还可以给文本内包含的示例代码高亮显示,就像是在编辑器内阅读代码一样直观,而如果只是上一步的操作,也就只能正常显示代码内容,并不具备高亮代码的能力。
想要具备此功能,也很简单,引入另外一个插件:highlight.js
highlight.js
是一个由JavaScript
编写的语法高亮插件,适用于包括JavaScript HTML CSS C/C++ python php C# Java
在内的各种编程语言。
如何使用 highlight.js
就不多说了,其官网已经讲解地很清楚了。
和上面引入 marked
相同,将 highlight.js
插件代码下载到本地,放入 /js
文件夹下,并在 manifest.json
文件中配置引入:
"content_scripts": [
{
// ...
"js": ["js/marked.min.js", "js/highlight.pack.js", "js/index.js"],
}
],
marked
和 highlight.js
是一对常用的组合,以至于 marked
的文档上专门给出了二者配合使用的示例,本文插件想要结合这二者也很简单:
"<div id='wrapper'>" + marked(document.querySelector('pre').textContent, {
breaks: true,
highlight: function(code) {
return hljs.highlightAuto(code).value;
}
}) + "</div>";
想要 highlight.js
像期待的那样正常运行,还需要额外添加样式,在根目录下新建 /css
文件夹,并在其中创建 base.css
和 github.css
两个文件,这两个文件的名字你可以自定义,只要能正常引入就行了。
在页面中注入 css
文件:
"content_scripts": [
{
// ...
"js": ["js/marked.min.js", "js/highlight.pack.js", "js/index.js"],
"css": ["style/base.css", "style/github.css"]
}
],
将解析好并且设置好样式的DOM
内容替换掉原本页面上的 mardown
源文本
上述已经解析好了 md
文件,并设置了样式,最后一步就很简单了。
document.body.innerHTML= "<div id='wrapper'>" + marked(document.querySelector('pre').textContent, {
breaks: true,
highlight: function(code) {
return hljs.highlightAuto(code).value;
}
}) + "</div>";
还有一点小优化,由于页面在加载的时候,会首先显示未经处理的 md
内容,然后插件才会启动运行开始解析,并替换页面上的内容,这个过程会发生页面整体内容的变化,会导致页面跳动,所以我们可以先将 #wrapper
元素设置 display: none;
,在插件解析完成后,再将其显示出来:
document.body.style.display = 'block';
至此,一个 预览本地 markdown文件
的 Chrome
插件就完成了。
总结
整体项目结构如下:
/img
文件夹存放扩展的图标
/js
文件夹下存放相关脚本文件,其中 highlight.pack.js
用于高亮代码,marked.min.js
用于将 md文本转为 html
元素,index.js
则是相应的初始化代码
/style
文件夹下是样式文件, github.css
给 代码文件 设置样式,base.css
用于 其他的 html
样式.
/manifest.json
是扩展程序的配置文件。
项目很简单,需要自己写的代码就几行而已,主要是引用了 marked.min.js
和 highlight.pack.js
这两个插件。
想要在自己的 webkit
内核的浏览器上(例如 Chrome、360浏览器)安装此扩展程序,可以参照 Chrome扩展及应用开发,因为我懒得上传到 Chrome网上应用商店了,所以也没有打包成 ctx
文件,直接安装源文件也是可以的。
项目代码已经放在 Github上了,感兴趣的可以下载下来安装试试。