如何使用 highlight.js 突出显示所有 R 函数名称?

How to highlight all R function names with highlight.js?

我想为 R 语言扩展 highlight.js 功能,以便 (1) 所有函数名称后跟左括号 ((2) 后跟 ::::: 运算符的所有包名称都将突出显示(就像在 RStudio 中一样,见图 1。) .括号 () 和运算符 ::::: 不应突出显示。

图 1。 R 代码部分(函数和包名称)的所需突出显示。

我的示例包含两个文件:index.htmlr.min.js

HTML 文件:

<html lang="en-us">
<head> <meta charset="utf-8">
    <link href='https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/agate.min.css' rel='stylesheet' type='text/css' />
</head>

<body>

<pre class="r"><code>doc_name &lt;-
    officer::read_docx() %&gt;% 
    flextable:::body_add_flextable(table_to_save) %&gt;% 
    print(target = &quot;word.docx&quot;)

.libPaths()

c("a", "b")

package::function()$field
</code></pre> 

<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.12.0/build/highlight.min.js"></script>
<script src="r.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>

</body>
</html>

r.min.js 文件:

hljs.registerLanguage("r",function(e){var r="([a-zA-Z]|\.[a-zA-Z.])[a-zA-Z0-9._]*";return{c:[e.HCM,{b:r,l:r,k:{keyword:"function if in break next repeat else for return switch while try tryCatch stop warning require library attach detach source setMethod setGeneric setGroupGeneric setClass ...",literal:"NULL NA TRUE FALSE T F Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 NA_complex_|10"},r:0},{cN:"number",b:"0[xX][0-9a-fA-F]+[Li]?\b",r:0},{cN:"number",b:"\d+(?:[eE][+\-]?\d*)?L\b",r:0},{cN:"number",b:"\d+\.(?!\d)(?:i\b)?",r:0},{cN:"number",b:"\d+(?:\.\d*)?(?:[eE][+\-]?\d*)?i?\b",r:0},{cN:"number",b:"\.\d+(?:[eE][+\-]?\d*)?i?\b",r:0},{b:"`",e:"`",r:0},{cN:"string",c:[e.BE],v:[{b:'"',e:'"'},{b:"'",e:"'"}]},

/* My attempt... */
/* ... to highlight function names between double 
and triple colons and opening parenthesis (in red as symbol): */
{cN:"symbol",b:":::|::",e:"\(",eB:!0,eE:!0},

/* ... to highlight other function names (in red as symbol): */
{cN:"symbol",  b:"([a-zA-Z]|\.[a-zA-Z.])[a-zA-Z0-9._]*",e:"\(",eE:!0},

/* ... to highlight package names (in cyan as variable): */
{cN:"variable",b:"(?<!\w)",e:":::|::",eE:!0},

]}});

r.min.js 基于 (this file) 并包含 highlight.js 规则来识别 r 代码元素。 我添加的行在评论下面 "My attempt." 缩写的含义:cN - css class name, b - "beggins", e-"ends",eB-"exclude begin",eE-"exclude end",其他含义解释here.

我得到的结果(图2)并不令人满意。似乎我使用的正则表达式找不到 R 代码所需部分的正确开头和结尾。


图2.使用修改后的结果r.min.js

r.min.js 中正确的 highlight.js 代码应该是什么,才能使 R 代码的部分像在 RStudio 中一样突出显示?

听起来像是一个值得改进的地方,所以我修改了一段时间。

这应该很容易,

捕获包名称前缀的正则表达式可以这样写 (demo):

\w+(?=:::?)

对于这样的函数名称 (demo):

\.?\w+(?=\()

不幸的是,它并不那么容易应用于 highlight.js 语言解析规则。

经过一些回溯、跟踪​​和错误,我确定了以下代码,它给出了非常一致的突出显示:

/* ... to highlight other function names (in orange as a keyword): */
{
    cN: "keyword",
    b: /(^|\s*)(:::?|\.)\w+(?=\(|$)/
},
/* ... to highlight package names (in red as meta): */
{
    cN: "meta",
    b: /(^|\s*)\w+(?=:::?|$)/,
    r: 0
},
  • 我将 cN|className keyword 用于函数,这就是它的本质,它对函数的预定义样式的干扰较小。
  • 我建议使用 cN meta 的软件包名称也是如此。这是其他包用于类似构造的,并且它再次为内置样式提供了更一致的结果,例如数字。
  • 我还在关键字列表中添加了 printc。 R 语言的列表显然有些不完整。可以说每个函数名称(甚至来自 3rd 方包)都应该作为关键字添加——这是其他一些语言的做法——但这不是很实用)。

这就是我get.

示例代码:

hljs.registerLanguage("r",function(e){var r="([a-zA-Z]|\.[a-zA-Z.])[a-zA-Z0-9._]*";return{c:[e.HCM,{b:r,l:r,k:{keyword:"function if in break next repeat else for return switch while try tryCatch stop warning require library attach detach source setMethod setGeneric setGroupGeneric setClass c print ...",literal:"NULL NA TRUE FALSE T F Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 NA_complex_|10"},r:0},{cN:"number",b:"0[xX][0-9a-fA-F]+[Li]?\b",r:0},{cN:"number",b:"\d+(?:[eE][+\-]?\d*)?L\b",r:0},{cN:"number",b:"\d+\.(?!\d)(?:i\b)?",r:0},{cN:"number",b:"\d+(?:\.\d*)?(?:[eE][+\-]?\d*)?i?\b",r:0},{cN:"number",b:"\.\d+(?:[eE][+\-]?\d*)?i?\b",r:0},{b:"`",e:"`",r:0},{cN:"string",c:[e.BE],v:[{b:'"',e:'"'},{b:"'",e:"'"}]},
{cN: "keyword", b: /(^|\s*)(:::?|\.)\w+(?=\(|$)/},
{cN: "meta",b: /(^|\s*)\w+(?=:::?|$)/,r: 0 }, ]}});

hljs.initHighlightingOnLoad();
<html lang="en-us">
<head> <meta charset="utf-8"><link href='https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/agate.min.css' rel='stylesheet' type='text/css' />
</head><body>

    <pre class="r"><code>library(officer)
doc_name &lt;-
    officer::read_docx() %&gt;% 
    flextable:::body_add_flextable(table_to_save) %&gt;% 
    print(target = &quot;word.docx&quot;)

.libPaths()
x = 4
c("a", "b")

package::function()$field
</code></pre>
<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.12.0/build/highlight.min.js"></script>

</body></html>

非常接近,但远非完美。这里的主要障碍是我很难完全理解解析器如何解释模式。有些结果对我来说根本没有意义,但是 still work.