目录
1.前言
2.webpack.demo.js
3.markdown文档
4.fence.js
1)tokens
2):::
3)```
5.containers.js
1)markdown-it-container
2)md.use()
3)代码逻辑
4)containers小结
6.congfig.js
1)markdown-it-chain
2)slugify
3)markdown-it-anchor
4)代码逻辑
7.总结
所有章节:
- 【elementui源码解析】如何实现自动渲染md文档-第一篇
- 【elementui源码解析】如何实现自动渲染md文档-第二篇
- 【elementui源码解析】如何实现自动渲染md文档-第四篇
1.前言
之前我们看了iconInit.js和build-entry.js文件,在build:file命令里还存在node build/bin/i18n.js & node build/bin/version.js这两个命令,在这里我们就不细看了,因为我们主要目的是分析md文档如何自动渲染到页面中的,这两个文件一个是根据模版文件和json配置文件自动生成多语言的主题,另一个是自动生成elementui版本列表。我们接下来主要看webpack.demo.js这个文件,这个文件是webpack打包的配置文件。
图1
2.webpack.demo.js
这个文件里面渲染md文档的主要代码就是这段,自定义了一个md-loader,然后md-loader文件夹里面有几个文件在接下来会一一介绍他们的作用。
图2
3.markdown文档
要看懂这个md-loader文档的代码,还是要对markdown的基本语法有一些了解,在这里可以看下基本语法:Markdown基本语法
其次还有关于markdown-it解析器的api的文档,可以结合着文档和源码来看这些api:markdown-it 中文文档
4.fence.js
首先这个文件覆盖了fence默认的渲染策略。
第3行代码:在很多Markdown解析器中,如markdown-it等,默认的fence
渲染策略通常是将代码内容包裹在<pre><code>
标签中,并且根据代码块的语言类型(如javascript
),添加对应的CSS类来应用语法高亮。elementui对其进行了覆盖。
图3
图4
第6行代码,可能会疑问这个tokens是什么东西,这是markdown-it解析器实现的数据结构,具体可以看下面例子,我在自己的项目里面加了如下的md文档。首先要了解这样一个前提,解析器是会把md文档的内容转义成HTML的。如图6。
图5
图6
1)tokens
可能会有很多人不清楚tokens是什么,所以我在第7行代码打印了tokens。我截了部分内容如下三张图。比如md文档第一行“## Input 输入框”,在tokens的解析下解析为三个,可以见图7,tag为“h2”,type分别为“heading_open、inline、heading_close”三个,同时对应的nesting的三个值为[-1、0、1],分别代表开标签、内容、闭标签。
图7 图8
图9
我们主要关注图9,type为“fence”,info为“html”这个token。fence.js这个文件就是主要对type为fence的content进行渲染策略的更改。第9行第10行代码就是在判断是否这个fence是否在demo里面。如果是的话就return第12行的代码来渲染代码到文档里。可以见图10理解。
图10
2):::
:::
在此上下文中作为自定义区块的开始和结束标记。当Markdown处理器遇到这样的标签时,它会根据预定义的规则来解析和渲染这部分内容,例如将描述作为提示信息显示,并将跟随的代码片段渲染为可交互的演示组件。至于为什么要加demo这个符号,可能是因为elementui的逻辑处理需要demo这个表示符来帮助匹配代码,如代码中的正则表达式,同时也是为后面的自定义容器做的准备。
3)```
而 ``` 后面加html的原因是为了高亮,在默认的markdown语法中```后面也是可以加一些标识符的,见最后面的图11。至于高亮是怎么实现的,为什么加个slot="highlight"就能高亮,原因是elementui使用了highlight.js这个库,至于具体实现就不深究了。
图11
5.containers.js
1)markdown-it-container
markdown-it-container是一个 markdown-it 的插件,它扩展了markdown-it 的功能,允许用户自定义块级语法容器。这意味着你可以定义自己的Markdown语法(通常是一对特定标签,比如elementui的 ```html```),用于包裹内容,并对这些内容应用自定义的渲染逻辑。
2)md.use()
md.use()方法用于注册插件,以扩展Markdown解析器的功能。这个文件主要注册了三个自定义的块级容器,demo、tip、warning。只有validate函数通过后才能进入render函数渲染。
3)代码逻辑
这里的validate函数就是match含有“demo”的内容。可以同时看上面图9来帮忙理解。然后render函数里就是匹配demo后面的描述内容,比如图9里的“通过 `disabled` 属性指定是否禁用 input 组件”,然后第12行的content就是```html```里的代码块,然后将代码块放到<!--element-demo: ${content}:element-demo-->里,在后面会有用处。
4)containers小结
总的来说。
'demo' 容器:用于演示或代码示例,带有可选的描述性文本。通过正则表达式 ^demo\s*(.*)$ 验证容器开头的标签,并从描述中提取内容。渲染逻辑会在开始标签处创建一个 <demo-block> 元素,并根据需要包含描述内容和代码块。结束标签处则闭合这个 <demo-block>。
'tip' 和 'warning' 容器应该是md自带的渲染格式。可以见图13和图14。
图12
图13
图14
6.congfig.js
图15
1)markdown-it-chain
markdown-it-chain是是一个为 markdown-it 解析器设计的配置辅助库,它的主要作用在于提供一种更简洁、易读且链式的方法来配置和扩展 markdown-it。
2)slugify
slugify的作用是将给定的字符串转换成一个“slug”格式的字符串。Slug通常用于URLs、文件名等,它由字母、数字、连字符或下划线组成,不包含空格或其他特殊字符,且往往都是小写的。这对于创建友好、安全且搜索引擎优化(SEO)友好的链接非常有用。
在Markdown处理或网站开发中,slugify常常用于生成文章标题的URL友好版本,或者为自动创建的锚点、ID等提供基础。例如,将一篇名为 "基础用法" 的文章标题转换成 slug 可能会变成 ji-chu-yong-fa"。
图16
3)markdown-it-anchor
markdown-it-anchor的主要作用是在生成的HTML文档中自动为每个标题(heading)添加锚点链接。这使得用户可以轻松链接到文档内的特定部分,提升长篇文章或文档的可导航性和可用性。
在12-19行代码中是其具体配置。
- level:2表示指定从Markdown文档的第2级标题(即两个
#
号开始的标题)开始添加锚点。这意味着只有## 标题名称
及以上的标题会生成锚点。 - slugify:指定使用从 transliteration 模块导入的
slugify
函数来生成锚点的ID。这意味着标题文本将被转换成URL友好的字符串,适合用作网页链接的一部分。 - permalink:true表示启用“永久链接”功能,会在每个标题旁边添加一个可点击的小图标或链接,用户点击后可以直接跳转到该标题的链接。
- permalinkBefore:true表示设置“永久链接”图标或链接出现在标题文本之前。如果设为
false
,则链接会出现在标题之后。
图17
4)代码逻辑
第10行就是通过options.html(true).end()启用markdown中直接插入HTML的功能。
第21行就是导入并使用containers.js中定义的三个容器。
第23行就是通过config.toMd()生成配置好的markdown-it实例。
第24行就通过overWriteFenceRule()来覆盖牧人的代码块处理渲染逻辑。
7.总结
我们在下一篇再来总结index.js里做了什么操作,这里是核心代码,所以单独一篇来讲。
总的来说,在fence.js里面覆盖了默认的 fence 渲染策略,在container.js里面定义了自定义容器,最后在config.js里面配置和初始化markdown-it解析器。md-loader里的代码还是要对md文档有一些基础知识才方便看懂,我也是一边看官方使用文档,一边看elementui代码。大家一起学起来吧!