zh CN DslContext - chiba233/yumeDSL GitHub Wiki
DslContext
DslContext 是一个很小的上下文对象,把"当前用什么语法"和"怎么生成 token ID"打包在一起。 解析器在调用你的 handler 时会把它作为最后一个参数传进来——你只需要原样转发给工具函数就行。
它在哪里出现
createParser / parseRichText
│
│ 解析时内部创建 DslContext
│ { syntax, createId }
│
▼
你的 handler(tokens, ctx) ← ctx 就是 DslContext
│
│ 转发 ctx
▼
parsePipeArgs(tokens, ctx) ← 用 ctx.syntax 知道管道符是什么
materializeTextTokens(tokens, ctx) ← 用 ctx.syntax 知道怎么反转义
createTextToken(value, ctx) ← 用 ctx.createId 生成 ID
接口
interface DslContext {
syntax: SyntaxConfig; // 当前生效的语法配置
createId?: CreateId; // token ID 生成器(可选)
}
就两个字段,很轻。打印出来长这样:
// 在 handler 里 console.log(ctx) 看到的东西:
{
syntax: {
tagPrefix: "$$",
tagOpen: "(",
tagClose: ")",
tagDivider: "|",
endTag: ")$$",
rawOpen: ")%",
blockOpen: ")*",
rawClose: "%end$$",
blockClose: "*end$$",
escapeChar: "\\",
escapableTokens: ["%end$$", "*end$$", ")$$", ")%", ")*", "(", ")", "|", "\\"],
},
createId: [Function], // 生成 token ID 的函数
}
就是告诉你的回调"当前用什么语法符号"和"怎么生成 ID"。
什么时候需要关心它
| 场景 | 要做什么 |
|---|---|
| 写 handler(最常见) | 把 ctx 原样转发给 parsePipeArgs 等工具函数就行 |
| 在解析之外调工具函数 | 自己构造一个:{ syntax: createSyntax(), createId: ... } |
| 用 createParser 且没有自定义 handler | 完全不用管 |
| 旧 handler 没接 ctx 参数 | 能跑(JS 会忽略多余参数),但管道分割和转义会用模块默认值。换了自定义语法就会出问题——加一行 ctx 参数就好 |
ctx 到底要不要写
永远写。 不管你的回调里用不用得到 ctx,都声明它:
// 底层 TagHandler
inline: (tokens, ctx) => ...
raw: (arg, content, ctx) => ...
// createPipeHandlers 回调
inline: (args, ctx) => ...
raw: (args, content, ctx) => ...
原因:
- ctx 由框架保证提供,声明它没有任何额外开销
- 未来大版本会把 ctx 改为 required,现在写了就不用改
- 并发环境(如 SSR)下,显式传 ctx 可以避免依赖模块级环境状态,确保每个请求独立
写 handler 时的标准写法
link: {
inline: (tokens, ctx) => {
const args = parsePipeArgs(tokens, ctx); // ← 转发 ctx
return {type: "link", url: args.text(0), value: args.materializedTailTokens(1)};
},
}
在解析之外使用
const ctx: DslContext = {
syntax: createSyntax(),
createId: (draft) => `demo-${draft.type}`,
};
const args = parsePipeTextArgs("ts | Demo", ctx);
省略 ctx 时的兜底链
工具函数在没收到 ctx 时按以下优先级兜底:
- 语法相关函数(分割、转义等)→
getSyntax()(模块默认语法) - createToken → 模块级计数器
rt-0, rt-1, ...
只要你没改默认语法,不传 ctx 也不会出错。但未来的大版本会把 ctx 变成必传参数,建议现在就养成转发的习惯。