(old) method for adding languages to highlight.js on Discourse

:warning: This method doesn’t work any more. See This method no longer works. Please see Install a new language for Highlight.JS via a theme component instead.

Original Post

Warning: This is a crazy hack!

I’m just sharing because (1) it maybe helpful to someone and (2) hopefully you will teach me a better way.

I hired a “Discourse as a Service” instance, so I don’t control the source code, nor can install plugins.

I wanted my forum to highlight the Beancount language.

First I wrote the syntax definition and sent it to upstream, but I didn’t want to wait for a Highlight.JS and Discourse release, and for my host to upgrade my instance.

Then I went to Admin -> Customize -> CSS/HTML -> </head> and added this hack to inject the Beancount language into Discourse’s Highlight.JS.

<script>
// Crazy hack to install Beancount syntax.
function waitForHighlightJS() {
    if(typeof hljs !== "undefined"){
        console.debug('HighlightJS ready... installing Beancount syntax.');
        
        // Install Beancount syntax.
        //Got this building highlight.js with: node tools/build.js -t cdn
        hljs.registerLanguage("beancount",function(e){var c="[A-Z][A-Za-z0-9-]*",a="[0-9]{4}[-|/][0-9]{2}[-|/][0-9]{2}",b="(balance|commodity|custom|document|event|note|open|pad|price|query)",t={cN:"literal",b:/([\-|\+]?)([\d]+[\.]?[\d]*)/,r:0},n={cN:"string",b:'"',e:'"',r:0,c:[e.BE]},s={cN:"name",b:"\\{",e:"\\}",c:[{cN:"literal",b:a},t,n,{cN:"subst",b:"[A-Z][A-Z0-9'._-]{0,22}[A-Z0-9]"}]};return{aliases:["beancount","bean","ledger"],c:[{cN:"built_in",b:"^(include|option|plugin|popmeta|poptag|pushmeta|pushtag)",r:0},{b:"^"+a+"\\s+"+b,rB:!0,r:10,c:[{cN:"type",b:a,e:/\s+/,eE:!0},{cN:"keyword",b:b}]},{b:"^"+a+"\\s+.\\s",rB:!0,r:10,c:[{cN:"type",b:a,e:"\\s+",eE:!0},{cN:"variable",b:".",endsParent:!0}]},e.C(";","$"),{cN:"meta",b:/^\s{2,}[a-z][A-Za-z0-9\-_]+:/},s,{cN:"name",b:"@"},{cN:"type",b:c+":",r:0,c:[{cN:"subst",b:c+"(:"+c+")?"}]},{cN:"section",b:/^\*\s+?.*/},{cN:"link",b:/\^[A-Za-z0-9\-_\/.]+/},{cN:["emphasis"],b:/#[A-Za-z0-9\-_\/.]+/},n,t]}});
        
        // Realod syntax for codeblocks.
        $("pre code[class]").each(function(i, e){
            hljs.highlightBlock(e);
        })
        
        console.debug('HighlightJS updated. Everything should look good.');
    }
    else{
        console.debug('HighlightJS not ready yet.')
        setTimeout(waitForHighlightJS, 250);
    }
}
setTimeout(waitForHighlightJS, 250);
</script>

Works for me. If you have any suggestions I would be glad to hear. Mainly if you know how it can be done without the setTimeout.

's!

4 个赞

Ideally I would prefer simply to upgrade highlight and make the brand new languages an option. This hack is very very very hacky.

4 个赞

Me too! :smiley: Unfortunately this is not under my control.

I was wandering… Discourse’s HLJS plugin already allow some customization on init. Maybe it would be useful to not limit this customization to languages. Maybe passing an object that would be merged with the config object could do this trick and more.

However, I don’t think ppl need this very much. I’ll stick with my hack until (1) HLJS is released and (2) Discourse updated.

How do you indiciate which syntax highlighter to use when you insert code into a post?

AFAIK HighlightJS uses the first language that match.

However, every language has a “registration name”.

hljs.registerLanguage("beancount",function(e){...})

So if you want to explicitly define the language, inform the name after the triple ```.

``` python
Some code
```
4 个赞

Thanks - I had seen the registration name but it wasn’t clear how to specify that name when posting code.

一个帖子被拆分到一个新主题:通过主题组件为 Highlight.JS 安装新语言

我在研究如何为我们的 Chapel 语言 Discourse 站点 添加 Chapel 语法高亮支持时,看到了这篇文章。我们计划使用一个第三方的 Chapel 版 highlight.js 扩展来实现。

@pmusaraj 上面的示例中,我明白如何将其修改为用 Chapel 替换 beancount。但作为 Discourse 的新手,我不清楚接下来该如何处理脚本块,以便在我们的 Discourse 站点上启用该功能。能否有人为像我这样的新手提供一些进一步的指导?

谢谢!

您可以在 管理 > 自定义 > 主题 下创建一个新的主题组件,然后将该代码粘贴到 <head> 部分。之后根据需要对其进行修改和调整。

更多信息:

Discourse 主题使用入门指南
Discourse 主题开发者指南

4 个赞

谢谢 @justin,这正是我所缺少的(而且如果不是在放弃之前尝试,我根本不可能自己找到这个方案)!我们的 Discourse 现在可以正确渲染 Chapel 代码了(或者说,至少在我的 highlight.js 脚本能做到的范围内正确渲染,这已经是个很好的开始了……)。

即使经过一些试错,仍有几点我不太清楚:

  1. 对于三重引号代码块上的语言标签,例如:

    ```chapel
    

    它是否仅与 registerHighlightJSLanguage() 调用的(第一个)参数进行匹配?还是会同时与语言高亮器在 highlight.js 定义中设置的别名进行匹配?如果是前者,是否有理由避免使用各种别名多次注册同一语言定义,以支持多种写法(例如 ```chapel```chpl)?

  2. 是否还需要将语言添加到站点的“高亮语言”设置中,代码块才能被识别?并且该名称必须与传递给 registerHighlightJSLanguage() 的字符串完全一致?

再次感谢。

我为 Jai 创建了新的语法高亮:GitHub - Jai-Community/discourse-highlightjs-jai: Discourse theme component to highlight Jai syntax · GitHub

然而,当我安装它并进入主题预览模式,然后创建一个新主题并添加一些代码,例如:

```jai
#run {}
```

…它确实检测到了语言(请查看 class 属性),但未能解析任何内容:

<pre><code class="lang-jai hljs">#run {}
</code></pre>

而在本地环境中运行相同的语言定义时,却能成功高亮 Jai 语法:

您可以在浏览器中打开 _dev/test-syntax-highlight.html 自行测试。

有什么建议吗?

原来 Discourse 使用的是旧版 Highlight.js,与当前版本不兼容。因此,我不得不修正我的语言定义,结果非常顺利。

如果您对完整的语法高亮主题组件仓库示例感兴趣,可以参考以下内容:

2 个赞

Screenshot 2024-01-21 at 8.41.45 PM

你好 @what,此主题的 OP 已过时。我已将有效的说明提取到一个新主题中:

3 个赞