PrismJS 需要 DOM 才能使大多数插件工作。查看plugins/line-numbers/prism-line-numbers.js#L109 中的代码后,我们可以看到行号只是一个span 元素和class="line-numbers-rows",它的每一行都包含一个空的span。我们可以在没有 DOM 的情况下模拟这种行为,只需使用 prism-line-numbers 用于获取行号的相同正则表达式,然后编写一个包含 span.line-numbers-rows 的 html 代码的字符串,并为每一行添加一个空字符串 <span></span> .
Prism.highlight 仅运行 2 个挂钩,before-tokenize 和 after-tokenize。我们将使用after-tokenize 组成一个包含span.line-numbers-rows 元素和空span 行元素的lineNumbersWrapper 字符串:
const Prism = require('prismjs');
const loadLanguages = require('prismjs/components/');
loadLanguages(['csharp']);
const code = `Console.WriteLine();
Console.WriteLine("Demo: Prism line-numbers plugin with nodejs");`;
// https://github.com/PrismJS/prism/blob/master/plugins/line-numbers/prism-line-numbers.js#L109
var NEW_LINE_EXP = /\n(?!$)/g;
var lineNumbersWrapper;
Prism.hooks.add('after-tokenize', function (env) {
var match = env.code.match(NEW_LINE_EXP);
var linesNum = match ? match.length + 1 : 1;
var lines = new Array(linesNum + 1).join('<span></span>');
lineNumbersWrapper = `<span aria-hidden="true" class="line-numbers-rows">${lines}</span>`;
});
const formated = Prism.highlight(code, Prism.languages.csharp, 'csharp');
const html = formated + lineNumbersWrapper;
console.log(html);
这将输出:
Console<span class="token punctuation">.</span><span class="token function">WriteLine</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Console<span class="token punctuation">.</span><span class="token function">WriteLine</span><span class="token punctuation">(</span><span class="token string">"Demo: Generate invalid numbers"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span>
最后有span.line-numbers-rows:
<span aria-hidden="true" class="line-numbers-rows">
<span></span>
<span></span>
</span>
现在,如果我们在 pre.language-csharp.line-numbers code.language-csharp 元素中使用该输出,我们将得到正确的行号结果。检查这个只有themes/prism.css 和plugins/line-numbers/prism-line-numbers.css 的Codepen,并用上面输出的代码正确显示行号。
请注意,每一行(第一行除外)都必须是用于代码正确显示的标记,这是因为我们在 pre.code 块内,但我想你已经知道了。
更新
如果您不依赖 CSS 并且只希望在每行之前添加一个行号,那么您可以通过拆分所有行来添加一个,并在开头使用 padStart 添加每个带有空格填充的 index + 1 :
const Prism = require('prismjs');
const loadLanguages = require('prismjs/components/');
loadLanguages(['csharp']);
const code = `Console.WriteLine();
Console.WriteLine("Demo: Prism line-numbers plugin with nodejs");`;
const formated = Prism.highlight(code, Prism.languages.csharp, 'csharp');
const html = formated
.split('\n')
.map((line, num) => `${(num + 1).toString().padStart(4, ' ')}. ${line}`)
.join('\n');
console.log(html);
将输出:
1. Console<span class="token punctuation">.</span><span class="token function">WriteLine</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
2. Console<span class="token punctuation">.</span><span class="token function">WriteLine</span><span class="token punctuation">(</span><span class="token string">"Demo: Prism line-numbers plugin with nodejs"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>