在Markdown使用代码高亮SyntaxHighlighter

经过长达几个小时的折腾,在Markdown使用代码高亮SyntaxHighlighter,几乎不可行。最后使用Google Code Prettify,绕过该问题,详情见博文《在Markdown使用代码高亮Google Code Prettify》。

0. 写在前面

最近打算转到用Markdown写博文(因为Window Live Writer不跨平台,输入数学公式也不方便),Markdown插入代码块是用triple backticks,被解析成<pre><code>...</code></pre>,这与之前在WLW使用PreCode(基于SyntaxHighlighter,其格式形如<pre class="brush: py">...</pre>)不尽相同。最开始的想法是找到一种方法使两者能兼容,但遇到了不少困难,最后得知Markdown不会处理HTML块级元素(当然也包括<pre></pre>),以为可以直接在Markdown,以<pre class="brush: ...">...</pre>的方式插入代码快。然而,SyntaxHighlighter要求所有在<pre>...</pre>间的<必须事先替换成HTML实体&lt;,使得在Markdown直接以<pre>...的方式插入代码快几乎不可能。

PROBLEMS: Major issue with this method is that all left angle brackets must be HTML escaped, eg all < must be replaced with &lt; This will ensure correct rendering.

这是之前做的笔记。记录吧不用插件安装SyntaxHighlighter,在markdown使用SyntaxHighlighter遇到的问题及可能的解决方法,并整理SyntaxHighlighter使用方法,方便日后查阅。

另,SyntaxHighlighter目前最新版本是3.0.9(我也是后来才知道,相对于3.0.83改动很大),整个项目搬到了GitHub,在这里。不过,本文用的是3.0.83(2010年,在这里)。

1. 无插件安装SyntaxHighlighter

可以直接安装wordpress插件SyntaxHighlighter Evolved(事实上,我之前也是这么做的),考虑到自己需要加一些不被该插件支持的语言(比如latex),于是决定手动安装SyntaxHighlighter。

步骤1:下载和定制

SyntaxHighlighter官网下载,按自已需要将所需文件整理到一个文件夹(如sh),并上传到跟主题或者子主题同目录下(以我为例:themes/radiate-child-01/)。以下文件是必须的:

  • styles/目录下的shCore.cssshThemeFadeToGrey.css(选个自己喜欢的主题,可以在这里预览主题样式)
  • scripts/文件下的shCore.jsshAutoloader.js,还有所需语言的javascript(如Python:shBrushPython.js),更多语言的js,可以查看All available brushes(目前已无法访问)

另,默认的代码块,第一行和最后一行贴边框太紧,可以修改shCore.css中的样式,如下:

/** modified in `sh/shCore.css` directly **/
.syntaxhighlighter table {
    margin-top: 0.5em !important;
    margin-bottom: 0.5em !important;
}

步骤2:加载js和css

functions.php添加必备css样式和js脚本,源代码如下(选个自己喜欢的主题):

function add_sh_styles_scripts() {
    wp_enqueue_style( 'shCore.css', get_stylesheet_directory_uri() . '/sh/shCore.css' );
    wp_enqueue_style( 'shThemeFadeToGrey.css', get_stylesheet_directory_uri() . '/sh/shThemeFadeToGrey.css' );

    wp_enqueue_script( 'shCore.js',  get_stylesheet_directory_uri() . '/sh/shCore.js', array(), false, false);
    wp_enqueue_script( 'shAutoloader.js',  get_stylesheet_directory_uri() . '/sh/shAutoloader.js', array(), false, false);
}
add_action( 'wp_enqueue_scripts', 'add_sh_styles_scripts' );

footer.php</body>之前添加如下代码(需要根据所选的语言做一些调整):

<script type="text/javascript">
    SyntaxHighlighter.autoloader(
        ['python', 'py', '<?php echo get_stylesheet_directory_uri(); ?>/sh/shBrushPython.js'],
        ['java', '<?php echo get_stylesheet_directory_uri(); ?>/sh/shBrushJava.js'],
        ['bash','shell','<?php echo get_stylesheet_directory_uri(); ?>/sh/shBrushBash.js'],
        ['css','<?php echo get_stylesheet_directory_uri(); ?>/sh/shBrushCss.js'],
        ['sql','<?php echo get_stylesheet_directory_uri(); ?>/sh/shBrushSql.js'],
        ['latex', 'tex','<?php echo get_stylesheet_directory_uri(); ?>/sh/shBrushLatex.js'],
        ['plain', 'text','<?php echo get_stylesheet_directory_uri(); ?>/sh/shBrushPlain.js'],
        ['php','<?php echo get_stylesheet_directory_uri(); ?>/sh/shBrushPhp.js'],
        ['js','jscript','javascript','<?php echo get_stylesheet_directory_uri(); ?>/sh/shBrushJScript.js'],
        ['xml', 'xhtml', 'xslt', 'html', 'xhtml','<?php echo get_stylesheet_directory_uri(); ?>/sh/shBrushXml.js']
    );
    SyntaxHighlighter.defaults['toolbar'] = false;
    SyntaxHighlighter.all();
</script>

值得注意的是,javascript的相对路径是基于当前页面,所以不能直接使用/sh/shBrushPython.js,因为会被解析成http://sparkandshine.net/sample-posts/sh/shBrushPython.js,报“not found”错误。另,如果不是用子主题,获取目录的函数get_stylesheet_directory_uri()可能需要改成get_template_directory_uri()

2. SyntaxHighlighter配置及使用

(1)配置

可以在上述代码SyntaxHighlighter.all();前加入SyntaxHighlighter配置,详情见这里,举例如下:

SyntaxHighlighter.config.stripBrs = true;

SyntaxHighlighter.defaults['gutter'] = false;
SyntaxHighlighter.defaults['html-script'] = true;
SyntaxHighlighter.defaults['toolbar'] = false;

SyntaxHighlighter.all();

(2)使用

实际插入代码,选项hightlight可能会用到比较多,用逗号(遵循csv格式)将要突出的行号分隔开,并用中括号括起来,举例如下:

<pre class="brush: js; highlight: [2, 4, 6]">
...
</pre>

3. 遇到的问题

3.1 在Markdown使用SyntaxHighlighter

在Markdown使用triple backticks插入代码会解析成<pre><code>...</code></pre>,SyntaxHighlighter无法正常解析,因为不符合SyntaxHighlighter的格式<pre class="brush: python">...</pre>

要是直接在Markdown编辑器直接插入<pre class="brush: ...">...</pre>,如果代码块包含<,SyntaxHighlighter也无法正常解析,因为SyntaxHighlighter要求<pre>...间的所有左尖括号<必须先转化成HTML实体,否则会出现匪夷所思的结果(源于SyntaxHighlighter自动匹配左尖括号<),举例如下:

// 好端端的代码
<pre class="brush: java">
private class MaxPropComparator implements Comparator<message> {
    ...
}
</pre>

// 会解析成这样(多添加了</message>)
<pre class="brush: java">
private class MaxPropComparator implements Comparator<message> {
    ...
}
</message></pre>

一个可能的方法是事先将所有<转换成&lt;$str = str_replace('<', '&lt;', $str);),这样尽管解决了代码高亮问题,但下次编辑博文,看到代码块散落的&lt;,是不是想死的心都有了?

3.2 html-script不可用

html-script设为true时(SyntaxHighlighter.defaults['html-script'] = true;),会提示如下错误:

TypeError: e.brushes.Xml is not a constructor
    SyntaxHighlighter</e.HtmlScript()   shCore.js:1
    SyntaxHighlighter</e.highlight()    shCore.js:1
    o/a.onreadystatechange()            shAutoloader.js:1

参考资料:
[1]StackOverflow: How to fix the pre tag’s issues with left angle brackets <?

专题: 代码高亮Syntax Highlighting (2/5)

发表评论

电子邮件地址不会被公开。 必填项已用*标注

One thought on “在Markdown使用代码高亮SyntaxHighlighter