c3f57c0e2599754d78b584b705ac3411cb208a25
[yaffs-website] / node_modules / uncss / node_modules / postcss / lib / tokenize.js
1 'use strict';
2
3 exports.__esModule = true;
4 exports.default = tokenize;
5 var SINGLE_QUOTE = 39;
6 var DOUBLE_QUOTE = 34;
7 var BACKSLASH = 92;
8 var SLASH = 47;
9 var NEWLINE = 10;
10 var SPACE = 32;
11 var FEED = 12;
12 var TAB = 9;
13 var CR = 13;
14 var OPEN_PARENTHESES = 40;
15 var CLOSE_PARENTHESES = 41;
16 var OPEN_CURLY = 123;
17 var CLOSE_CURLY = 125;
18 var SEMICOLON = 59;
19 var ASTERICK = 42;
20 var COLON = 58;
21 var AT = 64;
22
23 var RE_AT_END = /[ \n\t\r\f\{\(\)'"\\;/]/g;
24 var RE_WORD_END = /[ \n\t\r\f\(\)\{\}:;@!'"\\]|\/(?=\*)/g;
25 var RE_BAD_BRACKET = /.[\\\/\("'\n]/;
26
27 function tokenize(input) {
28     var tokens = [];
29     var css = input.css.valueOf();
30
31     var code = void 0,
32         next = void 0,
33         quote = void 0,
34         lines = void 0,
35         last = void 0,
36         content = void 0,
37         escape = void 0,
38         nextLine = void 0,
39         nextOffset = void 0,
40         escaped = void 0,
41         escapePos = void 0,
42         prev = void 0,
43         n = void 0;
44
45     var length = css.length;
46     var offset = -1;
47     var line = 1;
48     var pos = 0;
49
50     function unclosed(what) {
51         throw input.error('Unclosed ' + what, line, pos - offset);
52     }
53
54     while (pos < length) {
55         code = css.charCodeAt(pos);
56
57         if (code === NEWLINE || code === FEED || code === CR && css.charCodeAt(pos + 1) !== NEWLINE) {
58             offset = pos;
59             line += 1;
60         }
61
62         switch (code) {
63             case NEWLINE:
64             case SPACE:
65             case TAB:
66             case CR:
67             case FEED:
68                 next = pos;
69                 do {
70                     next += 1;
71                     code = css.charCodeAt(next);
72                     if (code === NEWLINE) {
73                         offset = next;
74                         line += 1;
75                     }
76                 } while (code === SPACE || code === NEWLINE || code === TAB || code === CR || code === FEED);
77
78                 tokens.push(['space', css.slice(pos, next)]);
79                 pos = next - 1;
80                 break;
81
82             case OPEN_CURLY:
83                 tokens.push(['{', '{', line, pos - offset]);
84                 break;
85
86             case CLOSE_CURLY:
87                 tokens.push(['}', '}', line, pos - offset]);
88                 break;
89
90             case COLON:
91                 tokens.push([':', ':', line, pos - offset]);
92                 break;
93
94             case SEMICOLON:
95                 tokens.push([';', ';', line, pos - offset]);
96                 break;
97
98             case OPEN_PARENTHESES:
99                 prev = tokens.length ? tokens[tokens.length - 1][1] : '';
100                 n = css.charCodeAt(pos + 1);
101                 if (prev === 'url' && n !== SINGLE_QUOTE && n !== DOUBLE_QUOTE && n !== SPACE && n !== NEWLINE && n !== TAB && n !== FEED && n !== CR) {
102                     next = pos;
103                     do {
104                         escaped = false;
105                         next = css.indexOf(')', next + 1);
106                         if (next === -1) unclosed('bracket');
107                         escapePos = next;
108                         while (css.charCodeAt(escapePos - 1) === BACKSLASH) {
109                             escapePos -= 1;
110                             escaped = !escaped;
111                         }
112                     } while (escaped);
113
114                     tokens.push(['brackets', css.slice(pos, next + 1), line, pos - offset, line, next - offset]);
115                     pos = next;
116                 } else {
117                     next = css.indexOf(')', pos + 1);
118                     content = css.slice(pos, next + 1);
119
120                     if (next === -1 || RE_BAD_BRACKET.test(content)) {
121                         tokens.push(['(', '(', line, pos - offset]);
122                     } else {
123                         tokens.push(['brackets', content, line, pos - offset, line, next - offset]);
124                         pos = next;
125                     }
126                 }
127
128                 break;
129
130             case CLOSE_PARENTHESES:
131                 tokens.push([')', ')', line, pos - offset]);
132                 break;
133
134             case SINGLE_QUOTE:
135             case DOUBLE_QUOTE:
136                 quote = code === SINGLE_QUOTE ? '\'' : '"';
137                 next = pos;
138                 do {
139                     escaped = false;
140                     next = css.indexOf(quote, next + 1);
141                     if (next === -1) unclosed('quote');
142                     escapePos = next;
143                     while (css.charCodeAt(escapePos - 1) === BACKSLASH) {
144                         escapePos -= 1;
145                         escaped = !escaped;
146                     }
147                 } while (escaped);
148
149                 content = css.slice(pos, next + 1);
150                 lines = content.split('\n');
151                 last = lines.length - 1;
152
153                 if (last > 0) {
154                     nextLine = line + last;
155                     nextOffset = next - lines[last].length;
156                 } else {
157                     nextLine = line;
158                     nextOffset = offset;
159                 }
160
161                 tokens.push(['string', css.slice(pos, next + 1), line, pos - offset, nextLine, next - nextOffset]);
162
163                 offset = nextOffset;
164                 line = nextLine;
165                 pos = next;
166                 break;
167
168             case AT:
169                 RE_AT_END.lastIndex = pos + 1;
170                 RE_AT_END.test(css);
171                 if (RE_AT_END.lastIndex === 0) {
172                     next = css.length - 1;
173                 } else {
174                     next = RE_AT_END.lastIndex - 2;
175                 }
176                 tokens.push(['at-word', css.slice(pos, next + 1), line, pos - offset, line, next - offset]);
177                 pos = next;
178                 break;
179
180             case BACKSLASH:
181                 next = pos;
182                 escape = true;
183                 while (css.charCodeAt(next + 1) === BACKSLASH) {
184                     next += 1;
185                     escape = !escape;
186                 }
187                 code = css.charCodeAt(next + 1);
188                 if (escape && code !== SLASH && code !== SPACE && code !== NEWLINE && code !== TAB && code !== CR && code !== FEED) {
189                     next += 1;
190                 }
191                 tokens.push(['word', css.slice(pos, next + 1), line, pos - offset, line, next - offset]);
192                 pos = next;
193                 break;
194
195             default:
196                 if (code === SLASH && css.charCodeAt(pos + 1) === ASTERICK) {
197                     next = css.indexOf('*/', pos + 2) + 1;
198                     if (next === 0) unclosed('comment');
199
200                     content = css.slice(pos, next + 1);
201                     lines = content.split('\n');
202                     last = lines.length - 1;
203
204                     if (last > 0) {
205                         nextLine = line + last;
206                         nextOffset = next - lines[last].length;
207                     } else {
208                         nextLine = line;
209                         nextOffset = offset;
210                     }
211
212                     tokens.push(['comment', content, line, pos - offset, nextLine, next - nextOffset]);
213
214                     offset = nextOffset;
215                     line = nextLine;
216                     pos = next;
217                 } else {
218                     RE_WORD_END.lastIndex = pos + 1;
219                     RE_WORD_END.test(css);
220                     if (RE_WORD_END.lastIndex === 0) {
221                         next = css.length - 1;
222                     } else {
223                         next = RE_WORD_END.lastIndex - 2;
224                     }
225
226                     tokens.push(['word', css.slice(pos, next + 1), line, pos - offset, line, next - offset]);
227                     pos = next;
228                 }
229
230                 break;
231         }
232
233         pos++;
234     }
235
236     return tokens;
237 }
238 module.exports = exports['default'];