Hack to install a new language for Highlight.JS on a hosted discourse


(Henrique Bastos) #1

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!


(Sam Saffron) #2

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


(Henrique Bastos) #3

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.