动手写一个简单的浏览器扩展插件 - markdown文件本地预览

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/DeepLies/article/details/80898787

平时写文档的时候,一些简单的文档都用 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_startdocument_enddocument_idle,这里选取 document_end,意思是在创建完DOM之后,在还没有加载类似于图片或frame等的子资源前立即运行。
icons用于指示插件在不同场景的 sizeicon图标的所在地址路径。
其他配置项都是辅助功能,就不详细说明了,具体含义可见Manifest文件

插件脚本

上面在 manifest.jsoncontent_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"],
  }
],

markedhighlight.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.cssgithub.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.jshighlight.pack.js这两个插件。

想要在自己的 webkit内核的浏览器上(例如 Chrome、360浏览器)安装此扩展程序,可以参照 Chrome扩展及应用开发,因为我懒得上传到 Chrome网上应用商店了,所以也没有打包成 ctx文件,直接安装源文件也是可以的。

项目代码已经放在 Github上了,感兴趣的可以下载下来安装试试。

猜你喜欢

转载自blog.csdn.net/DeepLies/article/details/80898787