在 DokuWiki 中,解析过程会生成一系列中间指令(instructions),这些指令随后被传递给渲染器来生成最终输出。这些指令是 Parser 和 Renderer 之间的桥梁。
指令的基本结构
DokuWiki 的指令通常是一个数组,包含三个元素:
- 指令名称(如
p_open
、cdata
等) - 参数数组
- 文本在原始文档中的位置
从代码中可以看到,指令是通过 addCall
方法添加的: handler.php:54-58
常见的中间过程指令
通过分析代码和测试文件,我们可以看到 DokuWiki 使用的主要指令类型:
1. 文档结构指令
document_start
- 文档开始document_end
- 文档结束p_open
- 段落开始p_close
- 段落结束section_open
- 章节开始section_close
- 章节结束
从测试文件中可以看到这些指令的使用: parser_media.test.php:93-100
2. 文本内容指令
cdata
- 普通文本内容header
- 标题文本linebreak
- 换行
3. 格式化指令
strong_open
/strong_close
- 粗体emphasis_open
/emphasis_close
- 斜体underline_open
/underline_close
- 下划线monospace_open
/monospace_close
- 等宽字体subscript_open
/subscript_close
- 下标superscript_open
/superscript_close
- 上标deleted_open
/deleted_close
- 删除线
4. 链接和媒体指令
internallink
- 内部链接externallink
- 外部链接internalmedia
- 内部媒体externalmedia
- 外部媒体
例如,媒体指令的格式如下: parser_media.test.php:154
5. 表格指令
table_open
/table_close
- 表格开始/结束tablerow_open
/tablerow_close
- 表格行开始/结束tablecell_open
/tablecell_close
- 表格单元格开始/结束tableheader_open
/tableheader_close
- 表格标题单元格开始/结束
6. 列表指令
listu_open
/listu_close
- 无序列表开始/结束listo_open
/listo_close
- 有序列表开始/结束listitem_open
/listitem_close
- 列表项开始/结束
7. 代码和引用指令
code
- 代码块file
- 文件内容quote_open
/quote_close
- 引用块开始/结束
8. 插件指令
plugin
- 插件调用,通常包含插件名称、状态和数据 handler.php:292-304
指令的处理流程
- 解析阶段:Parser 解析文本并生成指令 parserutils.php:219-234
- 缓存阶段:指令可以被缓存以提高性能 CacheInstructions.php:37-44
- 渲染阶段:Renderer 处理指令并生成输出
嵌套指令处理
DokuWiki 支持嵌套指令,通过 nest()
方法处理:
特殊处理器
DokuWiki 使用特殊的处理器来处理某些类型的内容:
- Block 处理器:处理块级元素
- Lists 处理器:处理列表结构
- Table 处理器:处理表格
- Quote 处理器:处理引用块
- Nest 处理器:处理嵌套结构
这些处理器通过 CallWriter
接口来管理指令流: handler.php:42-44
示例:完整的解析流程
以下是一个简单的 Markdown 表格被解析成指令的示例:
| 表头1 | 表头2 |
| ----- | ----- |
| 内容1 | 内容2 |
可能生成的指令序列:
[document_start, [], 0]
[p_open, [], 0]
[table_open, [], 0]
[tablerow_open, [], 0]
[tableheader_open, [1, 'left'], 0]
[cdata, ['表头1'], 2]
[tableheader_close, [], 7]
[tableheader_open, [1, 'left'], 8]
[cdata, ['表头2'], 10]
[tableheader_close, [], 15]
[tablerow_close, [], 16]
[tablerow_open, [], 17]
[tablecell_open, [1, 'left'], 17]
[cdata, ['内容1'], 19]
[tablecell_close, [], 24]
[tablecell_open, [1, 'left'], 25]
[cdata, ['内容2'], 27]
[tablecell_close, [], 32]
[tablerow_close, [], 33]
[table_close, [], 34]
[p_close, [], 34]
[document_end, [], 34]
Notes
DokuWiki 的中间过程指令是一个灵活的系统,允许将解析和渲染分离。这些指令形成了一种中间表示,可以被缓存并用于不同的渲染目标(如 HTML、纯文本等)。
指令系统的核心在于 handler.php
文件中的 addCall
方法,它将指令添加到指令流中。每个指令包含一个名称、参数数组和位置信息。
在开发 DokuWiki 插件时,了解这些中间指令非常重要,因为插件通常需要生成或处理这些指令。