123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790 |
- /*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Tobias Koppers @sokra
- */
- "use strict";
- /**
- * @typedef {object} CssTokenCallbacks
- * @property {function(string, number): boolean=} isSelector
- * @property {function(string, number, number, number, number): number=} url
- * @property {function(string, number, number): number=} string
- * @property {function(string, number, number): number=} leftParenthesis
- * @property {function(string, number, number): number=} rightParenthesis
- * @property {function(string, number, number): number=} pseudoFunction
- * @property {function(string, number, number): number=} function
- * @property {function(string, number, number): number=} pseudoClass
- * @property {function(string, number, number): number=} atKeyword
- * @property {function(string, number, number): number=} class
- * @property {function(string, number, number): number=} identifier
- * @property {function(string, number, number): number=} id
- * @property {function(string, number, number): number=} leftCurlyBracket
- * @property {function(string, number, number): number=} rightCurlyBracket
- * @property {function(string, number, number): number=} semicolon
- * @property {function(string, number, number): number=} comma
- */
- /** @typedef {function(string, number, CssTokenCallbacks): number} CharHandler */
- // spec: https://drafts.csswg.org/css-syntax/
- const CC_LINE_FEED = "\n".charCodeAt(0);
- const CC_CARRIAGE_RETURN = "\r".charCodeAt(0);
- const CC_FORM_FEED = "\f".charCodeAt(0);
- const CC_TAB = "\t".charCodeAt(0);
- const CC_SPACE = " ".charCodeAt(0);
- const CC_SOLIDUS = "/".charCodeAt(0);
- const CC_REVERSE_SOLIDUS = "\\".charCodeAt(0);
- const CC_ASTERISK = "*".charCodeAt(0);
- const CC_LEFT_PARENTHESIS = "(".charCodeAt(0);
- const CC_RIGHT_PARENTHESIS = ")".charCodeAt(0);
- const CC_LEFT_CURLY = "{".charCodeAt(0);
- const CC_RIGHT_CURLY = "}".charCodeAt(0);
- const CC_LEFT_SQUARE = "[".charCodeAt(0);
- const CC_RIGHT_SQUARE = "]".charCodeAt(0);
- const CC_QUOTATION_MARK = '"'.charCodeAt(0);
- const CC_APOSTROPHE = "'".charCodeAt(0);
- const CC_FULL_STOP = ".".charCodeAt(0);
- const CC_COLON = ":".charCodeAt(0);
- const CC_SEMICOLON = ";".charCodeAt(0);
- const CC_COMMA = ",".charCodeAt(0);
- const CC_PERCENTAGE = "%".charCodeAt(0);
- const CC_AT_SIGN = "@".charCodeAt(0);
- const CC_LOW_LINE = "_".charCodeAt(0);
- const CC_LOWER_A = "a".charCodeAt(0);
- const CC_LOWER_U = "u".charCodeAt(0);
- const CC_LOWER_E = "e".charCodeAt(0);
- const CC_LOWER_Z = "z".charCodeAt(0);
- const CC_UPPER_A = "A".charCodeAt(0);
- const CC_UPPER_E = "E".charCodeAt(0);
- const CC_UPPER_U = "U".charCodeAt(0);
- const CC_UPPER_Z = "Z".charCodeAt(0);
- const CC_0 = "0".charCodeAt(0);
- const CC_9 = "9".charCodeAt(0);
- const CC_NUMBER_SIGN = "#".charCodeAt(0);
- const CC_PLUS_SIGN = "+".charCodeAt(0);
- const CC_HYPHEN_MINUS = "-".charCodeAt(0);
- const CC_LESS_THAN_SIGN = "<".charCodeAt(0);
- const CC_GREATER_THAN_SIGN = ">".charCodeAt(0);
- /**
- * @param {number} cc char code
- * @returns {boolean} true, if cc is a newline
- */
- const _isNewLine = cc => {
- return (
- cc === CC_LINE_FEED || cc === CC_CARRIAGE_RETURN || cc === CC_FORM_FEED
- );
- };
- /** @type {CharHandler} */
- const consumeSpace = (input, pos, callbacks) => {
- /** @type {number} */
- let cc;
- do {
- pos++;
- cc = input.charCodeAt(pos);
- } while (_isWhiteSpace(cc));
- return pos;
- };
- /**
- * @param {number} cc char code
- * @returns {boolean} true, if cc is a newline
- */
- const _isNewline = cc => {
- return (
- cc === CC_LINE_FEED || cc === CC_CARRIAGE_RETURN || cc === CC_FORM_FEED
- );
- };
- /**
- * @param {number} cc char code
- * @returns {boolean} true, if cc is a space (U+0009 CHARACTER TABULATION or U+0020 SPACE)
- */
- const _isSpace = cc => {
- return cc === CC_TAB || cc === CC_SPACE;
- };
- /**
- * @param {number} cc char code
- * @returns {boolean} true, if cc is a whitespace
- */
- const _isWhiteSpace = cc => {
- return _isNewline(cc) || _isSpace(cc);
- };
- /**
- * ident-start code point
- *
- * A letter, a non-ASCII code point, or U+005F LOW LINE (_).
- *
- * @param {number} cc char code
- * @returns {boolean} true, if cc is a start code point of an identifier
- */
- const isIdentStartCodePoint = cc => {
- return (
- (cc >= CC_LOWER_A && cc <= CC_LOWER_Z) ||
- (cc >= CC_UPPER_A && cc <= CC_UPPER_Z) ||
- cc === CC_LOW_LINE ||
- cc >= 0x80
- );
- };
- /** @type {CharHandler} */
- const consumeDelimToken = (input, pos, callbacks) => {
- return pos + 1;
- };
- /** @type {CharHandler} */
- const consumeComments = (input, pos, callbacks) => {
- // If the next two input code point are U+002F SOLIDUS (/) followed by a U+002A
- // ASTERISK (*), consume them and all following code points up to and including
- // the first U+002A ASTERISK (*) followed by a U+002F SOLIDUS (/), or up to an
- // EOF code point. Return to the start of this step.
- //
- // If the preceding paragraph ended by consuming an EOF code point, this is a parse error.
- // But we are silent on errors.
- if (
- input.charCodeAt(pos) === CC_SOLIDUS &&
- input.charCodeAt(pos + 1) === CC_ASTERISK
- ) {
- pos += 1;
- while (pos < input.length) {
- if (
- input.charCodeAt(pos) === CC_ASTERISK &&
- input.charCodeAt(pos + 1) === CC_SOLIDUS
- ) {
- pos += 2;
- break;
- }
- pos++;
- }
- }
- return pos;
- };
- /** @type {function(number): CharHandler} */
- const consumeString = quote_cc => (input, pos, callbacks) => {
- const start = pos;
- pos = _consumeString(input, pos, quote_cc);
- if (callbacks.string !== undefined) {
- pos = callbacks.string(input, start, pos);
- }
- return pos;
- };
- /**
- * @param {string} input input
- * @param {number} pos position
- * @param {number} quote_cc quote char code
- * @returns {number} new position
- */
- const _consumeString = (input, pos, quote_cc) => {
- pos++;
- for (;;) {
- if (pos === input.length) return pos;
- const cc = input.charCodeAt(pos);
- if (cc === quote_cc) return pos + 1;
- if (_isNewLine(cc)) {
- // bad string
- return pos;
- }
- if (cc === CC_REVERSE_SOLIDUS) {
- // we don't need to fully parse the escaped code point
- // just skip over a potential new line
- pos++;
- if (pos === input.length) return pos;
- pos++;
- } else {
- pos++;
- }
- }
- };
- /**
- * @param {number} cc char code
- * @returns {boolean} is identifier start code
- */
- const _isIdentifierStartCode = cc => {
- return (
- cc === CC_LOW_LINE ||
- (cc >= CC_LOWER_A && cc <= CC_LOWER_Z) ||
- (cc >= CC_UPPER_A && cc <= CC_UPPER_Z) ||
- cc > 0x80
- );
- };
- /**
- * @param {number} first first code point
- * @param {number} second second code point
- * @returns {boolean} true if two code points are a valid escape
- */
- const _isTwoCodePointsAreValidEscape = (first, second) => {
- if (first !== CC_REVERSE_SOLIDUS) return false;
- if (_isNewLine(second)) return false;
- return true;
- };
- /**
- * @param {number} cc char code
- * @returns {boolean} is digit
- */
- const _isDigit = cc => {
- return cc >= CC_0 && cc <= CC_9;
- };
- /**
- * @param {string} input input
- * @param {number} pos position
- * @returns {boolean} true, if input at pos starts an identifier
- */
- const _startsIdentifier = (input, pos) => {
- const cc = input.charCodeAt(pos);
- if (cc === CC_HYPHEN_MINUS) {
- if (pos === input.length) return false;
- const cc = input.charCodeAt(pos + 1);
- if (cc === CC_HYPHEN_MINUS) return true;
- if (cc === CC_REVERSE_SOLIDUS) {
- const cc = input.charCodeAt(pos + 2);
- return !_isNewLine(cc);
- }
- return _isIdentifierStartCode(cc);
- }
- if (cc === CC_REVERSE_SOLIDUS) {
- const cc = input.charCodeAt(pos + 1);
- return !_isNewLine(cc);
- }
- return _isIdentifierStartCode(cc);
- };
- /** @type {CharHandler} */
- const consumeNumberSign = (input, pos, callbacks) => {
- const start = pos;
- pos++;
- if (pos === input.length) return pos;
- if (callbacks.isSelector(input, pos) && _startsIdentifier(input, pos)) {
- pos = _consumeIdentifier(input, pos, callbacks);
- if (callbacks.id !== undefined) {
- return callbacks.id(input, start, pos);
- }
- }
- return pos;
- };
- /** @type {CharHandler} */
- const consumeMinus = (input, pos, callbacks) => {
- const start = pos;
- pos++;
- if (pos === input.length) return pos;
- const cc = input.charCodeAt(pos);
- // If the input stream starts with a number, reconsume the current input code point, consume a numeric token, and return it.
- if (cc === CC_FULL_STOP || _isDigit(cc)) {
- return consumeNumericToken(input, pos, callbacks);
- } else if (cc === CC_HYPHEN_MINUS) {
- pos++;
- if (pos === input.length) return pos;
- const cc = input.charCodeAt(pos);
- if (cc === CC_GREATER_THAN_SIGN) {
- return pos + 1;
- } else {
- pos = _consumeIdentifier(input, pos, callbacks);
- if (callbacks.identifier !== undefined) {
- return callbacks.identifier(input, start, pos);
- }
- }
- } else if (cc === CC_REVERSE_SOLIDUS) {
- if (pos + 1 === input.length) return pos;
- const cc = input.charCodeAt(pos + 1);
- if (_isNewLine(cc)) return pos;
- pos = _consumeIdentifier(input, pos, callbacks);
- if (callbacks.identifier !== undefined) {
- return callbacks.identifier(input, start, pos);
- }
- } else if (_isIdentifierStartCode(cc)) {
- pos = consumeOtherIdentifier(input, pos - 1, callbacks);
- }
- return pos;
- };
- /** @type {CharHandler} */
- const consumeDot = (input, pos, callbacks) => {
- const start = pos;
- pos++;
- if (pos === input.length) return pos;
- const cc = input.charCodeAt(pos);
- if (_isDigit(cc)) return consumeNumericToken(input, pos - 2, callbacks);
- if (!callbacks.isSelector(input, pos) || !_startsIdentifier(input, pos))
- return pos;
- pos = _consumeIdentifier(input, pos, callbacks);
- if (callbacks.class !== undefined) return callbacks.class(input, start, pos);
- return pos;
- };
- /** @type {CharHandler} */
- const consumeNumericToken = (input, pos, callbacks) => {
- pos = _consumeNumber(input, pos, callbacks);
- if (pos === input.length) return pos;
- if (_startsIdentifier(input, pos))
- return _consumeIdentifier(input, pos, callbacks);
- const cc = input.charCodeAt(pos);
- if (cc === CC_PERCENTAGE) return pos + 1;
- return pos;
- };
- /** @type {CharHandler} */
- const consumeOtherIdentifier = (input, pos, callbacks) => {
- const start = pos;
- pos = _consumeIdentifier(input, pos, callbacks);
- if (pos !== input.length && input.charCodeAt(pos) === CC_LEFT_PARENTHESIS) {
- pos++;
- if (callbacks.function !== undefined) {
- return callbacks.function(input, start, pos);
- }
- } else {
- if (callbacks.identifier !== undefined) {
- return callbacks.identifier(input, start, pos);
- }
- }
- return pos;
- };
- /** @type {CharHandler} */
- const consumePotentialUrl = (input, pos, callbacks) => {
- const start = pos;
- pos = _consumeIdentifier(input, pos, callbacks);
- const nextPos = pos + 1;
- if (
- pos === start + 3 &&
- input.slice(start, nextPos).toLowerCase() === "url("
- ) {
- pos++;
- let cc = input.charCodeAt(pos);
- while (_isWhiteSpace(cc)) {
- pos++;
- if (pos === input.length) return pos;
- cc = input.charCodeAt(pos);
- }
- if (cc === CC_QUOTATION_MARK || cc === CC_APOSTROPHE) {
- if (callbacks.function !== undefined) {
- return callbacks.function(input, start, nextPos);
- }
- return nextPos;
- } else {
- const contentStart = pos;
- /** @type {number} */
- let contentEnd;
- for (;;) {
- if (cc === CC_REVERSE_SOLIDUS) {
- pos++;
- if (pos === input.length) return pos;
- pos++;
- } else if (_isWhiteSpace(cc)) {
- contentEnd = pos;
- do {
- pos++;
- if (pos === input.length) return pos;
- cc = input.charCodeAt(pos);
- } while (_isWhiteSpace(cc));
- if (cc !== CC_RIGHT_PARENTHESIS) return pos;
- pos++;
- if (callbacks.url !== undefined) {
- return callbacks.url(input, start, pos, contentStart, contentEnd);
- }
- return pos;
- } else if (cc === CC_RIGHT_PARENTHESIS) {
- contentEnd = pos;
- pos++;
- if (callbacks.url !== undefined) {
- return callbacks.url(input, start, pos, contentStart, contentEnd);
- }
- return pos;
- } else if (cc === CC_LEFT_PARENTHESIS) {
- return pos;
- } else {
- pos++;
- }
- if (pos === input.length) return pos;
- cc = input.charCodeAt(pos);
- }
- }
- } else {
- if (callbacks.identifier !== undefined) {
- return callbacks.identifier(input, start, pos);
- }
- return pos;
- }
- };
- /** @type {CharHandler} */
- const consumePotentialPseudo = (input, pos, callbacks) => {
- const start = pos;
- pos++;
- if (!callbacks.isSelector(input, pos) || !_startsIdentifier(input, pos))
- return pos;
- pos = _consumeIdentifier(input, pos, callbacks);
- let cc = input.charCodeAt(pos);
- if (cc === CC_LEFT_PARENTHESIS) {
- pos++;
- if (callbacks.pseudoFunction !== undefined) {
- return callbacks.pseudoFunction(input, start, pos);
- }
- return pos;
- }
- if (callbacks.pseudoClass !== undefined) {
- return callbacks.pseudoClass(input, start, pos);
- }
- return pos;
- };
- /** @type {CharHandler} */
- const consumeLeftParenthesis = (input, pos, callbacks) => {
- pos++;
- if (callbacks.leftParenthesis !== undefined) {
- return callbacks.leftParenthesis(input, pos - 1, pos);
- }
- return pos;
- };
- /** @type {CharHandler} */
- const consumeRightParenthesis = (input, pos, callbacks) => {
- pos++;
- if (callbacks.rightParenthesis !== undefined) {
- return callbacks.rightParenthesis(input, pos - 1, pos);
- }
- return pos;
- };
- /** @type {CharHandler} */
- const consumeLeftCurlyBracket = (input, pos, callbacks) => {
- pos++;
- if (callbacks.leftCurlyBracket !== undefined) {
- return callbacks.leftCurlyBracket(input, pos - 1, pos);
- }
- return pos;
- };
- /** @type {CharHandler} */
- const consumeRightCurlyBracket = (input, pos, callbacks) => {
- pos++;
- if (callbacks.rightCurlyBracket !== undefined) {
- return callbacks.rightCurlyBracket(input, pos - 1, pos);
- }
- return pos;
- };
- /** @type {CharHandler} */
- const consumeSemicolon = (input, pos, callbacks) => {
- pos++;
- if (callbacks.semicolon !== undefined) {
- return callbacks.semicolon(input, pos - 1, pos);
- }
- return pos;
- };
- /** @type {CharHandler} */
- const consumeComma = (input, pos, callbacks) => {
- pos++;
- if (callbacks.comma !== undefined) {
- return callbacks.comma(input, pos - 1, pos);
- }
- return pos;
- };
- /** @type {CharHandler} */
- const _consumeIdentifier = (input, pos) => {
- for (;;) {
- const cc = input.charCodeAt(pos);
- if (cc === CC_REVERSE_SOLIDUS) {
- pos++;
- if (pos === input.length) return pos;
- pos++;
- } else if (
- _isIdentifierStartCode(cc) ||
- _isDigit(cc) ||
- cc === CC_HYPHEN_MINUS
- ) {
- pos++;
- } else {
- return pos;
- }
- }
- };
- /** @type {CharHandler} */
- const _consumeNumber = (input, pos) => {
- pos++;
- if (pos === input.length) return pos;
- let cc = input.charCodeAt(pos);
- while (_isDigit(cc)) {
- pos++;
- if (pos === input.length) return pos;
- cc = input.charCodeAt(pos);
- }
- if (cc === CC_FULL_STOP && pos + 1 !== input.length) {
- const next = input.charCodeAt(pos + 1);
- if (_isDigit(next)) {
- pos += 2;
- cc = input.charCodeAt(pos);
- while (_isDigit(cc)) {
- pos++;
- if (pos === input.length) return pos;
- cc = input.charCodeAt(pos);
- }
- }
- }
- if (cc === CC_LOWER_E || cc === CC_UPPER_E) {
- if (pos + 1 !== input.length) {
- const next = input.charCodeAt(pos + 2);
- if (_isDigit(next)) {
- pos += 2;
- } else if (
- (next === CC_HYPHEN_MINUS || next === CC_PLUS_SIGN) &&
- pos + 2 !== input.length
- ) {
- const next = input.charCodeAt(pos + 2);
- if (_isDigit(next)) {
- pos += 3;
- } else {
- return pos;
- }
- } else {
- return pos;
- }
- }
- } else {
- return pos;
- }
- cc = input.charCodeAt(pos);
- while (_isDigit(cc)) {
- pos++;
- if (pos === input.length) return pos;
- cc = input.charCodeAt(pos);
- }
- return pos;
- };
- /** @type {CharHandler} */
- const consumeLessThan = (input, pos, callbacks) => {
- if (input.slice(pos + 1, pos + 4) === "!--") return pos + 4;
- return pos + 1;
- };
- /** @type {CharHandler} */
- const consumeAt = (input, pos, callbacks) => {
- const start = pos;
- pos++;
- if (pos === input.length) return pos;
- if (_startsIdentifier(input, pos)) {
- pos = _consumeIdentifier(input, pos, callbacks);
- if (callbacks.atKeyword !== undefined) {
- pos = callbacks.atKeyword(input, start, pos);
- }
- }
- return pos;
- };
- /** @type {CharHandler} */
- const consumeReverseSolidus = (input, pos, callbacks) => {
- const start = pos;
- pos++;
- if (pos === input.length) return pos;
- // If the input stream starts with a valid escape, reconsume the current input code point, consume an ident-like token, and return it.
- if (
- _isTwoCodePointsAreValidEscape(
- input.charCodeAt(start),
- input.charCodeAt(pos)
- )
- ) {
- return consumeOtherIdentifier(input, pos - 1, callbacks);
- }
- // Otherwise, this is a parse error. Return a <delim-token> with its value set to the current input code point.
- return pos;
- };
- const CHAR_MAP = Array.from({ length: 0x80 }, (_, cc) => {
- // https://drafts.csswg.org/css-syntax/#consume-token
- switch (cc) {
- // whitespace
- case CC_LINE_FEED:
- case CC_CARRIAGE_RETURN:
- case CC_FORM_FEED:
- case CC_TAB:
- case CC_SPACE:
- return consumeSpace;
- // U+0022 QUOTATION MARK (")
- case CC_QUOTATION_MARK:
- return consumeString(cc);
- // U+0023 NUMBER SIGN (#)
- case CC_NUMBER_SIGN:
- return consumeNumberSign;
- // U+0027 APOSTROPHE (')
- case CC_APOSTROPHE:
- return consumeString(cc);
- // U+0028 LEFT PARENTHESIS (()
- case CC_LEFT_PARENTHESIS:
- return consumeLeftParenthesis;
- // U+0029 RIGHT PARENTHESIS ())
- case CC_RIGHT_PARENTHESIS:
- return consumeRightParenthesis;
- // U+002B PLUS SIGN (+)
- case CC_PLUS_SIGN:
- return consumeNumericToken;
- // U+002C COMMA (,)
- case CC_COMMA:
- return consumeComma;
- // U+002D HYPHEN-MINUS (-)
- case CC_HYPHEN_MINUS:
- return consumeMinus;
- // U+002E FULL STOP (.)
- case CC_FULL_STOP:
- return consumeDot;
- // U+003A COLON (:)
- case CC_COLON:
- return consumePotentialPseudo;
- // U+003B SEMICOLON (;)
- case CC_SEMICOLON:
- return consumeSemicolon;
- // U+003C LESS-THAN SIGN (<)
- case CC_LESS_THAN_SIGN:
- return consumeLessThan;
- // U+0040 COMMERCIAL AT (@)
- case CC_AT_SIGN:
- return consumeAt;
- // U+005B LEFT SQUARE BRACKET ([)
- case CC_LEFT_SQUARE:
- return consumeDelimToken;
- // U+005C REVERSE SOLIDUS (\)
- case CC_REVERSE_SOLIDUS:
- return consumeReverseSolidus;
- // U+005D RIGHT SQUARE BRACKET (])
- case CC_RIGHT_SQUARE:
- return consumeDelimToken;
- // U+007B LEFT CURLY BRACKET ({)
- case CC_LEFT_CURLY:
- return consumeLeftCurlyBracket;
- // U+007D RIGHT CURLY BRACKET (})
- case CC_RIGHT_CURLY:
- return consumeRightCurlyBracket;
- // Optimization
- case CC_LOWER_U:
- case CC_UPPER_U:
- return consumePotentialUrl;
- default:
- // digit
- if (_isDigit(cc)) return consumeNumericToken;
- // ident-start code point
- if (isIdentStartCodePoint(cc)) {
- return consumeOtherIdentifier;
- }
- // EOF, but we don't have it
- // anything else
- return consumeDelimToken;
- }
- });
- /**
- * @param {string} input input css
- * @param {CssTokenCallbacks} callbacks callbacks
- * @returns {void}
- */
- module.exports = (input, callbacks) => {
- // This section describes how to consume a token from a stream of code points. It will return a single token of any type.
- let pos = 0;
- while (pos < input.length) {
- // Consume comments.
- pos = consumeComments(input, pos, callbacks);
- const cc = input.charCodeAt(pos);
- // Consume the next input code point.
- if (cc < 0x80) {
- pos = CHAR_MAP[cc](input, pos, callbacks);
- } else {
- pos++;
- }
- }
- };
- module.exports.isIdentStartCodePoint = isIdentStartCodePoint;
- /**
- * @param {string} input input
- * @param {number} pos position
- * @returns {number} position after comments
- */
- module.exports.eatComments = (input, pos) => {
- for (;;) {
- let originalPos = pos;
- pos = consumeComments(input, pos, {});
- if (originalPos === pos) {
- break;
- }
- }
- return pos;
- };
- /**
- * @param {string} input input
- * @param {number} pos position
- * @returns {number} position after whitespace
- */
- module.exports.eatWhitespace = (input, pos) => {
- while (_isWhiteSpace(input.charCodeAt(pos))) {
- pos++;
- }
- return pos;
- };
- /**
- * @param {string} input input
- * @param {number} pos position
- * @returns {number} position after whitespace and comments
- */
- module.exports.eatWhitespaceAndComments = (input, pos) => {
- for (;;) {
- let originalPos = pos;
- pos = consumeComments(input, pos, {});
- while (_isWhiteSpace(input.charCodeAt(pos))) {
- pos++;
- }
- if (originalPos === pos) {
- break;
- }
- }
- return pos;
- };
- /**
- * @param {string} input input
- * @param {number} pos position
- * @returns {number} position after whitespace
- */
- module.exports.eatWhiteLine = (input, pos) => {
- for (;;) {
- const cc = input.charCodeAt(pos);
- if (_isSpace(cc)) {
- pos++;
- continue;
- }
- if (_isNewLine(cc)) pos++;
- // For `\r\n`
- if (cc === CC_CARRIAGE_RETURN && input.charCodeAt(pos + 1) === CC_LINE_FEED)
- pos++;
- break;
- }
- return pos;
- };
|