From 76cb9c2a39d477a64824a985ade40507e3bbade1 Mon Sep 17 00:00:00 2001 From: Adam Mathes Date: Fri, 13 Feb 2026 21:34:48 -0800 Subject: feat(vanilla): add testing infrastructure and tests (NK-wjnczv) --- vanilla/node_modules/css-tree/lib/lexer/generic.js | 622 +++++++++++++++++++++ 1 file changed, 622 insertions(+) create mode 100644 vanilla/node_modules/css-tree/lib/lexer/generic.js (limited to 'vanilla/node_modules/css-tree/lib/lexer/generic.js') diff --git a/vanilla/node_modules/css-tree/lib/lexer/generic.js b/vanilla/node_modules/css-tree/lib/lexer/generic.js new file mode 100644 index 0000000..422e130 --- /dev/null +++ b/vanilla/node_modules/css-tree/lib/lexer/generic.js @@ -0,0 +1,622 @@ +import { cssWideKeywords } from './generic-const.js'; +import anPlusB from './generic-an-plus-b.js'; +import urange from './generic-urange.js'; +import { + isIdentifierStart, + isHexDigit, + isDigit, + cmpStr, + consumeNumber, + + Ident, + Function as FunctionToken, + AtKeyword, + Hash, + String as StringToken, + BadString, + Url, + BadUrl, + Delim, + Number as NumberToken, + Percentage, + Dimension, + WhiteSpace, + CDO, + CDC, + Colon, + Semicolon, + Comma, + LeftSquareBracket, + RightSquareBracket, + LeftParenthesis, + RightParenthesis, + LeftCurlyBracket, + RightCurlyBracket +} from '../tokenizer/index.js'; + +const calcFunctionNames = ['calc(', '-moz-calc(', '-webkit-calc(']; +const balancePair = new Map([ + [FunctionToken, RightParenthesis], + [LeftParenthesis, RightParenthesis], + [LeftSquareBracket, RightSquareBracket], + [LeftCurlyBracket, RightCurlyBracket] +]); + +// safe char code getter +function charCodeAt(str, index) { + return index < str.length ? str.charCodeAt(index) : 0; +} + +function eqStr(actual, expected) { + return cmpStr(actual, 0, actual.length, expected); +} + +function eqStrAny(actual, expected) { + for (let i = 0; i < expected.length; i++) { + if (eqStr(actual, expected[i])) { + return true; + } + } + + return false; +} + +// IE postfix hack, i.e. 123\0 or 123px\9 +function isPostfixIeHack(str, offset) { + if (offset !== str.length - 2) { + return false; + } + + return ( + charCodeAt(str, offset) === 0x005C && // U+005C REVERSE SOLIDUS (\) + isDigit(charCodeAt(str, offset + 1)) + ); +} + +function outOfRange(opts, value, numEnd) { + if (opts && opts.type === 'Range') { + const num = Number( + numEnd !== undefined && numEnd !== value.length + ? value.substr(0, numEnd) + : value + ); + + if (isNaN(num)) { + return true; + } + + // FIXME: when opts.min is a string it's a dimension, skip a range validation + // for now since it requires a type covertation which is not implmented yet + if (opts.min !== null && num < opts.min && typeof opts.min !== 'string') { + return true; + } + + // FIXME: when opts.max is a string it's a dimension, skip a range validation + // for now since it requires a type covertation which is not implmented yet + if (opts.max !== null && num > opts.max && typeof opts.max !== 'string') { + return true; + } + } + + return false; +} + +function consumeFunction(token, getNextToken) { + let balanceCloseType = 0; + let balanceStash = []; + let length = 0; + + // balanced token consuming + scan: + do { + switch (token.type) { + case RightCurlyBracket: + case RightParenthesis: + case RightSquareBracket: + if (token.type !== balanceCloseType) { + break scan; + } + + balanceCloseType = balanceStash.pop(); + + if (balanceStash.length === 0) { + length++; + break scan; + } + + break; + + case FunctionToken: + case LeftParenthesis: + case LeftSquareBracket: + case LeftCurlyBracket: + balanceStash.push(balanceCloseType); + balanceCloseType = balancePair.get(token.type); + break; + } + + length++; + } while (token = getNextToken(length)); + + return length; +} + +// TODO: implement +// can be used wherever , , ,