前端小技巧:加载并解析Markdown文档

JavaScript09

前端小技巧:加载并解析Markdown文档,第1张

移步github

作为程序猿,应该多多少少都用过Markdown,或者至少读过别人用Markdown语法写的一些文档,比如在GitHub有一个你要用的开源程序,而你又是第一回用它,那么你一般会在这个仓库的Readme里读一读开发者提供的工具说明和使用的相关信息,这部分文档一般就是用Markdown的语法写的

简单来说,Markdown就是简化阉割过的HTML,优点是语法简单高效,缺点就是HTML中一些稍微高级复杂一点的效果,比如文本居中,Markdown就无法实现,所以Markdown一般被用来写对页面排版要求不高,以文字为主的笔记和文档

如果你一开始用Markdown写了文档,想要把它放到你的网页上去,并以解析后的形式呈现

那么你有两种实现途径:

第一种方法:

第二种方法:

下面我们对 第二种方法 的实现过程进行详细的说明

上一部分已经提到,我们需要先让原始网页请求服务器中的Markdown文档

这一步需要使用AJAX(中文音译为阿甲克斯),这里先对AJAX作一个简单的科普:

对上面的脚本继续简单的说明:

那么这里有几个问题需要解答:

1. 怎么指定我想要的Markdown文档呢?

表单的显示效果如下:

点击表单中的“显示”按钮后会执行 showMarkdown( ) 函数,即 用AJAX获取Markdown文档 部分的那个函数,并且将表单选择的信息通过 form 变量传递给了 showMarkdown( ) 函数中的 f 变量

这样就通过表单设定了用户指定的Markdown文档

这里采用的是GitHub上的名为 marked 的JS框架,链接: https://github.com/markedjs/marked

要想使用这个框架,需要在html脚本的头信息中引用这个框架:

引用这个框架后就可以使用里面定义的 marked( ) 函数进行Markdown文本解析了

参考资料:

(1) 本人github笔记:AJAX学习笔记

(2) marked说明文档

marked.js是一个用JavaScript写的功能齐全的Markdown解析器和编译器。可以非常方便的在线编译Markdown代码为HTML并直接显示,并且支持完全的自定义各种格式。

使用案例:

var marked = require('marked')console.log(marked('I am using __markdown__.'))// Outputs: <p>I am using <strong>markdown</strong>.</p>

var marked = require('marked')marked.setOptions({renderer: new marked.Renderer(),gfm: true,tables: true,breaks: false,pedantic: false,sanitize: false,smartLists: true,smartypants: false})console.log(marked('I am using __markdown__.'))

<!doctype html><html><head> <meta charset="utf-8"/> <title>Marked in the browser</title> <script src="lib/marked.js"></script></head><body> <div id="content"></div> <script> document.getElementById('content').innerHTML =marked('# Marked in browser\n\nRendered by **marked**.') </script></body></html>

前言

最近笔者把之前写的文章( markdown )数据,全部同步到数据库里,来交给多端去实时渲染。在同步的过程中,却出现了一些问题。

笔者这里举个例子,让大家有所感受:

而且通过这个思路,还演化出 MDX 这个格式,大大的增强了 JSX Markdown 混合书写时的开发体验,增强了它的表现能力。

怎么做到的呢?

我们知道,原生 Markdown 功能很少,不会做任何花哨的事情,这导致它无法满足大量的场景。于是乎,大量的开发人员充分发挥了 主观能动性 ,定制了许多的 Markdown 编译器。

以著名的 Typora 为例,它就集成了 flowchart.js , mermaid 这类的图表库。我们可以在 md 里快速的生成一些简单的图表,但是遇到复杂的 case 时,可操控性还是远远弱于代码的。(这种情况,通常会在编辑器外部,先把图表做好,再把图片导出,插入 md 里)

甚至还出现了 nodeppt 这样,使用 markdown 来制作 ppt 的包。笔者曾经使用过一段时间,认为使用的场景,还是以部门内部的分享为主。受限于许多难记的语法和 md 自身的表现力,在遇到高自定义化的场景时,制作成本会远远超出 powerpoint

markdown 数据的分离存储

那么进入正题了,如何对 markdown 内不同的数据进行归类呢?

我们知道,不进行预处理的话,直接存进数据库里,无非就是一堆字符串。这堆字符串里藏着的数据,去实时处理,就是对计算机算力的浪费。

许多的 markdown 解析器,也都能够支持像 yaml json toml csv 等数据格式,此时预先把它们存进数据库就很有必要了。

怎么解析呢? 通常的做法就2字, 标记 ,在编写时,把它们用特殊的 flag 标识起来,比较通用的做法有:

--- {{code}} --- => yaml

---toml {{code}} --- => toml

---json {{code}} --- => json

这种做法本质上,和代码染色类似:

```js(染色语言) {{code}} ```

于是在标记出来之后,我们就可以非常容易的,对这堆字符串,进行 截取解析 分发给不同的解析引擎处理 了。现有的实现也很多,比如 gray-matter

但是这只解决了数据分离的问题,还有一个组件渲染的问题没有解决。

组件的原生渲染

在谈这个之前,先看看 md 是如何转成 html 的:

markded , markdown-it , unified(remark) 为例

它们无非是 把 md 先解析成 tokens/mdast , 例如:

然后再交给 html renderer 去处理的,上述的例子可以很容易的看出它的结果。

那么非转化成 html ,而去转化为原生标签怎么做呢?解决方案也有很多。

先说一下我实现的方案:

这一段字符串原封不动的存入数据库中,

然后在其他平台的场景,都去编写或者移植一个 Markdown 解析器,接着呢

这种做法本质就是 条件渲染 ,相当于一个 if 分支。

这个解决方案需要在不同的平台上,把 icebreaker-love-music 这个组件都实现一遍,并作为插件挂载在 Markdown 解析器中。

它的缺点也是很明显的:

另一种的畅想

另外一种则是我的畅想了,我们能否把组件本身,进行编译,变成一种 IL (Intermediate Language)的存在,交给各个端,进行原生渲染呢?

比如我们知道, web component 浏览器端原生支持

vue 组件可以被 @vue/web-component-wrapper 转化为 web-component

react 则有 react-web-component

那么 web-component 有可能,能依托一个像 QuickJS 这样的 Javascript Engine ,在原生环境进行实时的编译渲染吗?

以上这些就是笔者的一些愚见,如有想法,欢迎大家讨论和指点。

附录(ast的生成与转化)

syntax-tree

mdast-util-from-markdown

mdast-util-to-hast