mirror of
https://github.com/hanzoai/postcss.git
synced 2026-09-24 17:01:56 +00:00
221 lines
6.9 KiB
JavaScript
221 lines
6.9 KiB
JavaScript
var singleQuote = "'".charCodeAt(0),
|
|
doubleQuote = '"'.charCodeAt(0),
|
|
backslash = '\\'.charCodeAt(0),
|
|
slash = '/'.charCodeAt(0),
|
|
newline = '\n'.charCodeAt(0),
|
|
space = ' '.charCodeAt(0),
|
|
feed = '\f'.charCodeAt(0),
|
|
tab = '\t'.charCodeAt(0),
|
|
cr = '\r'.charCodeAt(0),
|
|
openBracket = '('.charCodeAt(0),
|
|
closeBracket = ')'.charCodeAt(0),
|
|
openCurly = '{'.charCodeAt(0),
|
|
closeCurly = '}'.charCodeAt(0),
|
|
semicolon = ';'.charCodeAt(0),
|
|
asterisk = '*'.charCodeAt(0),
|
|
colon = ':'.charCodeAt(0),
|
|
at = '@'.charCodeAt(0),
|
|
atEnd = /[ \n\t\r\{\(\)'"\\/]/g,
|
|
wordEnd = /[ \n\t\r\(\)\{\}:;@!'"\\]|\/(?=\*)/g,
|
|
badBracket = /.[\\\/\("'\n]/;
|
|
|
|
export default function (input) {
|
|
var tokens = [];
|
|
var css = input.css.valueOf();
|
|
|
|
var code, next, quote, lines, last, content, escape,
|
|
nextLine, nextOffset, escaped, escapePos, bad;
|
|
|
|
var length = css.length;
|
|
var offset = -1;
|
|
var line = 1;
|
|
var pos = 0;
|
|
|
|
var unclosed = function (what, end) {
|
|
if ( input.safe ) {
|
|
css += end;
|
|
next = length - 1;
|
|
} else {
|
|
throw input.error('Unclosed ' + what, line, pos - offset);
|
|
}
|
|
};
|
|
|
|
while ( pos < length ) {
|
|
code = css.charCodeAt(pos);
|
|
|
|
if ( code == newline ) {
|
|
offset = pos;
|
|
line += 1;
|
|
}
|
|
|
|
switch ( code ) {
|
|
case newline:
|
|
case space:
|
|
case tab:
|
|
case cr:
|
|
case feed:
|
|
next = pos;
|
|
do {
|
|
next += 1;
|
|
code = css.charCodeAt(next);
|
|
if ( code == newline ) {
|
|
offset = next;
|
|
line += 1;
|
|
}
|
|
} while ( code == space ||
|
|
code == newline ||
|
|
code == tab ||
|
|
code == cr ||
|
|
code == feed );
|
|
|
|
tokens.push(['space', css.slice(pos, next)]);
|
|
pos = next - 1;
|
|
break;
|
|
|
|
case openCurly:
|
|
tokens.push(['{', '{', line, pos - offset]);
|
|
break;
|
|
|
|
case closeCurly:
|
|
tokens.push(['}', '}', line, pos - offset]);
|
|
break;
|
|
|
|
case colon:
|
|
tokens.push([':', ':', line, pos - offset]);
|
|
break;
|
|
|
|
case semicolon:
|
|
tokens.push([';', ';', line, pos - offset]);
|
|
break;
|
|
|
|
case openBracket:
|
|
next = css.indexOf(')', pos + 1);
|
|
content = css.slice(pos, next + 1);
|
|
|
|
if ( next == -1 || badBracket.test(content) ) {
|
|
tokens.push(['(', '(', line, pos - offset]);
|
|
} else {
|
|
tokens.push(['brackets', content,
|
|
line, pos - offset,
|
|
line, next - offset
|
|
]);
|
|
pos = next;
|
|
}
|
|
|
|
break;
|
|
|
|
case closeBracket:
|
|
tokens.push([')', ')', line, pos - offset]);
|
|
break;
|
|
|
|
case singleQuote:
|
|
case doubleQuote:
|
|
quote = code == singleQuote ? "'" : '"';
|
|
next = pos;
|
|
do {
|
|
escaped = false;
|
|
next = css.indexOf(quote, next + 1);
|
|
if ( next == -1 ) unclosed('quote', quote);
|
|
escapePos = next;
|
|
while ( css.charCodeAt(escapePos - 1) == backslash ) {
|
|
escapePos -= 1;
|
|
escaped = !escaped;
|
|
}
|
|
} while ( escaped );
|
|
|
|
tokens.push(['string', css.slice(pos, next + 1),
|
|
line, pos - offset,
|
|
line, next - offset
|
|
]);
|
|
pos = next;
|
|
break;
|
|
|
|
case at:
|
|
atEnd.lastIndex = pos + 1;
|
|
atEnd.test(css);
|
|
if ( atEnd.lastIndex === 0 ) {
|
|
next = css.length - 1;
|
|
} else {
|
|
next = atEnd.lastIndex - 2;
|
|
}
|
|
tokens.push(['at-word', css.slice(pos, next + 1),
|
|
line, pos - offset,
|
|
line, next - offset
|
|
]);
|
|
pos = next;
|
|
break;
|
|
|
|
case backslash:
|
|
next = pos;
|
|
escape = true;
|
|
while ( css.charCodeAt(next + 1) == backslash ) {
|
|
next += 1;
|
|
escape = !escape;
|
|
}
|
|
code = css.charCodeAt(next + 1);
|
|
if ( escape && (code != slash &&
|
|
code != space &&
|
|
code != newline &&
|
|
code != tab &&
|
|
code != cr &&
|
|
code != feed ) ) {
|
|
next += 1;
|
|
}
|
|
tokens.push(['word', css.slice(pos, next + 1),
|
|
line, pos - offset,
|
|
line, next - offset
|
|
]);
|
|
pos = next;
|
|
break;
|
|
|
|
default:
|
|
if ( code == slash && css.charCodeAt(pos + 1) == asterisk ) {
|
|
next = css.indexOf('*/', pos + 2) + 1;
|
|
if ( next === 0 ) unclosed('comment', '*/');
|
|
|
|
content = css.slice(pos, next + 1);
|
|
lines = content.split('\n');
|
|
last = lines.length - 1;
|
|
|
|
if ( last > 0 ) {
|
|
nextLine = line + last;
|
|
nextOffset = next - lines[last].length;
|
|
} else {
|
|
nextLine = line;
|
|
nextOffset = offset;
|
|
}
|
|
|
|
tokens.push(['comment', content,
|
|
line, pos - offset,
|
|
nextLine, next - nextOffset
|
|
]);
|
|
|
|
offset = nextOffset;
|
|
line = nextLine;
|
|
pos = next;
|
|
|
|
} else {
|
|
wordEnd.lastIndex = pos + 1;
|
|
wordEnd.test(css);
|
|
if ( wordEnd.lastIndex === 0 ) {
|
|
next = css.length - 1;
|
|
} else {
|
|
next = wordEnd.lastIndex - 2;
|
|
}
|
|
|
|
tokens.push(['word', css.slice(pos, next + 1),
|
|
line, pos - offset,
|
|
line, next - offset
|
|
]);
|
|
pos = next;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
pos++;
|
|
}
|
|
|
|
return tokens;
|
|
}
|