本站之前一直都是用的 wordpress 二〇一五主题的默认代码块,闲着没事儿干就想着加上一个代码高亮的功能,加的同时遇到了一些坑,因此写一篇文章记录一下。
一、Prism
Prism js 是一个轻量级的语法高亮 js / css。广泛使用在各大站点中,本站也不太想用插件实现代码高亮,因此选择了 Prism。Prsim网站在此。
二、选择 Prism 功能
Prism 高度可扩展,因此只需要选择需要用到的语法高亮的功能,点击 Prism 的 Download 按钮,网站会自动跳转到功能选择页面,在页面上可以选择需要用的的语言(如 C, Java, Scala, Verilog 等),也可以选择需要的功能(如显示代码行数 line-numbers 等)。选择完成后点击最下方的两个下载按钮,分别下载 Prism.js 和 Prism.css。
三、上传 Prism 至站点
上节中下载的两个 Prism 文件需要放到 WordPress 的主题文件夹中以便引用。本站将其上传到了二〇一五主题的子主题中。所谓子主题,详细内容可以参照 WordPress 官网说明了解。笔者在此简单说明一下:
父主题:即大部分主题,是一个完整的、包含所有模板和所需主题文件的主题,任何除子主题之外的主题都是父主题,比如本站用的二〇一五主题,就是一个父主题。
子主题:子主题是一个继承了父主题的外观及其所有功能的主题,但可以在子主题中对父主题任意部分进行修改,修改的部分全部仅限在子主题的文件夹中,因此不会影响到父主题。子主题修改的部分 WordPress 会自动加载,子主题没有修改的部分 WordPress 会自动使用父主题的文件。通过这样的方式,可以实现随着主题更新,对主题文件的修改不会丢失。
总而言之,将 Prism 上传到你希望使用的站点主题文件夹中,无论父主题子主题均可。上传后,文件目录看起来应该是这个样子:
.../wp-content/themes/ |-twentyfifteen |-twentyfifteen-child # 主题文件夹,可能不同 |-style.css |-function.php |-prism.js # 上传的两个 Prism 文件 |-prism.css
记得修改文件的权限,使得 nginx 和 wordpress 有权限访问。
四、添加 php 函数加载 Prism
在你主题文件夹中,有一个 function.php 文件(在笔者给出的上述示例中即为 /wp-content/themes/twentyfifteen-child/function.php),编辑它,并插入代码(见后)
要插入的代码来自第三方教程,主要功能为注册 prism.js 和 prism.css,然后将它们按照 wordpress 手册给出的要求入队,并使用 add_action 绑定到钩子上,如果你不知道这段在说什么,请参照 WordPress 手册。插入的代码有两种可选,第一种为在每个文章页面上都启用 Prism,第二种为只在有 code
标签的文章页面上启用 Prism。按照喜好选择即可。
第一种(全局启用 Prism):
<?php
// Function to add prism.css and prism.js to the site
function add_prism() {
// Register prism.css file
wp_register_style(
'prismCSS', // handle name for the style
get_stylesheet_directory_uri() . '/prism.css' // location of the prism.css file
);
// Register prism.js file
wp_register_script(
'prismJS', // handle name for the script
get_stylesheet_directory_uri() . '/prism.js' // location of the prism.js file
);
// Enqueue the registered style and script files
wp_enqueue_style('prismCSS');
wp_enqueue_script('prismJS');
}
add_action('wp_enqueue_scripts', 'add_prism');
第二种(只在有 code
标签的文章页面上启用):
<?php
/**
* Add custom functions here
*/
// Function to add prism.css and prism.js to the site
function add_prism() {
if ( is_single() && has_tag( 'code' ) ) {
// Register prism.css file
wp_register_style(
'prismCSS', // handle name for the style
get_stylesheet_directory_uri() . '/prism.css' // location of the prism.css file
);
// Register prism.js file
wp_register_script(
'prismJS', // handle name for the script
get_stylesheet_directory_uri() . '/prism.js' // location of the prism.js file
);
// Enqueue the registered style and script files
wp_enqueue_style('prismCSS');
wp_enqueue_script('prismJS');
}
}
add_action('wp_enqueue_scripts', 'add_prism');
注意开头的 <?php
,如果你的 function.php 文件中已经有了这个字段,请不要重复添加。
在第二种代码中, is_single()
表示是一个文章页面, has_tag('code')
表示这个页面有 code 标签。从而只在需要的地方启用 Prism,减少不必要的开销,在文章中启用 Prism 的方法也很简单,在 WordPress 的文章编辑页面,选择 文章->标签,加上 code 标签即可。
五、启用代码高亮
上一节我们只是在想要的地方启用了 Prism,本节我们将会使用代码高亮功能。使用代码高亮有两种方式:
一:在 WordPress 文章编辑页面选中你的代码区块,点击右侧的设置->区块->高级,然后添加一条 css 样式,比如 language-java
,就能在选中的代码区块中实现 Java 的语法高亮,其他语言类似。
二:Wordpress 文章编辑页面中选择使用 html 编辑区块,然后在 code 项中添加 css 类,比如要在某个区块中实现 c 的语法高亮那么按照如下方式编辑这个区块的 html:
<pre><code class="language-c">
int main() {}
</code></pre>
如果需要显示行号,需要之前下载 Prism 时选择了该插件,并显式地加上 line-numbers:
<pre class="line-numbers"><code class="language-c">
int main() {}
</code></pre>
对于内联代码高亮,同样地对区块进行上述两种操作之一即可。
六、全局代码高亮
笔者觉得每次敲一个代码区块都要写上<pre><code>这些内容非常麻烦,而按照第一种方法直接在区块的高级设置里添加 css 又会导致代码块有白边(二〇一五主题的问题,也可能是因为笔者没安装古腾堡编辑器),非常不美观。因此希望找到一种能够方便的进行代码高亮的方法,目前只有一个不算很好的解决方案。
笔者目前采用了在子主题中的 function.php 添加一个绑定到 filter 上的 callback function 来实现自动代码高亮(主要是以前的旧文章,不希望一个个手动添加<pre>和<code>前后缀),在此进行一些简要介绍。
首先在子主题的 function.php 中,添加如下的函数:
// Functions to auto replace code block
function replace_code_block($text_wp){
// default do nothing
$replace = array(
'<pre>' => '<pre>',
'<code>' => '<code>',
);
if ( is_single() && has_tag( 'code' ) && has_tag( 'php' ) ) {
$replace = array(
'<pre class="wp-block-code">' => '<pre class="line-numbers">',
'<code>' => '<code class="language-php">',
);
}
$text_wp = str_replace(array_keys($replace), $replace, $text_wp);
return $text_wp;
}
add_filter('the_content', 'replace_code_block');
该自定义函数命名为 replace_code_block,意为对文章中的代码块进行自动替换。默认情况下,replace 变量不会进行任何替换。对文章内 ( is_single()
) 且有标签 code 和 php 的文章,进行如下替换:<pre class="wp-code-block">
替换为 <pre class="line-numbers">
,<code>
替换为 <code class="language-php">
。进行这样做的原因是, WordPress 自带的 css 类 wp-code-block
在同时启用 Prism 代码高亮的情况下会有一个白圈,不好看,同时可以自动把带 php 标签文章内所有的代码块启用 php 语言的代码高亮,并且开启行数显示。
类似的,在函数内继续添加多个 if 块,即可实现对不同标签的语言实现不同语言的代码高亮。不过这么做也有缺点,多个语言的标签只有最后一个 if 被执行的标签所属的语言生效。并且,在代码块内,如果需要不同的语言的代码高亮,仍要按上节所述的方法手动指定。
七、单个代码块代码高亮
感谢 @元子 提供的方案,可以自动替换代码块,并使用首行指定语言的方式,为每个代码块方便地实现不同语言的代码高亮。详见 [4]。
八、总结
使用 Prism 进行语法高亮是很方便,但是如何适配好主题对笔者来说尚有一定难度,目前的解决方案也只是勉强及格。如果有更好的建议欢迎提出。
我是在模板函数(functions.php)中新增了一个函数,用于将默认的代码块转换成prism高亮代码块,使用wp古腾堡默认代码块进行编辑,然后第一行写明高亮语言,可以逐一进行识别高亮,代码如下:
/**
* prism.js将默认的代码块转换成prism
*/
function process_code_blocks( $content ) {
$pattern = ‘/
(.*?)/s';
$content = preg_replace_callback( $pattern, function( $matches ) {
$code = html_entity_decode($matches[1]);
if (preg_match('/(.+?)\n(.*)/s', $code, $first_line_matches)) {
$language = trim($first_line_matches[1]);
$code = $first_line_matches[2];
} else {
$language = 'plaintext';
}
// 构造新的代码块
$new_code_block = '
' . htmlspecialchars($code) . '
';// 返回新的代码块
return $new_code_block;
}, $content );
return $content;
}
add_filter( 'the_content', 'process_code_blocks' );
测试了一下,你的方案确实更好,更加灵活,学习了~