10 种 DokuWiki 语法处理方法示例与总结

1. 自动嵌套语法处理(使用getAllowedTypes()和UNMATCHED状态)

这种方法通过声明允许的语法类型,让DokuWiki自动处理嵌套语法。

class syntax_plugin_example extends \dokuwiki\Extension\SyntaxPlugin {  
    public function getAllowedTypes() {  
        return ['formatting', 'substition', 'disabled', 'protected'];  
    }  

    public function handle($match, $state, $pos, Doku_Handler $handler) {  
        switch ($state) {  
            case DOKU_LEXER_UNMATCHED:  
                // 直接返回未匹配内容,系统自动处理嵌套语法  
                return ['state' => $state, 'text' => $match];  
        }  
    }  
}

2. 手动解析和渲染(使用p_get_instructions和nest)

这种方法手动创建解析上下文,适用于需要特殊处理的情况。

public function render($mode, Doku_Renderer $renderer, $data) {  
    if ($mode !== 'xhtml') return false;  

    // 手动解析内容中的嵌套语法  
    $instructions = p_get_instructions($data['content']);  
    $renderer->nest($instructions);  

    return true;  
}

3. 直接插件处理(调用其他插件的handle()方法)

这种方法直接使用其他插件的功能,避免重复实现。

public function handle($match, $state, $pos, Doku_Handler $handler) {  
    // 直接使用另一个插件处理内容  
    $plugin = plugin_load('syntax', 'markdown');  
    if ($plugin) {  
        return $plugin->handle($match, $state, $pos, $handler);  
    }  
    return false;  
}

4. 直接处理器调用(使用addCall)

这种方法直接向处理器添加指令,提供底层控制。

public function handle($match, $state, $pos, Doku_Handler $handler) {  
    // 直接添加处理器指令  
    $handler->addCall('table_open', [], $pos);  
    $handler->addCall('tablerow_open', [], $pos);  
    $handler->addCall('tablecell_open', [1, 'left'], $pos);  
    $handler->addCall('cdata', ['Cell content'], $pos);  
    $handler->addCall('tablecell_close', [], $pos);  
    $handler->addCall('tablerow_close', [], $pos);  
    $handler->addCall('table_close', [], $pos);  

    return true;  
}

5. 使用CallWriter类

这种方法创建自定义的CallWriter来处理特定的语法结构。

class MyCustomCallWriter implements CallWriterInterface {  
    protected $calls = [];  

    public function writeCall($call) {  
        // 自定义处理逻辑  
        $this->calls[] = $call;  
    }  

    public function finalise() {  
        // 完成处理  
    }  
}  

public function handle($match, $state, $pos, Doku_Handler $handler) {  
    // 设置自定义CallWriter  
    $customWriter = new MyCustomCallWriter();  
    $handler->setCallWriter($customWriter);  

    return true;  
}

6. 使用Nest类处理嵌套内容

这种方法使用专门的Nest类来处理嵌套内容。

public function handle($match, $state, $pos, Doku_Handler $handler) {  
    if ($state == DOKU_LEXER_ENTER) {  
        // 创建嵌套上下文  
        $handler->setCallWriter(new \dokuwiki\Parsing\Handler\Nest(  
            $handler->getCallWriter(),   
            'my_plugin_close'  
        ));  
    } else if ($state == DOKU_LEXER_EXIT) {  
        // 处理嵌套内容  
        $writer = $handler->getCallWriter();  
        $handler->setCallWriter($writer->process());  
    }  

    return true;  
}

7. 使用事件系统

这种方法使用DokuWiki的事件系统来修改解析过程。

class action_plugin_example extends \dokuwiki\Extension\ActionPlugin {  
    public function register(Doku_Event_Handler $controller) {  
        $controller->register_hook('PARSER_HANDLER_DONE', 'AFTER', $this, 'handleParserDone');  
    }  

    public function handleParserDone(Doku_Event $event, $param) {  
        $handler = $event->data;  
        // 修改最终的指令列表  
        // 例如添加额外的指令或修改现有指令  
    }  
}

8. 使用自定义渲染器

这种方法创建自定义的渲染器来处理特定的输出格式。

class renderer_plugin_example extends Doku_Renderer {  
    public function getFormat() {  
        return 'example';  
    }  

    // 重写渲染方法  
    public function header($text, $level, $pos) {  
        // 自定义标题渲染  
        $this->doc .= "<h$level class='custom'>$text</h$level>";  
    }  

    // 其他渲染方法...  
}

9. 组合使用多种方法

这种方法结合使用多种技术来处理复杂的语法需求。

class syntax_plugin_complex extends \dokuwiki\Extension\SyntaxPlugin {  
    public function getAllowedTypes() {  
        return ['formatting', 'substition'];  
    }  

    public function handle($match, $state, $pos, Doku_Handler $handler) {  
        switch ($state) {  
            case DOKU_LEXER_ENTER:  
                // 使用Nest处理嵌套内容  
                $handler->setCallWriter(new \dokuwiki\Parsing\Handler\Nest(  
                    $handler->getCallWriter(), 'complex_close'  
                ));  
                return ['state' => $state];  

            case DOKU_LEXER_MATCHED:  
                // 对于匹配内容,直接添加处理器指令  
                $handler->addCall('strong_open', [], $pos);  
                $handler->addCall('cdata', [$match], $pos);  
                $handler->addCall('strong_close', [], $pos);  
                return ['state' => $state];  

            case DOKU_LEXER_UNMATCHED:  
                // 对于未匹配内容,让系统自动处理嵌套语法  
                return ['state' => $state, 'text' => $match];  

            case DOKU_LEXER_EXIT:  
                // 处理嵌套内容  
                $writer = $handler->getCallWriter();  
                $handler->setCallWriter($writer->process());  
                return ['state' => $state];  
        }  
    }  

    public function render($mode, Doku_Renderer $renderer, $data) {  
        // 渲染逻辑...  
    }  
}

10. 使用Block处理器

这种方法使用Block处理器来处理块级元素,确保正确的嵌套。

public function handle($match, $state, $pos, Doku_Handler $handler) {  
    // 添加块级元素  
    $handler->addCall('p_open', [], $pos);  
    $handler->addCall('cdata', [$match], $pos);  
    $handler->addCall('p_close', [], $pos);  

    // Block处理器会自动重写这些调用以确保正确的嵌套  
    return true;  
}

总结比较

方法 优点 缺点 适用场景
1. 自动嵌套语法处理 简单,由DokuWiki自动处理 控制有限,只适用于UNMATCHED内容 容器语法,需要支持多种内嵌语法
2. 手动解析和渲染 完全控制解析过程,适用于任何状态 需要手动创建解析上下文,可能效率较低 需要特殊处理的内容,如表格单元格
3. 直接插件处理 高效,精确控制,避免重复实现 紧密耦合,依赖特定插件 扩展或使用其他插件的功能
4. 直接处理器调用 底层控制,直接生成处理器指令 需要手动管理所有指令,容易出错 需要精确控制输出结构的场景
5. 使用CallWriter类 高度自定义的处理逻辑 实现复杂,需要了解CallWriter机制 需要特殊处理指令流的场景
6. 使用Nest类 自动处理嵌套内容的开始和结束 仅适用于嵌套内容 处理复杂的嵌套结构
7. 使用事件系统 不修改原始插件即可修改解析结果 间接控制,可能与其他插件冲突 扩展现有插件的功能
8. 使用自定义渲染器 完全控制输出格式 需要实现所有渲染方法 创建新的输出格式
9. 组合使用多种方法 灵活,可以处理复杂需求 复杂,需要深入了解多种机制 复杂的语法插件
10. 使用Block处理器 确保正确的文档结构和嵌套 控制有限,依赖Block处理器的行为 处理块级元素

这些方法可以根据具体需求单独使用或组合使用。选择合适的方法取决于您的插件需要处理的语法复杂性、性能要求以及与其他插件的交互需求。

Notes:

  • 示例代码是基于DokuWiki的语法插件系统编写的,展示了每种方法的基本用法
  • 实际应用中可能需要更复杂的逻辑和错误处理
  • DokuWiki的解析系统是基于状态机的,理解DOKU_LEXER_ENTER、DOKU_LEXER_MATCHED、DOKU_LEXER_UNMATCHED和DOKU_LEXER_EXIT等状态对于开发插件非常重要
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇