node.js - 使用 prismjs 生成静态 html - 如何启用行号?

标签 node.js prismjs

我使用 node.js 从代码生成静态 html 文件,并使用 prismjs 对其进行格式化。在我的应用程序中,我无法访问支持 Javascript 的 HTML 渲染器(我使用的是“htmllite”)。所以我需要能够生成不需要 Javascript 的 HTML。

const Prism = require('prismjs');
const loadLanguages = require('prismjs/components/');
loadLanguages(['csharp']);
const code = '<a bunch of C# code>';
const html = Prism.highlight(code, Prism.languages.csharp, 'csharp');

这很好用。但我想使用 line-numbers插件,但不知道如何使其工作。我的<pre>line-numbers类,我得到了更大的左边距,但没有行号。

最佳答案

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 个钩子(Hook), before-tokenize after-tokenize 。我们将使用 after-tokenize 撰写lineNumbersWrapper包含 span.line-numbers-rows 的字符串元素和空 span线条元素:

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 中使用该输出元素,我们将得到正确的行号结果。检查这个Codepen只有 themes/prism.cssplugins/line-numbers/prism-line-numbers.css并使用上面输出的代码正确显示行号。

请注意,每一行(第一行除外)都必须是标记,以便代码正确显示,这是因为我们位于 pre.code 内。阻止,但我想你已经知道了。

更新

如果您不依赖 CSS 并且只想在每行之前添加一个行号,那么您可以通过拆分所有行并添加每个 index + 1 来添加一个行号。在开头使用空格填充 padStart :

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>

关于node.js - 使用 prismjs 生成静态 html - 如何启用行号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59508413/

相关文章:

node.js - 在node.js中如何要求与当前文件不在同一文件夹中的模块

node.js - 无法删除文件,我没有得到详细的 ENOENT

javascript - PrismJS 没有换行符

javascript - 如何使用 prismjs 在 vuejs 中添加复制到剪贴板功能?

node.js - Angular 6 |表达 : Getting 404 error on dist files

node.js - HAProxy 配置 - 如何使 TCP 连接保持粘性(Node.js、socket.io、websocket、FlashSocket)

javascript - 循环嵌套 Handlebars 导入数组中的特定元素时出现问题

reactjs - Prismjs 没有突出显示 React 组件

javascript - 如何在react中加载自定义prismjs语法文件?