{
  "lead": "Markdown 用 # 表示标题、* 表示强调、- 表示列表，写起来像纯文本，又能转换成排版好的 HTML。这个页面的转换器完全手写：先按行识别出标题、列表、引用、代码块、表格这些「块」，再在每个块里解析强调、链接、行内代码这些「行内」标记。渲染结果直接放进页面，所以另一个重点是安全：用户输入里的任何 HTML 都不会被执行。",
  "formulas": [
    [
      "文本 → 块结构 → 行内标记 → HTML",
      "两遍解析：块级决定「这一段是什么」，行内级决定「这几个字怎么显示」"
    ]
  ],
  "terms": [
    [
      "块级解析",
      "逐行扫描：以 # 开头的是标题，``` 开头的是代码块（一直读到结束标记），> 开头的是引用（去掉 > 后递归解析里面的内容），- 或 1. 开头的是列表项（缩进的后续行属于这一项，同样递归解析），带 | 且下一行是 |---| 分隔行的是表格，其余连续的行合成段落。列表项之间有空行时是「松散」列表，每项包在 &lt;p&gt; 里。"
    ],
    [
      "强调的配对",
      "星号和下划线的规则比看起来复杂：<code>2 * 3 * 4</code> 里的星号不是强调，<code>snake_case_name</code> 里的下划线也不是。解析器按 CommonMark 的规则判断每一串 * 或 _ 能否开始、能否结束强调（看它前后是空白、标点还是字母），再用一个栈从左到右配对，两个配成 &lt;strong&gt;，一个配成 &lt;em&gt;，所以 <code>***both***</code> 会得到嵌套正确的 &lt;em&gt;&lt;strong&gt;。"
    ],
    [
      "防 XSS",
      "输出用 innerHTML 插入页面，所以绝不能让输入变成可执行的代码。三条措施：所有文字中的 &amp; &lt; &gt; &quot; &#39; 一律转义，原始 HTML 只会原样显示；属性值统一用双引号包住并转义，标题、图片说明里的引号无法「跳出」属性；链接和图片地址只允许 http、https、mailto 和相对地址，判断前先去掉空白和控制字符，所以 <code>JaVaScRiPt:</code>、<code>java&lt;Tab&gt;script:</code> 都会被替换成 #。点「XSS 测试」可以看到常见攻击写法的输出。"
    ],
    [
      "代码高亮",
      "带语言标注的代码块（rust、js、python、bash）会被切分成关键字、字符串、注释、数字和类型名，分别套上不同颜色的 &lt;span&gt;。这是按字符扫描的简单分词，不做完整的语法分析。"
    ],
    [
      "支持的范围",
      "实现的是 CommonMark 的常用子集加上 GFM 的表格、删除线和任务列表。不支持：原始 HTML 透传（出于安全考虑）、「下划线式」标题（=== / ---，--- 会被当作分隔线）、缩进式代码块、脚注和引用式链接。"
    ]
  ],
  "flow": [
    [
      "js",
      "每次输入（每帧最多一次）JS 调用 <code>md_render(文本)</code>。"
    ],
    [
      "rust",
      "Rust 解析出块结构树，对每个块做行内解析，拼接成 HTML 字符串返回。异常输入（上千个未闭合的 [、几百层嵌套的引用）也有线性时间和递归深度的保护。"
    ],
    [
      "js",
      "JS 把结果放进预览区；也可以切换成查看 HTML 源码。"
    ]
  ],
  "perf": [
    "实测（桌面 Chromium）：示例文档（约 1 KB）每次渲染 0.1~2ms，完全跟得上打字；「测速」把示例重复成约 1 MB，最快约 30ms，约 32 MB/s。",
    "这个 .wasm 约 72 KB，是本项目较大的一个：大量的字符串处理和格式化代码占了体积。",
    "测试包括每种语法的逐字输出对比、一组 XSS 攻击用例、3000 份由特殊字符和中文随机拼成的文档（检查不会崩溃、不会产生渲染器以外的标签），以及几种会让简单实现变成平方级耗时的病态输入：成千上万个未闭合的 [、不闭合的链接地址（「[a](xxx」重复上万次）、长度依次递增的反引号串。链接地址最长扫描 2048 个字符，反引号串的位置预先建好索引，所以耗时始终和输入长度成正比。"
  ],
  "src": [
    [
      "crates/tools/markdown/src/block.rs",
      ""
    ],
    [
      "crates/tools/markdown/src/inline.rs",
      ""
    ],
    [
      "crates/tools/markdown/src/escape.rs",
      ""
    ],
    [
      "www/markdown/index.js",
      ""
    ]
  ]
}
