js/hirust.js 3.4 KiB raw
1
(function (hirust) {
2
//
3
// hirust - Rust Syntax Highlighter
4
//
5
// Copyright (c) 2020 Alexis Sellier
6
//
7
8
// All elements which match this will be syntax highlighted.
9
var selector = hirust || '.language-rust';
10
11
var keywords = ('fn pub if else for while break match struct enum type let impl use mod self '
12
               +'continue return true false loop in unsafe where crate super').split(' '),
13
    special  = ('Ok Err Result').split(' '),
14
    traits   = ('Eq PartialEq Ord PartialOrd Copy Clone Debug Default Sync Send Sized').split(' ');
15
16
// Syntax definition.
17
//
18
// The key becomes the class name of the <span> around the matched block of code.
19
var syntax = [
20
  ['comment', /(\/\/[^\n]*)/g],
21
  ['string' , /("(?:(?!")[^\\\n]|\\.)*"|'[^\\\n']')/g],
22
  ['attr'   , /(#\[[^\]]+\])/g],
23
  ['number' , /\b([0-9]+(?:\.[0-9]+)?)\b/g],
24
  ['ref'    , /(&mut\b|\bmut\b|&)\b/g],
25
  ['op'     , /(::|\.\.)/g],
26
  ['macro'  , /\b(println!|eprintln!|panic!|assert!|assert_eq!)/g],
27
  ['trait'  , new(RegExp)('\\b(' + traits.join('|') + ')\\b', 'g')],
28
  ['keyword', new(RegExp)('\\b(' + keywords.join('|') + ')\\b', 'g')],
29
  ['special', new(RegExp)('\\b(' + special.join('|') + ')\\b', 'g')]
30
];
31
var nodes, table = {};
32
33
if (/^[a-z]+$/.test(selector)) {
34
    nodes = document.getElementsByTagName(selector);
35
} else if (/^\.[\w-]+$/.test(selector)) {
36
    nodes = document.getElementsByClassName(selector.slice(1));
37
} else if (document.querySelectorAll) {
38
    nodes = document.querySelectorAll(selector);
39
} else {
40
    nodes = [];
41
}
42
43
for (var i = 0, children; i < nodes.length; i++) {
44
    children = nodes[i].childNodes;
45
46
    for (var j = 0, str; j < children.length; j++) {
47
        code = children[j];
48
49
        if (code.length >= 0) { // It's a text node
50
            // Don't highlight command-line snippets
51
            if (! /^\$\s/.test(code.nodeValue.trim())) {
52
                syntax.forEach(function (s) {
53
                    var k = s[0], v = s[1];
54
                    code.nodeValue = code.nodeValue.replace(v, function (_, m) {
55
                        return '\u00ab' + encode(k) + '\u00b7'
56
                                        + encode(m) +
57
                               '\u00b7' + encode(k) + '\u00bb';
58
                    });
59
                });
60
            }
61
        }
62
    }
63
}
64
65
for (var i = 0; i < nodes.length; i++) {
66
    nodes[i].innerHTML =
67
        nodes[i].innerHTML.replace(/\u00ab(.+?)\u00b7(.+?)\u00b7\1\u00bb/g,
68
            function (_, name, value) {
69
                value = value.replace(/\u00ab[^\u00b7]+\u00b7/g, '')
70
                             .replace(/\u00b7[^\u00bb]+\u00bb/g, '');
71
72
                return '<span class="' + decode(name) + '">'
73
                                       + escape(decode(value))
74
                                       + '</span>';
75
            });
76
}
77
78
function escape(str) {
79
    return str.replace(/</g, '&lt;').replace(/>/g, '&gt;');
80
}
81
82
// Encode ASCII characters to, and from Braille
83
function encode (str, encoded) {
84
    table[encoded = str.split('').map(function (s) {
85
        if (s.charCodeAt(0) > 127) { return s }
86
        return String.fromCharCode(s.charCodeAt(0) + 0x2800);
87
    }).join('')] = str;
88
89
    return encoded;
90
}
91
92
function decode (str) {
93
    if (str in table) {
94
        return table[str];
95
    } else {
96
        return str.trim().split('').map(function (s) {
97
            if (s.charCodeAt(0) - 0x2800 > 127) { return s }
98
            return String.fromCharCode(s.charCodeAt(0) - 0x2800);
99
        }).join('');
100
    }
101
}
102
103
})(window.hirust);