summaryrefslogtreecommitdiff
path: root/proselight.js
blob: 16b2f1e671fc57e1f6ac06350a9eb5137b1fe16d (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
/**
 * @fileoverview proselight, based on 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 (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['exports'], factory);
    } else if (typeof exports !== 'undefined') {
        factory(exports);
    } else {
        factory((root.microlight = {}));
    }
}(this, function (exports) {
    // for better compression
    var _window       = window,
        _document     = document,
        appendChild   = 'appendChild',
        test          = 'test',

        i,
        microlighted,
        cn, //child nodes
        el; // current microlighted element to run through


    
    var reset = function() {
        // nodes to highlight
        microlighted = _document.querySelectorAll('p');

        for (i = 0; el = microlighted[i++];) {
            cn = Array.from(el.childNodes);
            for (j = 0; j < cn.length; j++) {
                if (cn[j].nodeType != Node.TEXT_NODE) {
                    el.appendChild(cn[j]);
                    continue;
                }
                el.removeChild(cn[j]);
                var text  = cn[j].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
                    
                    // current token type:
                    tokenType = 0,

                    // flag determining if token is multi-character
                    multichar,
                    node;

                // running through characters and highlighting
                while (prev2 = prev1, prev1 = chr) {
                    chr = next1;
                    next1=text[++pos];
                    multichar = token.length > 1;

                    // checking if current token should be finalized
                    if (!chr  || // end of content
                        [ // finalize conditions for other token types
                            // 0: unformatted
                            /[":;,\\.?!\])\/{}[(|]/[test](chr),
                            // 1: parentesis or braces
                            /[\]){}[(]/[test](prev1) && multichar,
                            // 2: terminators
                            1,                // consist of a single character
                            // 3: separators
                            1,                // consist of a single character
                            // 4: quotes
                            prev1 == '"' && multichar,
                        ][tokenType]
                    ) {
                        // appending the token to the result
                        if (token) {
                            // map token type into class
                            el[appendChild](
                                node = _document.createElement('span')
                            ).setAttribute('class', 'ph'+tokenType);

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

                        // initializing a new token
                        token = '';

                        // determining the new token type (going up the
                        // list until matching a token type start
                        // condition)
                        tokenType = 5;
                        while (![
                            1,                         //  0: unformatted
                            /[\]){}[(]/[test](chr),    //  1: parenthesis or braces
                            /[\\.?!]/[test](chr),      //  2: terminators
                            /[:;,]/[test](chr),        //  3: separators
                            chr == '"',                //  4: quotes
                        ][--tokenType]);
                    }

                    token += chr;
                }
            }
        }
    }

    exports.reset = reset;

    if (_document.readyState == 'complete') {
        reset();
    } else {
        _window.addEventListener('load', function(){reset()}, 0);
    }
}));