2
\$\begingroup\$

I wrote a userscript (to be run with Greasemonkey/Tampermonkey on Stack Exchange sites) to include a Prettify extension and enable syntax highlighting for a language which isn't supported by default.

I have only occasionally dabbled in JavaScript, and I have never written a userscript before:

(function (func) {
    // helper for injecting the script into the page
    var script = document.createElement("script");
    // insert a script element...

    script.type = 'text/javascript';
    script.appendChild(
            // with a function which is called on document ready
            document.createTextNode("$(" + func + ")")
            );
    // run the script after other scripts
    document.body.appendChild(script);
})(function () {
    // Helper to check if post tags contain `vim`
    var tagsIncludeVim = function () {
        var tags = document.getElementsByClassName('post-tag');
        for (var i = 0; i < tags.length; i++) {
            var t = tags[i];
            if (t.textContent.includes("vim")) {
                return true;
            }
        }
        return false;
    };
    // Run by default only on (meta)vi.se, or if the post tags contain `vim`.
    if (!window.location.hostname.endsWith("vi.stackexchange.com") && !tagsIncludeVim()) {
        console.log('Not highlighting!');
        return;
    }

    var setLanguage = function () {
        var pres = document.getElementsByTagName('pre');
        for (var i = 0; i < pres.length; i++) {
            var p = pres[i];
            // If already highlighted or language has been specified manually
            if (/prettyprint(?:ed|-override)/.test(p.className)) {
                continue;
            }
            p.className = 'lang-vim prettyprint';
        }
        prettyPrint();
    };

    var langscript = document.createElement("script");
    langscript.type = 'text/javascript';

    /*
    Since Github blocks hotlinking of scripts, and I really don't feel
    like using a third-party site for it, I'll fetch the script
    manually...
    */
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
            langscript.appendChild(document.createTextNode(xhr.responseText));
        }

        /*
        Need to ensure Prettify is loaded.
        See http://meta.stackexchange.com/a/278614/270345
        */
        StackExchange.using('prettify', function () {
            document.body.appendChild(langscript);
            observer = new MutationObserver(setLanguage);
            observer.observe(document.body, {childList: true});
        });
    };
    xhr.open("GET", "https://raw.githubusercontent.com/hail2u/google-code-prettify-language-handlers/master/lang-vim.js", true);
    xhr.send();
});

Intended targets:

  • Supported versions of Google Chrome and Firefox. IE is not in my mind.

Known problems:

  • At first run, syntax highlighting is enabled but for a default language. I think this is due to caching of some sort, since it works fine after a refresh. I don't think it's a bug in the code.

Future plans:

  • Add a UI to allow specifying alternate extension URLs and languages and disable the extension. (I'm not asking how to do that, but if there are parts of the code that should be encapsulated for that purpose, do tell.)
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.