Hexo
处理的代码块会被包裹在 figure table tbody tr > td.code pre
中,每一行代码又被 span
包裹,如果需要加入对 Typst
的支持,需要将所有的代码重新提取出来,处理后之后再填入,有两种方法可以选择:
前端修改:在 html
页面中读取代码块元素,提取代码处理后再填入(1) 标签插件(推荐 ) :在 hexo
生成的过程中使用标签插件 (2) 处理前端修改 此方法可能需要刷新才能正常显示 此方法会将所有的 plaintext
识别为 typst
,可以通过在第一行加一行说明语言来处理
引入js
文件 1 2 3 4 5 <script crossorigin ="anonymous" src ="https://foolishfox.cn/js/hl.js" > </script > <script id ="script-main" src ="https://cdn.jsdelivr.net/npm/@myriaddreamin/highlighter-typst/dist/cjs/contrib/hljs/typst.bundle.js" > </script >
注册 Typst
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 const run = ( ) => { $typst$parserModule.then (() => { hljs.registerLanguage ( 'typst' , window .hljsTypst ({ codeBlockDefaultLanguage : 'typst' , }), ); hljs.configure ({ classPrefix : '' }); }).then (() => { document .querySelectorAll ('figure table tbody tr > td.code pre' ).forEach (el => { if (!el.getAttribute ('data-highlighted' )) { var pre = document .createElement ("pre" ); var lang = el.parentNode .parentNode .parentNode .parentNode .parentNode .classList [1 ]; var code = "" ; for (i = 0 ; i < el.childElementCount ; i++){ ch = el.children [i]; if (ch.tagName == "SPAN" ) code += ch.textContent ; if (ch.tagName == "BR" ) code += "\n" ; } if (lang == "plaintext" ) { lang = "typst" ; } if (lang != "plaintext" ) { el.innerHTML = hljs.highlight (code, {language : lang}).value } } }); }); } run ();
标签插件 查看 Hexo
原生处理代码块的逻辑 (4) :
register plugins/tag/index.ts 12 13 14 15 const code = require ('./code' )(ctx);tag.register ('code' , code, true ); tag.register ('codeblock' , code, true );
在 code
模块中,先对传入的参数进行了解析,然后再调用 hexo-utils
的 highlight
进行渲染:
code plugins/tag/code.ts 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 function parseArgs (args: string[] ): HighlightOptions { ...... return { lang, language_attr, firstLine, caption, line_number, line_threshold, mark, wrap }; } module .exports = ctx => function codeTag (args, content ) { ...... const options = parseArgs (args); options.lines_length = content.split ('\n' ).length ; content = ctx.extend .highlight .exec (ctx.config .syntax_highlighter , { context : ctx, args : [content, options] }); return content.replace (/{/g , '{' ).replace (/}/g , '}' ); };
所以我们可以在返回 content
之前对其进行处理,处理的逻辑与前一种方法是类似的,首先导入所需要的模块:
import typst.js 1 2 3 const hljs = require ('highlight.js' );const highlight = require ('hexo-util' ).highlight ;const typstBunlde = require ('./typst.bundle' );
然后获取 highlight
处理过后的代码块:
highlight process typst.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 const codeTypst = (args, content ) => { const options = parseArgs (args); options.lines_length = content.split ('\n' ).length ; const line_threshold = options.line_threshold || 0 ; const shouldUseLineNumbers = options.line_number ; const surpassesLineThreshold = options.lines_length > line_threshold; const gutter = shouldUseLineNumbers && surpassesLineThreshold; const hljsOptions = { caption : options.caption , firstLine : options.firstLine , gutter, mark : options.mark , }; var contentHljs = highlight (content, hljsOptions); contentHljs = contentHljs.replace (/{/g , '{' ).replace (/}/g , '}' ); ...... }
然后注册 Typst
语言,并提取代码进行处理:
extract and process typst.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 const codeTypst = (args, content ) => { ...... return typstBunlde.parserModule .then (() => { hljs.registerLanguage ( 'typst' , typstBunlde.hljsTypst ({ codeBlockDefaultLanguage : 'typst' , }), ) }).then (() => { var re = /<td class="code"><pre>(.+)<\/pre><\/td>/i ; var code = hljs.highlight (content, {language : 'typst' }).value ; contentHljs = contentHljs.replace ("highlight plaintext" , "highlight typst" ) return contentHljs.replace (re, `<td class="code"><pre>${code} </pre></td>` ); }); }
最后在 Hexo
中注册这个标签插件,由于注册 Typst
语言并处理的过程是异步的,所以这里也要开启异步选项:
register with async typst.js 1 hexo.extend .tag .register ('typst' , codeTypst, {ends : true , async : true });
示例 使用方法 预览 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 {% typst %} #import "@preview/tablex:0.0.6": tablex, rowspanx, colspanx, hlinex, vlinex #let three-line-table(columns, headers, contents, caption, lang: "en",rows: auto) = {figure( tablex( columns: columns, rows: rows, align: center + horizon, auto-lines: false, repeat-header: true, hlinex(stroke: 1.5pt), ..headers, hlinex(stroke: 0.75pt), ..contents, hlinex(stroke: 1.5pt), ), kind: table, supplement: [#if (lang == "en") {"Table"} else {"表"}], caption: caption, )} {% endtypst %}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 # import "@preview/tablex:0.0.6" : tablex , rowspanx , colspanx , hlinex , vlinex
# let three-line-table ( columns , headers , contents , caption , lang : "en" , rows : auto ) = { figure (
tablex (
columns : columns ,
rows : rows ,
align : center + horizon ,
auto-lines : false ,
repeat-header : true ,
hlinex ( stroke : 1.5pt ) ,
.. headers ,
hlinex ( stroke : 0.75pt ) ,
.. contents ,
hlinex ( stroke : 1.5pt ) ,
) ,
kind : table ,
supplement : [ # if ( lang == "en" ) { "Table" } else { "表" } ] ,
caption : caption ,
) }
参考资料 在 Hugo 中为 Typst 配置语法高亮(PaperMod 主题) 标签插件(Tag) highlighter 代码高亮