zmdjs

0.3.0 • Public • Published

zmd

怎么的,假装自己是 markdown 解析工具不行吗?

Overview

尝试进行 markdown 编译,直接对标 GitHub Flavored Markdown

Spec

Demo

提供一个在线演练的页面:zmd Playground,可以在上面随意调试该工具。

  • 左边部分为输入,右边部分为展示。
  • 点击 clear 按钮可清空输入的文本。
  • 点击 clear 右侧的选择框可以切换到选项设置。
  • Permalink 为当前访问链接,可以进行分享操作。
  • 点击右边部分的下拉选择框可以在预览界面、HTML 文本、和块状语法分析结果的查看。

Install

npm i zmdjs --save

Usage

const zmd = require('zmdjs')
const out = zmd('## Hello `zmd`!')
...
<script src="/path/to/zmd.js"></script>
...
<script>
  document.getElementById('content').innerHTML = zmd('## Hello `zmd`!')
</script>
...

通常来说,输出的文本会有拖尾换行,在使用时可根据实际情况进行移除。

Options

zmd(text, options)
选项 类型 默认值 说明
langPrefix String language- 代码块给定语言时的 CSS 类名前缀
headerIds Boolean true 是否给标题一个唯一标识
headerPrefix String '' 标题唯一标识的前缀
footnote Boolean true 是否开启脚注功能
highlight Function null fence 代码块高亮方法
xhtml Boolean false 使用 XHTML 语法
autourl Boolean false 是否开启链接自动识别
divClass String '' 自定义 div 的类名
ignoreBlankLine Boolean false 忽略空行
encodeURI Boolean false 是否对链接的 href 开启 encodeURI 转义
rfc3986 Boolean false 是否对链接的 href 开启 encodeURI 转义并遵循 RFC3986

options.renderer 的说明见下面的 Renderer 说明。

Markdown Extend Syntax

raw 文本

原始文本,将不做任何处理,原样进来,原样出去。

语法标识为以 {% raw %} 开头,以 {% endraw %} 结束。

raw/endraw 与边界之间支持任意数量的空格。% 符号可以省略。

定义列表

支持紧凑的定义列表。

定义列表包含一个定义标题和数个定义内容,所有部分均为单行

多行的支持暂时不做支持,后续可自行通过插件系统实现。

语法识别规则为针对定义内容进行识别,定义内容以冒号 : 开头。

多个定义内容之间的空行将被忽略。

定义内容与开头冒号之间的空格将被忽略。

有多个定义标题的,写在一起即可。

我是标题
: 我是内容1
: 我是内容2

自定义 div

使用 ::: 包裹的内容视为自定义 div。

可以在 ::: 后面跟文本表示该 div 的类名。

结束的冒号 : 可以有多个。

脚注

支持单行脚注。

脚注的语法分为两个部分,一个为定义,一个为使用。

定义的语法为块级语法,跟链接的定义类似,但是开头为 ^

使用的语法为行内语法, 表述为 [^name],其中 name 为定义过的名称,如果未进行定义,则忽略之。

序号会自动进行调整。

上标

^^ 进行包裹的行内语法。渲染器采用 sup 标签进行输出。

下标

~ 进行包裹的行内语法。渲染器采用 sub 标签进行输出。

注意,如果使用 ~~,为删除线语法。嵌套的处理未做特殊处理,请避免嵌套这两个语法。

插入

++ 进行包裹的行内语法。渲染器采用 ins 标签进行输出。

标记

== 进行包裹的行内语法。渲染器采用 mark 标签进行输出。

GFM 语法中的自动链接增强语法默认不开启。另外 HTML 代码块支持度不够理想,不建议在编写 markdown 的时候过度依赖此特性。可以通过 raw 语法进行替代。

Renderer

renderer 可以进行渲染器的自定义,以下代码示例演示了一个自定义标题渲染方法:

const renderer = new zmd.Renderer()
// const _heading = renderer.heading
renderer.heading = function (text, level, slug) {
  return '<h'
    + level
    + (slug ? ' id="' + slug + '"' : '')
    + '>'
    + (slug ? '<a href="#' + slug + '" class="header-link"></a>' : '')
    + text
    + '</h'
    + level
    + '>\n'
}

zmd('## demo', {renderer})
zmd('###', {renderer})
<h2 id="demo"><a href="#demo" class="header-link"></a>demo</h2>

<h3></h3>
#4 中提到的代码块行高亮解决方案
const renderer = new zmd.Renderer()
const _fence = renderer.fence
renderer.fence = function (code, lang, meta, escaped) {
  let out = _fence.call(renderer, code, lang, meta, escaped)
  const match = meta.match(/^ *\{([^}]+)\}/) || []
  const lines = getHLines(match[1], out.split('\n').length)
  let wrap = ''

  if (lines.length > 0) {
    wrap = '<div class="code-hl">\n'
    lines.forEach(item => {
      wrap += '<div class="code-hl-item" style="top:'
      wrap += ((item - 1) * 20 + 16)
      wrap += 'px"></div>\n'
    })
    out = wrap + out + '</div>'
  }

  return out
}

function getHLines(text, lines) {
  var ret = []
  if (text) {
    text.split(/ *, */).forEach(item => {
      if (item.indexOf('-') === -1) {
        var n = +item
        if (n && n <= lines) {
          ret.push(n)
        }
      } else {
        var nn = item.split(/ *- */)
        for (var i = +nn[0]; i <= +nn[1] && i <= lines; i++) {
          ret.push(i)
        }
      }
    })
  }
  return ret
}
zmd('```js {1,2}\nvar a\nvar b\nvar c\n```', {renderer})
<div class="code-hl">
<div class="code-hl-item" style="top:16px"></div>
<div class="code-hl-item" style="top:36px"></div>
<pre><code class="language-js">var a
var b
var c
</code></pre>
</div>
当前的默认渲染器提供的方法
方法名 说明 参数 备注
hr 水平线
br 换行
heading 标题 text, level, slug 标题文本、级别、唯一标识
codeblock 块级代码块 code 代码文本
fence fence 代码块 code, lang, meta, escaped 代码文本,语言、附加信息、是否已经转义
footnote 脚注 footnotes 脚注的数组(详细说明见下方 脚注 说明)
raw 原始文本 text 文本
text 普通文本 text 文本
html HTML 文本 text 文本
table 表格 header, body 表格标题和表格主体
tablecell 表格单元格 tag, content, align 单元格标签,单元格内容、对齐方式
tablerow 表格行 content tr 的内容
div 自定义 div content, kls 内容和类名
list 列表 content, order, start, task 列表内容,是否为有序列表,列表开始值,是否包含任务列表
li 列表项 content, task 列表项内容,是否为任务列表
dl 定义列表 content 内容
dt 定义列表标题 content 内容
dd 定义列表项 content 内容
p 段落 content 内容
blockquote 块引用 content 内容
strong 着重强调 text 文本
em 普通强调 text 文本
code 行内代码块 text 文本
ins 插入 text 文本
mark 标记 text 文本
del 删除线 text 文本
sub 下标 text 文本
sup 上标 text 文本
link 链接 href, text, title 链接目标,展示文本,标题
img 图片 src, alt, title 图片源,辅助文本,标题
checkbox 复选框 checked 是否选中
paragraph 段落 p 的别名
image 图片 img 的别名

Special Thanks

特别感谢 marked 项目,当前版本的 zmd 的核心参考。编译流程基本保持跟 marked 一致。

参考项目

TODO

  • [x] 测试

    当前只针对 Slugger 对象进行了测试,具体测试文件为 test/slug.js

  • [x] 语法覆盖率

    针对 GFM 语法规范进行检验性测试,直接严格比对,未处理单引号转换和 TAB 的差异。测试文件为 test/gfm.jstest/diff.js,有先后顺序,测试结果为 test/coverage.md

  • [ ] 命令行支持
  • [ ] 插件系统

License

MIT

Dependencies (0)

    Dev Dependencies (5)

    Package Sidebar

    Install

    npm i zmdjs

    Weekly Downloads

    2

    Version

    0.3.0

    License

    MIT

    Unpacked Size

    434 kB

    Total Files

    21

    Last publish

    Collaborators

    • xovel