您的问题是关于在 DokuWiki 插件的 render()
方法中获取并修改指令的示例。
在 DokuWiki 中,通常 render()
方法接收的是已经处理过的数据,而不是原始指令。但是,有几种方法可以在渲染阶段获取和修改指令:
1. 使用 nest() 方法处理修改后的指令
最直接的方法是使用 nest()
方法,它允许您传入一组指令并执行它们:
public function render($mode, Doku_Renderer $renderer, $data) {
if ($mode !== 'xhtml') return false;
// 获取原始指令
$instructions = p_get_instructions($data['text']);
// 修改指令
foreach ($instructions as &$instruction) {
if ($instruction[0] === 'header') {
// 修改标题级别,例如将所有标题提升一级
$instruction[1][1] = max(1, $instruction[1][1] - 1);
}
}
// 使用修改后的指令
$renderer->nest($instructions);
return true;
}
这个示例中,我们获取了原始指令,修改了所有标题的级别,然后使用 nest()
方法执行修改后的指令。
2. 创建自定义渲染器
另一种方法是创建一个自定义渲染器,它可以拦截和修改指令的执行:
class MyCustomRenderer extends Doku_Renderer_xhtml {
public function header($text, $level, $pos) {
// 修改标题级别
$level = max(1, $level - 1);
// 调用父类方法
parent::header($text, $level, $pos);
}
}
public function render($mode, Doku_Renderer $renderer, $data) {
if ($mode !== 'xhtml') return false;
// 创建自定义渲染器
$customRenderer = new MyCustomRenderer();
// 获取指令
$instructions = p_get_instructions($data['text']);
// 使用自定义渲染器执行指令
foreach ($instructions as $instruction) {
if (method_exists($customRenderer, $instruction[0])) {
call_user_func_array([$customRenderer, $instruction[0]], $instruction[1] ?: []);
}
}
// 将自定义渲染器的输出添加到原始渲染器
$renderer->doc .= $customRenderer->doc;
return true;
}
3. 实际示例:bin/render.php
DokuWiki 的 bin/render.php
命令行工具提供了一个实际的例子,展示了如何获取指令并将其传递给渲染器: render.php:51-60
在这个示例中,p_get_instructions($source)
获取指令,然后将它们传递给 p_render()
函数进行渲染。
4. 使用 p_render() 函数
p_render()
函数是 DokuWiki 中处理指令渲染的核心函数: parserutils.php:688-693
您可以在自己的插件中使用类似的方法:
public function render($mode, Doku_Renderer $renderer, $data) {
if ($mode !== 'xhtml') return false;
// 获取指令
$instructions = p_get_instructions($data['text']);
// 修改指令
foreach ($instructions as &$instruction) {
// 修改指令...
}
// 创建一个临时渲染器
$tempRenderer = new Doku_Renderer_xhtml();
// 执行修改后的指令
foreach ($instructions as $instruction) {
if (method_exists($tempRenderer, $instruction[0])) {
call_user_func_array([$tempRenderer, $instruction[0]], $instruction[1] ?: []);
}
}
// 将临时渲染器的输出添加到原始渲染器
$renderer->doc .= $tempRenderer->doc;
return true;
}
5. 使用 nest() 方法的实际实现
DokuWiki 的 nest()
方法是专门设计用来执行指令的: renderer.php:136-144
这个方法遍历指令数组,并对每个指令调用相应的渲染器方法。
总结
在 DokuWiki 的 render()
阶段修改指令的关键步骤是:
- 获取指令(通常使用
p_get_instructions()
) - 修改指令数组
- 使用
nest()
方法或手动遍历执行修改后的指令
这种方法允许您在渲染阶段完全控制内容的呈现方式,而不仅仅是修改最终的 HTML 输出。
注意事项
- 修改指令可能会影响缓存,您可能需要禁用缓存(
$renderer->info['cache'] = false;
) - 确保您的修改不会破坏文档结构(例如,确保开始和结束标签匹配)
- 不同的渲染模式(如 xhtml、metadata 等)可能需要不同的处理方式