summaryrefslogtreecommitdiff
path: root/microlight.js
blob: 597ef1360863af409f37357001a029e865b86ac1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/**
 * @fileoverview microlight - syntax highlightning library
 * @version 0.0.7
 *
 * @license MIT, see http://github.com/asvd/microlight
 * @copyright 2016 asvd <heliosframework@gmail.com>
 *
 * Code structure aims at minimizing the compressed library size
 */


( function () {
    // for better compression
    var _window       = window,
        _document     = document,
        appendChild   = 'appendChild',
        test          = 'test',

        i,
        microlighted,
        el;  // current microlighted element to run through

    // nodes to highlight
    microlighted = _document.querySelectorAll('code');

    for (i = 0; el = microlighted[i++];) {
        var text  = el.textContent,
            pos   = 0,       // current position
            next1 = text[0], // next character
            chr   = 1,       // current character
            prev1,           // previous character
            prev2,           // the one before the previous
            token =          // current token content
            el.innerHTML = '',  // (and cleaning the node)
            
            // current token type:
            //  0: anything else (whitespaces / newlines)
            //  1: operator or brace
            //  2: closing braces (after which '/' is division not regex)
            //  3: (key)word
            //  4: regex
            //  5: string starting with "
            //  6: string starting with '
            //  7: xml comment  <!-- -->
            //  8: multiline comment /* */
            //  9: single-line comment starting with two slashes //
            // 10: single-line comment starting with hash #
            tokenType = 0,

            // kept to determine between regex and division
            lastTokenType,
            // flag determining if token is multi-character
            multichar,
            // first token of line
            firstToken,
            node;

        // running through characters and highlighting
        while (prev2 = prev1,
               // escaping if needed (with except for comments)
               // pervious character will not be therefore
               // recognized as a token finalize condition
               prev1 = tokenType < 7 && prev1 == '\\' ? 1 : chr
        ) {
            chr = next1;
            next1=text[++pos];
            multichar = token.length > 1;

            // checking if current token should be finalized
            if (!chr  || // end of content
                // newline
                chr == '\n' || prev1 == '\n' ||
                [ // finalize conditions for other token types
                    // 0: whitespaces
                    /\S/[test](chr),  // merged together
                    // 1: operators
                    1,                // consist of a single character
                    // 2: braces
                    1,                // consist of a single character
                    // 3: (key)word
                    !/[$\w]/[test](chr),
                    // 4: regex
                    (prev1 == '/' || prev1 == '\n') && multichar,
                    // 5: string with "
                    prev1 == '"' && multichar,
                    // 6: string with '
                    prev1 == "'" && multichar,
                    // 7: xml comment
                    text[pos-4]+prev2+prev1 == '-->',
                    // 8: multiline comment
                    prev2+prev1 == '*/'
                ][tokenType]
            ) {
                // appending the token to the result
                if (token) {
                    // remapping token type into style
                    // (some types are highlighted similarly)
                    el[appendChild](
                        node = _document.createElement('span')
                    ).setAttribute('class', 'f'+(firstToken|0)+' c'+(
                        // not formatted
                        !tokenType ? 0 :
                        // diff
                        tokenType > 10 ? tokenType :
                        // punctuation
                        tokenType < 3 ? 2 :
                        // comments
                        tokenType > 6 ? 4 :
                        // regex and strings
                        tokenType > 3 ? 3 :
                        // otherwise tokenType == 3, (key)word
                        // (1 if regexp matches, 0 otherwise)
                        + /^(a(bstract|lias|nd|rguments|rray|s(m|sert)?|uto)|b(ase|egin|ool(ean)?|reak|yte)|c(ase|atch|har|hecked|lass|lone|ompl|onst|ontinue)|de(bugger|cimal|clare|f(ault|er)?|init|l(egate|ete)?)|do|double|e(cho|ls?if|lse(if)?|nd|nsure|num|vent|x(cept|ec|p(licit|ort)|te(nds|nsion|rn)))|f(allthrough|alse|inal(ly)?|ixed|loat|or(each)?|riend|rom|unc(tion)?)|global|goto|guard|#?i(f|mp(lements|licit|ort)|n(it|clude(_once)?|line|out|stanceof|t(erface|ernal)?)?|s)|l(ambda|et|ock|ong)|m(icrolight|odule|utable)|NaN|n(amespace|ative|ext|ew|il|ot|ull)|o(bject|perator|r|ut|verride)|p(ackage|arams|rivate|rotected|rotocol|ublic)|r(aise|e(adonly|do|f|gister|peat|quire(_once)?|scue|strict|try|turn))|s(byte|ealed|elf|hort|igned|izeof|tatic|tring|truct|ubscript|uper|ynchronized|witch)|t(emplate|hen|his|hrows?|ransient|rue|ry|ype(alias|def|id|name|of))|u(n(checked|def(ined)?|ion|less|signed|til)|se|sing)|v(ar|irtual|oid|olatile)|w(char_t|hen|here|hile|ith)|xor|yield)$/[test](token)
                    ));

                    node[appendChild](_document.createTextNode(token));
                }

                // saving the previous token type
                // (skipping whitespaces and comments)
                lastTokenType =
                    (tokenType && tokenType < 7) ?
                    tokenType : lastTokenType;

                // initializing a new token
                token = '';

                // first token of line
                firstToken = pos < 2 || prev1 == '\n';

                // determining the new token type (going up the
                // list until matching a token type start
                // condition)
                tokenType = 15;
                while (![
                    1,                   //  0: whitespace
                                         //  1: operator or braces
                    /[\/{}[(\-+*=<>:;|\\.,?!&@~]/[test](chr),
                    /[\])]/[test](chr),  //  2: closing brace
                    /[#$\w]/[test](chr), //  3: (key)word
                    chr == '/' &&        //  4: regex
                        // previous token was an
                        // opening brace or an
                        // operator (otherwise
                        // division, not a regex)
                        (lastTokenType < 2) &&
                        // workaround for xml
                        // closing tags
                        prev1 != '<',
                    chr == '"',          //  5: string with "
                    chr == "'",          //  6: string with '
                                         //  7: xml comment
                    chr+next1+text[pos+1]+text[pos+2] == '<!--',
                    chr+next1 == '/*',   //  8: multiline comment
                    chr+next1 == '//',   //  9: single-line comment
                                         // 10: hash-style comment
                    chr == '#' && next1+text[pos+1]+text[pos+2] != 'inc',
                                         // 11: diff add
                    firstToken && chr == '+',
                                         // 12: diff remove
                    firstToken && chr == '-',
                                         // 13: diff compared
                    firstToken && (chr+next1+text[pos+1] == '+++' || chr+next1+text[pos+1] == '---'),
                                         // 14: diff offset
                    firstToken && chr+next1 == '@@'
                ][--tokenType]);
            }

            token += chr;
        }
    }
} )();