123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392 |
- "use strict";
- var SINGLE_QUOTE = '\''.charCodeAt(0);
- var DOUBLE_QUOTE = '"'.charCodeAt(0);
- var BACKSLASH = '\\'.charCodeAt(0);
- var SLASH = '/'.charCodeAt(0);
- var NEWLINE = '\n'.charCodeAt(0);
- var SPACE = ' '.charCodeAt(0);
- var FEED = '\f'.charCodeAt(0);
- var TAB = '\t'.charCodeAt(0);
- var CR = '\r'.charCodeAt(0);
- var OPEN_SQUARE = '['.charCodeAt(0);
- var CLOSE_SQUARE = ']'.charCodeAt(0);
- var OPEN_PARENTHESES = '('.charCodeAt(0);
- var CLOSE_PARENTHESES = ')'.charCodeAt(0);
- var OPEN_CURLY = '{'.charCodeAt(0);
- var CLOSE_CURLY = '}'.charCodeAt(0);
- var SEMICOLON = ';'.charCodeAt(0);
- var ASTERISK = '*'.charCodeAt(0);
- var COLON = ':'.charCodeAt(0);
- var AT = '@'.charCodeAt(0);
- var COMMA = ','.charCodeAt(0);
- var HASH = '#'.charCodeAt(0);
- var RE_AT_END = /[ \n\t\r\f{}()'"\\;/[\]#]/g;
- var RE_WORD_END = /[ \n\t\r\f(){}:;@!'"\\\][#]|\/(?=\*)/g;
- var RE_BAD_BRACKET = /.[\\/("'\n]/;
- var RE_HEX_ESCAPE = /[a-f0-9]/i;
- var RE_NEW_LINE = /[\r\f\n]/g;
- module.exports = function scssTokenize(input, options) {
- if (options === void 0) {
- options = {};
- }
- var css = input.css.valueOf();
- var ignore = options.ignoreErrors;
- var code, next, quote, lines, last, content, escape, nextLine, nextOffset, escaped, prev, n, currentToken;
- var brackets;
- var length = css.length;
- var offset = -1;
- var line = 1;
- var pos = 0;
- var buffer = [];
- var returned = [];
- function unclosed(what) {
- throw input.error('Unclosed ' + what, line, pos - offset);
- }
- function endOfFile() {
- return returned.length === 0 && pos >= length;
- }
- function interpolation() {
- var deep = 1;
- var stringQuote = false;
- var stringEscaped = false;
- while (deep > 0) {
- next += 1;
- if (css.length <= next) unclosed('interpolation');
- code = css.charCodeAt(next);
- n = css.charCodeAt(next + 1);
- if (stringQuote) {
- if (!stringEscaped && code === stringQuote) {
- stringQuote = false;
- stringEscaped = false;
- } else if (code === BACKSLASH) {
- stringEscaped = !escaped;
- } else if (stringEscaped) {
- stringEscaped = false;
- }
- } else if (code === SINGLE_QUOTE || code === DOUBLE_QUOTE) {
- stringQuote = code;
- } else if (code === CLOSE_CURLY) {
- deep -= 1;
- } else if (code === HASH && n === OPEN_CURLY) {
- deep += 1;
- }
- }
- }
- function nextToken() {
- if (returned.length) return returned.pop();
- if (pos >= length) return;
- code = css.charCodeAt(pos);
- if (code === NEWLINE || code === FEED || code === CR && css.charCodeAt(pos + 1) !== 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);
- currentToken = ['space', css.slice(pos, next)];
- pos = next - 1;
- break;
- case OPEN_SQUARE:
- currentToken = ['[', '[', line, pos - offset];
- break;
- case CLOSE_SQUARE:
- currentToken = [']', ']', line, pos - offset];
- break;
- case OPEN_CURLY:
- currentToken = ['{', '{', line, pos - offset];
- break;
- case CLOSE_CURLY:
- currentToken = ['}', '}', line, pos - offset];
- break;
-
- case COMMA:
- currentToken = ['word', ',', line, pos - offset, line, pos - offset + 1];
- break;
-
- case COLON:
- currentToken = [':', ':', line, pos - offset];
- break;
- case SEMICOLON:
- currentToken = [';', ';', line, pos - offset];
- break;
- case OPEN_PARENTHESES:
- prev = buffer.length ? buffer.pop()[1] : '';
- n = css.charCodeAt(pos + 1);
- if (prev === 'url' && n !== SINGLE_QUOTE && n !== DOUBLE_QUOTE) {
- brackets = 1;
- escaped = false;
- next = pos + 1;
- while (next <= css.length - 1) {
- n = css.charCodeAt(next);
- if (n === BACKSLASH) {
- escaped = !escaped;
- } else if (n === OPEN_PARENTHESES) {
- brackets += 1;
- } else if (n === CLOSE_PARENTHESES) {
- brackets -= 1;
- if (brackets === 0) break;
- }
- next += 1;
- }
- 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;
- }
- currentToken = ['brackets', content, line, pos - offset, nextLine, next - nextOffset];
- offset = nextOffset;
- line = nextLine;
- pos = next;
- } else {
- next = css.indexOf(')', pos + 1);
- content = css.slice(pos, next + 1);
- if (next === -1 || RE_BAD_BRACKET.test(content)) {
- currentToken = ['(', '(', line, pos - offset];
- } else {
- currentToken = ['brackets', content, line, pos - offset, line, next - offset];
- pos = next;
- }
- }
- break;
- case CLOSE_PARENTHESES:
- currentToken = [')', ')', line, pos - offset];
- break;
- case SINGLE_QUOTE:
- case DOUBLE_QUOTE:
-
- quote = code;
- next = pos;
- escaped = false;
- while (next < length) {
- next++;
- if (next === length) unclosed('string');
- code = css.charCodeAt(next);
- n = css.charCodeAt(next + 1);
- if (!escaped && code === quote) {
- break;
- } else if (code === BACKSLASH) {
- escaped = !escaped;
- } else if (escaped) {
- escaped = false;
- } else if (code === HASH && n === OPEN_CURLY) {
- interpolation();
- }
- }
- 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;
- }
- currentToken = ['string', css.slice(pos, next + 1), line, pos - offset, nextLine, next - nextOffset];
- offset = nextOffset;
- line = nextLine;
- pos = next;
- break;
- case AT:
- RE_AT_END.lastIndex = pos + 1;
- RE_AT_END.test(css);
- if (RE_AT_END.lastIndex === 0) {
- next = css.length - 1;
- } else {
- next = RE_AT_END.lastIndex - 2;
- }
- currentToken = ['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;
- if (RE_HEX_ESCAPE.test(css.charAt(next))) {
- while (RE_HEX_ESCAPE.test(css.charAt(next + 1))) {
- next += 1;
- }
- if (css.charCodeAt(next + 1) === SPACE) {
- next += 1;
- }
- }
- }
- currentToken = ['word', css.slice(pos, next + 1), line, pos - offset, line, next - offset];
- pos = next;
- break;
- default:
-
- n = css.charCodeAt(pos + 1);
- if (code === HASH && n === OPEN_CURLY) {
- next = pos;
- interpolation();
- 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;
- }
- currentToken = ['word', content, line, pos - offset, nextLine, next - nextOffset];
- offset = nextOffset;
- line = nextLine;
- pos = next;
- } else if (code === SLASH && n === ASTERISK) {
-
- next = css.indexOf('*/', pos + 2) + 1;
- if (next === 0) {
- if (ignore) {
- next = css.length;
- } else {
- 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;
- }
- currentToken = ['comment', content, line, pos - offset, nextLine, next - nextOffset];
- offset = nextOffset;
- line = nextLine;
- pos = next;
- } else if (code === SLASH && n === SLASH) {
- RE_NEW_LINE.lastIndex = pos + 1;
- RE_NEW_LINE.test(css);
- if (RE_NEW_LINE.lastIndex === 0) {
- next = css.length - 1;
- } else {
- next = RE_NEW_LINE.lastIndex - 2;
- }
- content = css.slice(pos, next + 1);
- currentToken = ['comment', content, line, pos - offset, line, next - offset, 'inline'];
- pos = next;
- } else {
- RE_WORD_END.lastIndex = pos + 1;
- RE_WORD_END.test(css);
- if (RE_WORD_END.lastIndex === 0) {
- next = css.length - 1;
- } else {
- next = RE_WORD_END.lastIndex - 2;
- }
- currentToken = ['word', css.slice(pos, next + 1), line, pos - offset, line, next - offset];
- buffer.push(currentToken);
- pos = next;
- }
- break;
- }
- pos++;
- return currentToken;
- }
- function back(token) {
- returned.push(token);
- }
- return {
- back: back,
- nextToken: nextToken,
- endOfFile: endOfFile
- };
- };
|