解决markdown-it-prism未能正确加载Languages的BUG
在hexo博客同步至csdn - 木然轩一文中,我提到了prismjs
在尝试渲染C++代码块时不能正确加载node_modules/prismjs/components/prism-cpp.js
。于是,我在prismjs
的GitHub项目上提交了Pull Request:cpp extend clike by jlice · Pull Request #1914 · PrismJS/prism。不过,prismjs
的项目维护者却告诉我,这锅prismjs
不背,是markdown-it-prism
自己的问题。
其实在提交这个Pull Request时我也觉得奇怪,prismjs
的用户基数那么大,而C++也是非常常见的语言,要是出现这种问题早就解决了。不过,我的确是在一顿Debug后找到了出错的位置,但 这个出错的位置是错误的果,未必是错误的因。
prismjs
prismjs
是一个代码块高亮的库,其作用和highlight.js
差不多,有点像Python里的Pygments
。大致看了下prismjs
的源码,感觉主要就是用正则表达式描述了各编程语言的文法,然后做词法分析,对各种类型的token应用相应的样式。下面是prismjs
的目录结构:
components
目录是对各语言的定义,plugins
是一些功能增强插件,themes
就是主题了。例如,prism/components/prism-cpp.js中就定义了C++的文法:
Prism.languages.cpp = Prism.languages.extend('c', {
'class-name': {
pattern: /(\b(?:class|enum|struct)\s+)\w+/,
lookbehind: true
},
...
它扩展自C。类似地,在prism/components/prism-c.js中定义了C的文法:
Prism.languages.c = Prism.languages.extend('clike', {
...
而clike没有扩展自别的语言,应该在prism
作为一种基本的语言类型。
在Debug的过程中,我在prism/components/prism-core.js中发现了DFS递归查找语言定义。心想,都有DFS了,怎么就不能正确加载呢,路径都没问题呀。
loadPrismLang
经prismjs
维护者提示,找到了问题之所在。位于markdown-it-prism/index.js的loadPrismLang函数内:
require('prismjs/components/prism-' + lang);
对于C++,lang
的值应是cpp
。这里它就直接调用prismjs/components/prism-cpp这个模块了,可根据前面的分析,它extend自prism-c,而prism-c又extend自prism-clike。因此,像这样直接调用会出错的,应该使用prismjs
里提供的loadLanguages
,它可以自动处理依赖关系。在prismjs
的官方文档上也提到了这一点:
这个函数定义在prism/components/index.js。于是乎,就给markdown-it-prism
提交了个Pull Request。
如果通过npm
安装markdown-it-prism
,可以发现index.js
位于build
目录下,而markdown-it-prism
的GitHub项目里,index.js
位于项目的根目录,而且这两个index.js
的内容不一样。通过查看项目下的package.json,可以了解到项目是使用babel编译的,用mocha来测试的。编译、测试一下,一切OK。结果GitHub用TravisCI跑一下,在老版本Nodejs上未能通过测试:
不过,这并不代表修改是错误的,也许是测试用例没有更新。
Pull Request
markdown-it-prism
项目的维护者Merge了我的Pull Request:
而且,也添加了我的测试用例。