Rust in Everything
基于 pulldown-cmark 0.13.5

输出

解析器交出的是事件,不是 HTML。这一部分讲输出主线:事件怎么变成 HTML 文本,文档里的字符串在写出前怎么转义,以及在解析器和写出器之间怎么改写事件流。三者都只是 Iterator<Item = Event> 的消费者或适配器,换掉任何一个都不影响解析;本站就把写出器整个换成了自己的 RSX 渲染(08 在本站中)。

代码分布(按 tag v0.13.5 统计):pulldown-cmark/src/html.rs 631 行,单独发布的 pulldown-cmark-escape(tag 上是 0.11.0)只有 src/lib.rs 470 行,pulldown-cmark/src/utils.rs 181 行,pulldown-cmark/examples/ 八个文件共 515 行。0.13.4 到 0.13.5 这几处都没有改动,本站锁定的 0.13.4 输出行为与本部分相同。

  1. HTML 写出器:HtmlWriter 是一个循环加八个字段,不记嵌套;表格的 <tbody> 在表头结束时补上,脚注编号按名字首次出现分配且区分大小写,图片 alt 由 raw_text 压平子事件;三个入口函数和不对外导出的 StrWrite,write_html_io 不缓冲。
  2. 转义:正文转 &<>,属性再加两个引号,href 做百分号编码但不看协议;256 项查表的标量版和 x86_64 的 SSSE3 版在 Rosetta 下的相对快慢;HTML 事件和 javascript: 链接原样通过,净化是调用方的事。
  3. 改写事件流:map、filter、flat_map,TextMergeStream 合并被切开的文字,into_offset_iter 映射回行号,标题锚点、文末脚注、目录为什么必须缓冲;上游八个例子在 tag 上都能编译运行。
flowchart TB
  parser["Parser"] --> adapt["迭代器适配器"]
  adapt --> writer["HtmlWriter"]
  writer --> esc["pulldown-cmark-escape"]
  esc --> sink["String 或 io Write"]
  parser --> rsx["本站 RSX 渲染"]

写出器只依赖事件,不碰解析器的树;所以事件模型里每种事件带什么数据,就是这一部分能用的全部信息。紧凑列表不输出 <p>、链接引用定义早已解析完毕这类结果,都在解析阶段就定了,写出器只是照着事件写。

💬 关联讨论

发起讨论
加载中...