:root{--puock-block-not-tran:100%}

Pandoc Markdown 转换为 HTML 格式代码块手动指定语言 PHP 修复

768次阅读
没有评论

共计 1895 个字符,预计需要花费 5 分钟才能阅读完成。

问题描述

这段时间我已经搭建好了 VSCdoe + Pandoc 的写作环境, 搭建过程参考我这边文章使用VSCode搭建Markdown写作环境. 但在在页面中代码高亮存在问题. 页面上我发现 highlightjs 并不不能很好的识别到需要渲染的代码块. 如下代码所示:

# Markdown 代码块 转换为 HTML 普通输出
echo -e '```html\nfoo\n```' | pandoc
# out: <div class="sourceCode" id="cb1"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a>foo</span></code></pre></div>
# Markdown 代码块 转换为 HTML 禁用自带的代码高亮
echo -e '```html\nfoo\n```' | pandoc --no-highlight
# <pre class="html"><code>foo</code></pre>

问题探究

如上所示的两种方法都不会转换出 highlightjs 所需要的手动指定语言class的HTML

<pre><code class="language-html">...</code></pre>

这个问题也在Pandoc Issues #3858有反馈并且在2017年就提出了. 或许官方是基于兼容性考虑并未修复它.

Pandoc 在转换中认为.

``` foo
bar
```

``` {.foo}
bar
```

的语义是相同的. 个人认为 Pandoc 在其中的问题讨论中 Pandoc 仓库的维护者也说明了一定一些原因, 在 Pandoc 导出 html 片段 默认文档不做任何处理只导出其语义. pre class="html" 在预处理标签中放入这个信息, 然后再到渲染的地方去具体实现它更符合最大兼容度理念.

解决问题

最终我选择放弃在 Pandoc 中处理, 在上面的Gihub问题讨论中, 有人也尝试过使用Lua 脚本的方案去解决这个问题. 详细见 pandoc-filters standard-code. 这种过滤方法存在问题 导出的时候回进行嵌套转换破坏 Pandoc 导出的兼容性, 不推荐.

Pandoc 导出标准化

由于我使用的是 WordPress 或许在 PHP 中动态处理会是一个比较好的方案. 下面是我的 markdown 导出到 html 脚本代码

pandoc --no-highlight --wrap=none -f markdown src.md -t html -o dist.html

需要注意这两个参数:

  • --no-highlight 指定导出时不进行代码高亮处理
  • --wrap=none 导出时关闭自动换行导出到 html 的时候 Pandoc 的处理方式有点奇怪, 直接关闭.

这样会得到如下代码的比较标准的输出

 <pre class="html"><code>foo</code></pre>

PHP 中输出 highlightjs 标准格式

//对pre里面的内容进行转义
function pk_tag_pre_encode($content)
{
    preg_match_all("/<pre\sclass=\"(.+?)\">(.+?)<\/pre>/is", $content, $matches);
    if (isset($matches[2])) {
        $index = 0;
        foreach ($matches[2] as $match) {
            $m = trim($match);
            $classes = explode(' ',$matches[1][$index]);
            $language = 'language-default';
            foreach($classes as $class){
                if($class!=='sourceCode'){
                    $language = "language-".$class;
                }
            }
            if (!(substr($m, 0, strlen("<code")) === "<code")) {
                $m = "<code class='".$language."'>$m</code>";
            }
            if (substr($m, 0, strlen("<code>")) === "<code>") {
                $m = "<code class='".$language."'>" .substr($m, strlen("<code>"));
            }
            $content = str_replace($match, $m, $content);
            $index++;
        }
    }
    return $content;
}

总结

以上只是我对 Pandoc 输出格式代码块的个人解决方案. 目前还在探索中…

正文完
 4
太阳
版权声明:本站原创文章,由 太阳 于2023-10-28发表,共计1895字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)