WordPress 支持代码高亮

本站之前一直都是用的 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 进行语法高亮是很方便,但是如何适配好主题对笔者来说尚有一定难度,目前的解决方案也只是勉强及格。如果有更好的建议欢迎提出。

九、参考资料

  1. https://startblogging101.com/how-to-add-prism-js-syntax-highlighting-wordpress/
  2. https://developer.wordpress.org/themes/advanced-topics/child-themes/
  3. http://www.95408.com/blog/3415.html
  4. https://yzgsa.com/index.php/2024/04/12/prism-也许是目前理想的wordpress代码高亮方案/

《WordPress 支持代码高亮》上有2条评论

  1. 我是在模板函数(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' );

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据