Skip to content

Latest commit

 

History

History
118 lines (79 loc) · 6.3 KB

File metadata and controls

118 lines (79 loc) · 6.3 KB

Compatibility Report: markdown-it-ts vs markdown-it

中文概要

本文说明 markdown-it-ts 与上游 markdown-it 的兼容性合同、主要差异、迁移风险和验证清单。

markdown-it-ts 的目标是兼容 markdown-it 的公开 API,而不是兼容上游包里的每一个私有实现细节。

兼容性合同

Stable

这些接口属于明确支持的兼容目标:

  • 主解析/渲染 API:parseparseInlinerenderrenderInlinerenderAsync
  • 与 markdown-it 行为对齐的公开选项和 preset 风格用法
  • Token shape 和常见 token mutation helper
  • Ruler / CoreRuler / BlockRuler / InlineRuler 风格的规则注册
  • md.renderer.rules 渲染规则扩展
  • 遵循 function plugin(md, options) 模式的常见插件 hook
  • 本包文档化并通过 exports 发布的稳定子路径

Best Effort

这些场景会尽量验证,但迁移时仍需要用户在自己的 workload 上测试:

  • 不依赖上游私有文件的第三方 markdown-it 插件
  • 在 ESM 项目中通过 Node 或 bundler interop 加载的 CJS 插件
  • 使用 renderAsync 的异步 renderer/highlight 集成
  • 面向大输入或 append-heavy 编辑器场景的 stream、chunked、unbounded、editable-buffer API(通过 markdown-it-ts/experimental 使用;部分 helper 也有显式子路径:markdown-it-ts/stream/buffermarkdown-it-ts/stream/chunkedmarkdown-it-ts/stream/debouncedmarkdown-it-ts/support/chunk_recommend

Unsupported

这些模式不属于兼容性承诺:

  • 直接导入上游私有路径,例如 markdown-it/lib/...
  • 依赖未文档化的内部 parser state shape 或规则实现细节
  • 在 CommonJS 中直接 require('markdown-it-ts'),而不使用动态 import()
  • Node.js 18 以下运行时
  • 假设 chunked 或 streaming API 在尚未看到后续全局定义时,也一定能产出与完整 parse 完全一致的中间结果

主要差异

  • 语言与打包markdown-it-ts 使用 TypeScript 实现,并以 ESM-only package exports 发布。
  • 运行时:要求 Node.js >= 18。
  • 子路径导出:请使用文档化的 markdown-it-ts/... exports,不要依赖上游私有路径。
  • Renderer 集成:主入口包含 renderrenderInlinerenderAsyncrenderer 和 advanced withRenderermarkdown-it-ts/plugins/with-renderer 也保留给 custom/core-shaped instance。
  • 大输入 APIstreamchunkedParseStreamBufferUnboundedBufferEditableBuffer 是本包扩展能力,只适合特定输入形态,并有独立正确性边界;它们从 markdown-it-ts/experimental 导入,部分 helper 也可从 markdown-it-ts/stream/buffermarkdown-it-ts/stream/chunkedmarkdown-it-ts/stream/debouncedmarkdown-it-ts/support/chunk_recommend 导入,不从 1.0 根入口导出。

导入示例

ESM

import markdownIt from 'markdown-it-ts'
import emoji from 'markdown-it-emoji'

const md = markdownIt({ html: true })
md.use(emoji)

console.log(md.render('# Hello'))

CommonJS Application

markdown-it-ts 是 ESM-only。CommonJS 项目里使用动态 import:

async function main() {
  const { default: markdownIt } = await import('markdown-it-ts')

  const md = markdownIt({ html: true })
  console.log(md.render('# Hello'))
}

main().catch((error) => {
  console.error(error)
  process.exitCode = 1
})

插件兼容性说明

大多数使用 markdown-it 公开 API 的插件,在替换 import 后应当可以工作。当前 CI 的插件矩阵覆盖 abbreviation、container、definition list、emoji、footnote、inline hook、ins、mark、sub、sup 等常见插件。

以下插件需要重点验证:

  • 导入 markdown-it/lib/... 等上游内部路径
  • patch 未文档化的 state 对象
  • 假设 CommonJS-only 加载方式
  • 在 streaming/chunked parsing 期间修改 renderer 或 parser state

Stream 与 Chunked 正确性

Markdown 不总是 chunk-local。Reference definition、footnote definition、abbreviation definition,以及插件自定义全局状态,都可能影响前文内容。

chunkedParse() 和完整字符串的 unbounded parsing 默认对已知全局状态语法采用 correctness-first fallback。Iterable/sink parsing 更偏 stream 场景,可能在看到后续定义前就提交前面的 chunk;如果需要严格 full-parse parity,请使用完整字符串解析,或避免过早 flush。

关闭 global-state fallback 属于性能模式,可能产生与 full parse 不同的输出。

迁移清单

  1. 将导入改为 ESM import,或在 CommonJS 中使用动态 import()
  2. 用业务 fixture 同时对比旧版和新版渲染输出。
  3. 验证所有第三方插件,尤其是依赖上游私有路径的插件。
  4. 检查安全敏感行为:html、link validation、highlight 输出,以及外部 sanitization。
  5. 优先使用普通 md.parse / md.render。只有大输入或 append-heavy workload 才引入 stream/chunk API。
  6. 如果关注性能,请带上 docs/perf-latest.json 记录的 Node、CPU、OS、依赖版本、commit 等元数据复现 benchmark。

English Summary

markdown-it-ts targets the markdown-it public API, not every private upstream implementation detail.

  • Stable: main parse/render APIs, Token shape, ruler APIs, renderer rules, common public plugin hooks, and documented stable package exports.
  • Best effort: third-party plugins that avoid private upstream files, CJS plugin interop from ESM, async render/highlight integrations, and large-input stream/chunk/editable APIs imported from markdown-it-ts/experimental; selected helpers also have explicit subpaths: markdown-it-ts/stream/buffer, markdown-it-ts/stream/chunked, markdown-it-ts/stream/debounced, and markdown-it-ts/support/chunk_recommend.
  • Unsupported: private upstream imports such as markdown-it/lib/..., undocumented internal state dependencies, direct CommonJS require('markdown-it-ts'), Node.js < 18, and assuming stream/chunk output is always equivalent before future document-level definitions are known.

Use normal md.parse / md.render first. The stable default path keeps plugin/custom-rule instances on plain full parse unless chunking is explicitly enabled. Adopt stream/chunk APIs only for large-input or append-heavy workloads, and validate output against full parse when exact parity matters.