markdown-it 源码分析及插件编写:parse 和 token(1/3)
markdown-it 是一个广受欢迎的 JavaScript Markdown 解析库,它提供了强大的源码插件系统,简化了 Markdown 转换为 HTML 的源码过程。然而,源码其文档相对晦涩,源码初学者可能难以理解如何编写插件。源码加密工具源码本文旨在通过阅读 markdown-it 的源码源码,为想要开发插件的源码读者提供一些启示。首先,源码让我们简要了解一下 markdown-it 的源码基本使用方法。
使用 markdown-it 的源码核心方法包括 `render` 和 `parse`。`render` 方法直接将 Markdown 转换成 HTML,源码而 `parse` 方法则将 Markdown 转换成 token,源码之后使用 `renderer.render` 方法将这些 token 转换成 HTML。源码实际上,源码`render` 方法就是调用了 `parse` 和 `renderer.render` 的组合。
为了更清晰地解释这些流程,本文将分为两部分:Markdown 解析为 token 和 token 转换为 HTML。在深入源码之前,建议读者先尝试使用 markdown-it,以便在阅读过程中更好地理解代码。
下面,我们开始阅读 markdown-it 的源码,建议读者在阅读本部分内容前,先自己动手试用 markdown-it,这样能帮助你更好地理解下面的内容。强烈建议读者从官方链接克隆源码,跟随本文一起阅读。
步骤 1:无需过多解释,我们直接从步骤 2 开始。步骤 2:实例化。实例化涉及初始化几个变量并对配置进行处理。这部分对理解代码逻辑影响不大,故不详细展开。主要关注点在于初始化过程。
步骤 3:Markdown 解析为 token。在深入分析具体代码之前,先看下生成的 token 是什么样子。我们将通过一个例子来展示 parse 后的 token 结构。
在分析源码前,js promise源码不妨先看看 parse 后的 token 大致是什么样。例如,一个简单的 Markdown 文本通过 parse 后会生成一个包含多个 token 的数组,每个 token 包括类型、内容等信息。你可以在官方文档中查看完整的 token 内容。查看 token 的过程,建议点击右上角的 debug 功能。
token 包含头尾两个元素,中间的 token 通常表示 Markdown 的某一特定元素,如文本、链接、列表等。这些中间的 token 与特定的类型绑定,比如 inline 类型。inline 类型的 token 通常包含子 token,这些子 token 用于处理 Markdown 语法中更复杂的元素,例如标记、列表等。
下面,我们将重点讲解 parse 的核心规则。解析流程主要分为两步:初始化状态和应用预定义规则。状态初始化用于保存解析过程中的信息,而规则应用则负责将 Markdown 转换成 token。在源码中,解析流程涉及核心规则,包括 block 规则和 inline 规则。
block 规则是处理 Markdown 中的块元素,如段落、列表等。inline 规则则关注处理 Markdown 中的内联元素,如文本、超链接等。通过理解这些规则,可以深入理解 markdown-it 如何将复杂的 Markdown 文本解析为结构化的 token。
在解析流程中,block 规则会调用特定的函数来处理每行文本,而 inline 规则则应用于每一个需要解析的 token。理解这些规则有助于编写自定义插件,闲聊app源码从而扩展 markdown-it 的功能。
深入理解 markdown-it 的源码需要耐心和细致,本文仅提供了一个大致的框架和关键点的概述。希望本文能为正在开发或计划开发 markdown-it 插件的读者提供一些启示。在后续的篇章中,我们将分别探讨 markdown-it 的渲染流程和插件编写技术,敬请关注。本文由 GitHub 上的 WPL/s 发布。
.md文件是什么?.md如何打开?-搜狗输入法
搜狗输入法,作为业界领先的智能输入解决方案,凭借其强大的词库、智能化的组词功能和用户友好的界面设计,赢得了亿万用户的青睐。无论是手机还是电脑,搜狗输入法都能提供快速、准确的输入体验。现在您可以轻松下载最新版本的搜狗输入法,享受极致的输入新体验。/
可能有些朋友会看到以md为结尾的文件,但是不知道用什么打开。下面就来说一下.md文件如何打开,markdown文件用什么打开。
1、首先来普及一下什么是md文件, md全称markdown,markdown也是一种标记语言。
2、md文件其实可以用常用的文本编辑器都可以打开,例如记事本、EditPlus、sublime等等。
3、用记事本打开,把markdown文件拖到记事本图标上就可以打开 。
4、用 sublime打开方法也一样 ,当然也可以在文件上右击选择打开方式。
5、当然 打开markdown文件最专业的php源码收缩还是markdownPad软件 。左边是源码,右边可以看展示效果。
搜狗输入法官网不仅提供了便捷的下载通道,还为用户准备了详尽的使用指南和贴心的客户服务。通过访问 / ,您将进入一个全新的智能输入世界。无论您遇到任何问题或困惑,搜狗输入法官网都将是您最坚实的后盾。立即点击链接,开启您的智能输入之旅吧!
免费开源的在线 Markdown 编辑器
Markdown 是一种轻量级标记语言,广泛应用于文档编写和网页发布。许多人利用其简洁特性进行文章创作。对于寻求 Linux 环境下 Markdown 编辑器的用户,已有多款编辑器可供选择。然而,对于那些不希望在本地安装额外软件,或追求在线协作、发布集成、笔记同步的用户,免费开源的在线 Markdown 编辑器则成为理想选择。 在线 Markdown 编辑器通过提供一系列高级功能,简化了 Markdown 文档的创建和协作过程。它们支持实时预览、发布到各类平台、同步至云端服务等,满足用户在多种场景下的需求。 本篇文章将为你推荐五款免费开源的在线 Markdown 编辑器,它们在功能、易用性等方面各具特色,可满足不同用户的需求。 1. StackEdit StackEdit 是最受欢迎的开源在线 Markdown 编辑器之一,提供直观的用户界面和丰富功能,包括协作能力、文档同步至 Blogger、WordPress、GitHub 等平台。它支持 LaTeX 数学表达式、UML 图等 Markdown 扩展,python wxpy源码界面友好,支持离线工作,且可离线使用 Chrome 应用程序和扩展。 用户可轻松导入和导出文件,StackEdit 的 GitHub 仓库提供源代码,便于部署到服务器。 2. Dillinger Dillinger 是另一个有趣的开源在线 Markdown 编辑器,支持与 Dropbox、GitHub、Medium 等服务的链接,方便文件管理。与 StackEdit 相比,Dillinger 的界面较为简洁,不支持 LaTeX 表达式或图表扩展,适合简单在线 Markdown 编辑需求。Dillinger 也支持 Docker 容器部署,GitHub 页面提供更多技术细节。 3. Write.as Write.as 基于自由开源软件 WriteFreely 开发,允许用户在服务器上托管服务。它支持基本的 Markdown 功能,并提供了付费订阅以解锁额外功能。Write.as 与 Mastodon、ActivityPub 等社交平台集成,支持轻松关注和分享博客文章。GitHub 页面提供了更多关于 WriteFreely 的信息。 4. Editor.md Editor.md 是一个功能丰富的开源 Markdown 编辑器,支持嵌入自定义网页。它提供实时预览、GitHub 风格的 Markdown 支持,具备所见即所得的编辑器功能,支持表情符、LaTeX 表达式、流程图等。用户可选择自托管服务,GitHub 页面提供详细部署信息。 5. CodiMD CodiMD 是一个开源在线 Markdown 编辑器,提供实时协作功能。基于 HackMD 的源代码,CodiMD 提供演示实例进行测试,并支持黑暗模式,易于使用。计划在未来的发布版本中更名“HedgeDoc”。GitHub 页面提供关于 Docker/Kubernetes 部署和其他手动配置选项的信息。 6. Wri.pe Wri.pe 是一款简单开源在线 Markdown 编辑器,具有实时预览和笔记导出功能。尽管不再维护,但仍然可用。Wri.pe 的特点是用户体验友好,支持 Dropbox/Evernote 导出。对于寻求轻量级在线 Markdown 编辑工具的用户,Wri.pe 是一个不错的选择。 此外,推荐 Markdown Web Dingus 和 Markdown Journal 等工具,尽管 Markdown Journal 已停止开发,但 Markdown Web Dingus 由 Markdown 语言的创造者提供,适用于在线 Markdown 编辑和预览。 在线 Markdown 编辑器为用户提供了灵活的创作环境,支持多种功能,满足从个人到团队协作的不同需求。选择适合自己的在线 Markdown 编辑器时,应考虑功能、易用性、协作能力、平台集成以及是否需要部署至服务器等因素。markdown-it 原理解析
在《一篇带你用 VuePress + Github Pages 搭建博客》中,我们使用 VuePress 搭建了一个博客,最终的效果查看: TypeScript 中文文档。
在搭建博客的过程中,我们出于实际的需求,在《VuePress 博客优化之拓展 Markdown 语法》中讲解了如何写一个 markdown-it插件,本篇我们将深入markdown-it的源码,讲解 markdown-it的执行原理,旨在让大家对 markdown-it有更加深入的理解。
引用 markdown-it Github 仓库的介绍:
Markdown parser done right. Fast and easy to extend.
可以看出markdown-it是一个 markdown 解析器,并且易于拓展。
其演示地址为: markdown-it.github.io/
markdown-it具有以下几个优势:
使用源码解析
我们查看markdown-it 的 入口代码,可以发现其代码逻辑清晰明了:
从render方法中也可以看出,其渲染分为两个过程:
跟 Babel 很像,不过 Babel 是转换为抽象语法树(AST),而markdown-it 没有选择使用 AST,主要是为了遵循 KISS(Keep It Simple, Stupid) 原则。
Tokens
那 Tokens 长什么样呢?我们不妨在 演示页面中尝试一下:
可以看出# header生成的 Token 格式为(注:这里为了展示方便,简化了):
具体 Token 里的字段含义可以查看 Token Class。
通过这个简单的 Tokens 示例也可以看出 Tokens 和 AST 的区别:
Parse
查看 parse 方法相关的代码:
可以看到其具体执行的代码,应该是写在了./parse_core 里,查看下 parse_core.js 的代码:
可以看出,Parse 过程默认有 6 条规则,其主要作用分别是:
1. normalize
在 CSS 中,我们使用normalize.css 抹平各端差异,这里也是一样的逻辑,我们查看 normalize 的代码,其实很简单:
我们知道\n是匹配一个换行符,\r是匹配一个回车符,那这里为什么要将 \r\n替换成 \n 呢?
我们可以在阮一峰老师的这篇 《回车与换行》中找到\r\n出现的历史:
在计算机还没有出现之前,有一种叫做电传打字机(Teletype Model )的玩意,每秒钟可以打个字符。但是它有一个问题,就是打完一行换行的时候,要用去0.2秒,正好可以打两个字符。要是在这0.2秒里面,又有新的字符传过来,那么这个字符将丢失。 于是,研制人员想了个办法解决这个问题,就是在每行后面加两个表示结束的字符。一个叫做"回车",告诉打字机把打印头定位在左边界;另一个叫做"换行",告诉打字机把纸向下移一行。 这就是"换行"和"回车"的来历,从它们的英语名字上也可以看出一二。 后来,计算机发明了,这两个概念也就被般到了计算机上。那时,存储器很贵,一些科学家认为在每行结尾加两个字符太浪费了,加一个就可以。于是,就出现了分歧。 Unix系统里,每行结尾只有"",即"\n";Windows系统里面,每行结尾是"",即"\r\n";Mac系统里,每行结尾是""。一个直接后果是,Unix/Mac系统下的文件在Windows里打开的话,所有文字会变成一行;而Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号。
之所以将\r\n替换成 \n其实是 遵循规范:
A line ending is a newline (U+A), a carriage return (U+D) not followed by a newline, or a carriage return and a following newline.
其中 U+A 表示换行(LF) ,U+D 表示回车(CR) 。
除了替换回车符外,源码里还替换了空字符,在 正则中,\0表示匹配 NULL(U+)字符,根据 WIKI 的解释:
空字符(Null character)又称结束符,缩写 NUL,是一个数值为 0 的控制字符。 在许多字符编码中都包括空字符,包括ISO/IEC (ASCII)、C0控制码、通用字符集、Unicode和EBCDIC等,几乎所有主流的编程语言都包括有空字符 这个字符原来的意思类似NOP指令,当送到列表机或终端时,设备不需作任何的动作(不过有些设备会错误的打印或显示一个空白)。
而我们将空字符替换为\uFFFD,在 Unicode 中,\uFFFD表示替换字符:
之所以进行这个替换,其实也是遵循规范,我们查阅 CommonMark spec 2.3 章节:
For security reasons, the Unicode character U+ must be replaced with the REPLACEMENT CHARACTER (U+FFFD).
我们测试下这个效果:
效果如下,你会发现原本不可见的空字符被替换成替换字符后,展示了出来:
2. block
block 这个规则的作用就是找出 block,生成 tokens,那什么是 block?什么是 inline 呢?我们也可以在 CommonMark spec 中的 Blocks and inlines 章节 找到答案:
We can think of a document as a sequence of blocks—structural elements like paragraphs, block quotations, lists, headings, rules, and code blocks. Some blocks (like block quotes and list items) contain other blocks; others (like headings and paragraphs) contain inline content—text, links, emphasized text, images, code spans, and so on.
翻译一下就是:
我们认为文档是由一组 blocks 组成,结构化的元素类似于段落、引用、列表、标题、代码区块等。一些 blocks (像引用和列表)可以包含其他 blocks,其他的一些 blocks(像标题和段落)则可以包含 inline 内容,比如文字、链接、 强调文字、、代码片段等等。
当然在markdown-it中,哪些会识别成 blocks,可以查看 parser_block.js,这里同样定义了一些识别和 parse 的规则:
关于这些规则我挑几个不常见的说明一下:
code 规则用于识别 Indented code blocks (4 spaces padded),在 markdown 中:
fence 规则用于识别 Fenced code blocks,在markdown 中:
hr 规则用于识别换行,在 markdown 中:
reference 规则用于识别 reference links,在 markdown 中:
html_block 用于识别 markdown 中的 HTML block 元素标签,就比如div。
lheading 用于识别 Setext headings,在 markdown 中:
3. inline
inline 规则的作用则是解析 markdown 中的 inline,然后生成 tokens,之所以 block 先执行,是因为 block 可以包含 inline ,解析的规则可以查看 parser_inline.js:
关于这些规则我挑几个不常见的说明一下:
newline规则用于识别 \n,将 \n 替换为一个 hardbreak 类型的 token
backticks 规则用于识别反引号:
entity 规则用于处理 HTML entity,比如 { ``¯``"等:
4. linkify
自动识别链接
5. replacements
将(c)`` (C) 替换成 ©,将 替换成 ,将 !!!!! 替换成 !!!,诸如此类:
6. smartquotes
为了方便印刷,对直引号做了处理:
Render
Render 过程其实就比较简单了,查看 renderer.js 文件,可以看到内置了一些默认的渲染 rules:
其实这些名字也是 token 的 type,在遍历 token 的时候根据 token 的 type 对应这里的 rules 进行执行,我们看下 code_inline 规则的内容,其实非常简单:
自定义 Rules
至此,我们对 markdown-it 的渲染原理进行了简单的了解,无论是 Parse 还是 Render 过程中的 Rules,markdown-it 都提供了方法可以自定义这些 Rules,这些也是写 markdown-it 插件的关键,这些后续我们会讲到。
系列文章
博客搭建系列是我至今写的唯一一个偏实战的系列教程,讲解如何使用 VuePress 搭建博客,并部署到 GitHub、Gitee、个人服务器等平台。
微信:「mqyqingfeng」,加我进冴羽唯一的读者群。
如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励。
正则表达式的种元字符(metacharacters)
在探索正则表达式的世界中,我们常常会遇到种特殊的字符,它们被称为元字符(metacharacters)。这些字符在常规字符串中有着特殊的含义,如匹配特定模式或进行操作。在编写正则表达式时,如果你希望它们表示字面意义,而非其固有的功能,就需要使用转义字符(反斜杠)来"保护"它们。
在Python编程中,当你需要在字符串中使用这些元字符时,需要在它们前面加上反斜杠`\`以避免它们被解释为正则表达式的特殊操作。例如,如果你想要匹配一个点号`.`,在正则表达式中它通常表示任意字符,但如果你想匹配一个实际的点号,就需要写成`\.`。
以下是这些元字符在markdown格式中的源码列表,以供参考:
2024-11-20 14:08
2024-11-20 14:03
2024-11-20 13:19
2024-11-20 12:52
2024-11-20 12:42