[v2] 语言组合 / 扩展 / 嵌入 / …
作者: LeaVerou创建于 2025年5月5日更新于 2026年9月13日
我一直在思考如何最好地处理依赖或利用其他语言的语言定义。早期的想法包括:
- https://GitHub.com/PrismJS/prism/issues/3911
- https://GitHub.com/PrismJS/prism/issues/3923
- https://GitHub.com/PrismJS/prism/issues/3916 我怀疑这些都是同一个问题的不同方面,而且良好的 API 设计将会减少每个问题的独立解决方案的数量,因此我将关闭这三个问题,以便在这里全面讨论它们。
[!NOTE] 这是一个正在进行中的工作,我会根据对这个问题的更多思考来更新它。 但在进入细节之前,有一个图示(来自 VS Code 的我们代码的真实截图):
这是 4 种语言相互嵌套!
- 外部语言是 JS(好吧, TS)
- JSDoc 在 JS 文档注释中
- Markdown 在 JSDoc 中
- JS 在 Markdown 代码块中 目前有两种类型的依赖:
- 必要(实际 ESM 导入)
- 可选(如果其他东西导入了它们,否则不使用)
还有几种使用案例如下所述。
_注意: 任何提及"现在"的内容都指的是
simplify分支(草案 PR),而不是当前的v2分支。
1. 语言使用另一种语言作为基础(例如 JavaScript 使用 C-like)
这是最直观的情况:只是简单的继承。
- 基础语言现在通过
base键而不是强制性的extend()调用来声明(我想parent或extends可能是更好的名称),并且被视为必需的依赖。 - 它被作为普通的 ESM 导入导入
- 其语法通过
base键同步解析传递给语言的grammar()函数。默认情况下,子语言定义中的任何标记会覆盖基础语言中的标记。如果需要不同的行为,则有以下逃逸途径:$merge进行某些标记的深度合并$insertBefore在另一个之前插入某些标记$insertAfter在另一个之后插入某些标记$insert是$insertBefore/$insertAfter的简写版本,更适合一次性插入,因为位置通过$before/$after在其值内指定- 上述所有操作都合并为一个单一补丁,并在尽可能晚的时间应用
- 我仍在争论这是否是一个好主意。
通常情况下,基础语言本身是有用的。例如,
clike并不是仅仅为了使其子语言更加 DRY 而创建的,而是为了在需要突出 C-like 语言时作为一种退路,而这种语言没有专门的语言定义(尽管在 Prism 首次推出时只有 5 种语言时,这种情况更为重要)。 如今,也存在一些语言定义仅仅是为了使其他语言定义更加 DRY 的原因而存在(例如javadoclike)。
内容来源: PrismJS/prism