和别的类似的给自己的个人 Hexo 博客添加 Prettify 的教程文章不同,这篇文章是给 Hexo 主题适配 Google Prettify 的教程,虽然这两者在实际上并无太多不同。
为了让「Suka」主题正如我在 Slogan 介绍的那样是一个「Powerful」的主题,所以除了内置 Prism 代码高亮以外,至少还应该内置 Google Code Prettify 代码高亮。
首先是把 Google Code Prettify 添加到 Hexo 主题之中。查看 Google Code Prettify 的 README 上面的教程,按照 Google 提供的方法,只需要引入一个主题 css 文件和一个 prettify.js
就行。
Google 打包了一个 Prettify 的默认主题和一个通用方案版本的 prettify.js
代码 供开发者下载。解压以后丢进主题的 source
目录里。
为了主题的前端性能,所以我们只需要在文章页面(layout 为 post 的页面)引入文件。正好,Hexo 提供了这辅助函数 is_post()
判断当前页面的 layout,我们就不需要什么 if (page.layout === 'post')
了。所以可以直接用这样的代码完成 prettify.js
的按需加载。
<% if ( (is_post()) ) { %> |
<script src="<%- url_for('js/prettify.js') %>"></script> |
<% } %> |
光光引入 prettify.js
并不能完成代码高亮,还要需要“激活”代码才能开始让 prettify 开始渲染代码。Google 推荐在 <body>
上绑定 onload
事件来调用 prettify,就像这样:
<body onload="PR.prettyPrint()"> |
这个方案显然很 dirty,而且 不符合规范 (虽然我这里引用的规范是我自己写的)。如果你在其它类似的给 Hexo 添加 Prettify 的教程上介绍的方法,无一例外使用了 $(document).ready()
,还有一些使用了 $(window).load(function()
。但是「Suka」主题并没有使用 jQuery,所以只能用 VanillaJS 的方法。而且,和 $(document).ready()
可以在一个页面里反复使用不同,window.onload
方法在一个页面里只允许使用一次。
我的方案更加简单粗暴。因为 HTML 中的 <script>
标签是按照顺序执行的,所以我可以在页面底部添加 <script>
标签调用 Prettify,在执行的时候已经可以确保所有 DOM Tree 都已经建立好、可以调用 Prettify 去遍历 DOM Node 了,并不需要等待 onload 事件发生。
但是,Prettify 并不是指定元素选择器的方式来就决定渲染哪一部分,Google Code Prettify 使用的元素选择器是 .prettyprint
,并需要添加 .linenums
作为行号。所以必须事先对 <pre>
标签带上这个 class。不过,我在为「Suka」主题添加 PrismJS 代码高亮的时候就是使用的 preprocess 的方案,通过在主题的 scripts
目录下编写了一段插件脚本、在执行 hexo s
或者 hexo g
的时候对代码进行预处理(打上 class)。到适配 Google Code Prettify 的时候,我不想再采用 preprocess 的方案了,我要用 JS 中遍历 <pre>
标签带上这两个 class。
在那些常见的为 Hexo 添加 Prettify 的教程中,他们一般会教你使用 $('pre').addClass('prettyprint linenums');
方法。但是同样因为我没有用 jQuery,我需要使用 VanillaJS 的方法:
for (var i = 0; i < (document.querySelectorAll('pre') || []).length; i += 1) { |
document.querySelectorAll('pre')[i].classList.add('prettyprint'); |
document.querySelectorAll('pre')[i].classList.add('linenums'); |
} |
虽然看起来更长,但是这是纯原生的 JS 代码方法,而且 It works。只需要在这段代码之后再添加 prettyPrint();
渲染就行了。最终代码就像这样:
<script> |
var prettifyel = document.querySelectorAll('pre'); |
for (var i = 0; i < (prettifyel || []).length; i += 1) { |
prettifyel[i].classList.add('prettyprint'); |
prettifyel[i].classList.add('linenums'); |
} |
prettyPrint(); |
</script> |
当然,因为 prettyPrint()
方法依赖 prettify.js
,所以需要把它放在其后,放在 is_post()
的判断的里面。
用同样的判断方法按需添加 prettify 的主题 css 文件。但是测试之后发现,Google 提供的默认的 Prettify 的主题并不好看。所以在 Google 上面搜索 Prettify Theme,排名第一的结果就是 这个,上面提供了很多漂亮的代码高亮主题。那么就是它了!
下载 zip 解压丢进主题的 source/css/prettify-themes
目录里。但是用户需要能够自己挑选主题,所以需要在主题配置文件之中暴露一个接口。我在主题配置文件中添加了 prettify.theme
,接着在 <head>
使用 <link>
标签添加 css 到页面:
<% if ( (is_post()) ) { %> |
<link rel="stylesheet" href="<%- url_for('css/prettify-themes/' + theme.prettify.theme + '.min.css') %>"> |
<% } %> |
然后跑一遍 hexo s
预览一下效果,稍微修改一下样式就可以了。
你可以在「Suka」主题的这两条 commit 中找到其它相关细节、比如如何适配行号和如何添加 Custom CDN 支持:12a3ce7
59ef7a9
本文作者 : Sukka
本文采用 CC BY-NC-SA 4.0 许可协议。转载和引用时请注意遵守协议!
本文链接 : https://blog.skk.moe/post/add-prettify-to-hexo/