2

为 Google 的 Prettify 创建自己的规则的最先进方法是什么?

我不是在谈论更改现有规则的颜色,此外,我想创建新规则:

  • 例如对于 shell/bash
  • 也许在一首诗的极端情况下,我想在其中显示“爱”这个词的所有外观

或者我想显示一棵树并将所有 spec.ts 文件标记为粗体,例如:

    ├── 源
    │ ├── 应用
    │ │ ├── app-routing.module.ts
    │ │ ├── app.component.css
    │ │ ├── app.component.css.map
    │ │ ├── app.component.html
    │ │ ├── app.component.scss
    │ │ ├── app.component.spec.ts
    │ │ ├── app.component.ts
    │ │ ├── app.module.ts
    │ │ └── 课
    │ │ ├── 课程.component.css
    │ │ ├── 课程.component.css.map
    │ │ ├── 课程.component.html
    │ │ ├── 课程.component.scss
    │ │ ├── course.component.spec.ts
    │ │ └── 课程.component.ts
4

1 回答 1

1

最简单的方法是从现有示例开始。

如果您查看该文件,您会发现它有一些围绕两个元组列表的样板:

PR['registerLangHandler'](
    PR['createSimpleLexer'](
        [
          // Some tuples
        ],
        [
          // Some more tuples
        ],
        [/* Some file extensions without dot */]));

如果文件扩展名列表包含"ext"并且要求 prettify 美化代码块,class="lang-ext ..."则将使用此处理程序。

两组元组具有相似的结构。这是第一组的一些

['opn',             /^\(+/, null, '('],
['clo',             /^\)+/, null, ')'],

这是第二组中的一个。

[PR['PR_KEYWORD'],     /^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|...)\b/, null],

PR['PR_KEYWORD']是一个预定义的标记类型,并与预定义样式表中的样式相匹配:

.kwd { color: #008 }  /* a keyword */

什么

['opn',             /^\(+/, null, '('],

就是说,在美化时,如果代码的开头以 开头/^\(+/,那么输入会被包裹在<span class="opn">...</span>. opn(LISP 开括号) 是一个字符串文字,因为它没有预定义的常量。如果您定义自己的令牌类型类,您可能必须在任何页面加载美化中为它们定义样式规则。

右侧的字符串'(', 被视为字符列表,因此当输入文本以这些字符之一开头时,此规则是唯一适用的规则。这是过去几年对 IE 6 的重要优化。

两组元组之间的唯一区别是第一个列表中的元组具有这个额外的独占字符元素。

IIRC,null支持的功能被发现很少(如果有必要)并且不再受支持。您在该位置放置的任何值都将被忽略。

CSS处理程序有一些关于这一切的文档,并演示了另一个特性。

['lang-css-kw', /^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],

如果标记类型以 开头lang-,而不是生成<span class="lang-css-kw">...</span>, prettify 将寻找文件扩展名的语言处理程序css-kw并将其递归地应用到组 1 中的内容。这个功能在这里可能是矫枉过正,因为现代 JS 引擎一直支持前瞻,但它是必要的,以便 HTML 模式可以递归地将 JS 和 CSS 模式应用于<script><style>块的内容。


Prettify 可以处理仅依赖于从左到右传递令牌的任何转换。它没有办法在边表中收集符号以消除歧义,因此无法区分这两个 C 代码段:

typedef int t  // t is declared as a type
t* x;   // declare x as a pointer to a t. "t" should have class="typ"

int t = 1;  // t is declared as a variable, not a type
t* x;   // multiplication.  "t" should not have class="typ"

面对您在 stackoverflow 等网站上经常看到的小代码片段和格式错误的代码,这种有限的方法似乎更加健壮。

对常见的语言约定进行编码是合理的,例如

  • 类型名称以大写字母开头
  • _t以类型结尾的标识符

在你的规则中。

于 2017-11-13T14:37:10.703 回答