aboutsummaryrefslogtreecommitdiffstats
path: root/vanilla/node_modules/css-tree/cjs/lexer/generic-urange.cjs
diff options
context:
space:
mode:
authorAdam Mathes <adam@adammathes.com>2026-02-13 21:34:48 -0800
committerAdam Mathes <adam@adammathes.com>2026-02-13 21:34:48 -0800
commit76cb9c2a39d477a64824a985ade40507e3bbade1 (patch)
tree41e997aa9c6f538d3a136af61dae9424db2005a9 /vanilla/node_modules/css-tree/cjs/lexer/generic-urange.cjs
parent819a39a21ac992b1393244a4c283bbb125208c69 (diff)
downloadneko-76cb9c2a39d477a64824a985ade40507e3bbade1.tar.gz
neko-76cb9c2a39d477a64824a985ade40507e3bbade1.tar.bz2
neko-76cb9c2a39d477a64824a985ade40507e3bbade1.zip
feat(vanilla): add testing infrastructure and tests (NK-wjnczv)
Diffstat (limited to 'vanilla/node_modules/css-tree/cjs/lexer/generic-urange.cjs')
-rw-r--r--vanilla/node_modules/css-tree/cjs/lexer/generic-urange.cjs149
1 files changed, 149 insertions, 0 deletions
diff --git a/vanilla/node_modules/css-tree/cjs/lexer/generic-urange.cjs b/vanilla/node_modules/css-tree/cjs/lexer/generic-urange.cjs
new file mode 100644
index 0000000..ce167bb
--- /dev/null
+++ b/vanilla/node_modules/css-tree/cjs/lexer/generic-urange.cjs
@@ -0,0 +1,149 @@
+'use strict';
+
+const charCodeDefinitions = require('../tokenizer/char-code-definitions.cjs');
+const types = require('../tokenizer/types.cjs');
+const utils = require('../tokenizer/utils.cjs');
+
+const PLUSSIGN = 0x002B; // U+002B PLUS SIGN (+)
+const HYPHENMINUS = 0x002D; // U+002D HYPHEN-MINUS (-)
+const QUESTIONMARK = 0x003F; // U+003F QUESTION MARK (?)
+const U = 0x0075; // U+0075 LATIN SMALL LETTER U (u)
+
+function isDelim(token, code) {
+ return token !== null && token.type === types.Delim && token.value.charCodeAt(0) === code;
+}
+
+function startsWith(token, code) {
+ return token.value.charCodeAt(0) === code;
+}
+
+function hexSequence(token, offset, allowDash) {
+ let hexlen = 0;
+
+ for (let pos = offset; pos < token.value.length; pos++) {
+ const code = token.value.charCodeAt(pos);
+
+ if (code === HYPHENMINUS && allowDash && hexlen !== 0) {
+ hexSequence(token, offset + hexlen + 1, false);
+ return 6; // dissallow following question marks
+ }
+
+ if (!charCodeDefinitions.isHexDigit(code)) {
+ return 0; // not a hex digit
+ }
+
+ if (++hexlen > 6) {
+ return 0; // too many hex digits
+ } }
+
+ return hexlen;
+}
+
+function withQuestionMarkSequence(consumed, length, getNextToken) {
+ if (!consumed) {
+ return 0; // nothing consumed
+ }
+
+ while (isDelim(getNextToken(length), QUESTIONMARK)) {
+ if (++consumed > 6) {
+ return 0; // too many question marks
+ }
+
+ length++;
+ }
+
+ return length;
+}
+
+// https://drafts.csswg.org/css-syntax/#urange
+// Informally, the <urange> production has three forms:
+// U+0001
+// Defines a range consisting of a single code point, in this case the code point "1".
+// U+0001-00ff
+// Defines a range of codepoints between the first and the second value, in this case
+// the range between "1" and "ff" (255 in decimal) inclusive.
+// U+00??
+// Defines a range of codepoints where the "?" characters range over all hex digits,
+// in this case defining the same as the value U+0000-00ff.
+// In each form, a maximum of 6 digits is allowed for each hexadecimal number (if you treat "?" as a hexadecimal digit).
+//
+// <urange> =
+// u '+' <ident-token> '?'* |
+// u <dimension-token> '?'* |
+// u <number-token> '?'* |
+// u <number-token> <dimension-token> |
+// u <number-token> <number-token> |
+// u '+' '?'+
+function urange(token, getNextToken) {
+ let length = 0;
+
+ // should start with `u` or `U`
+ if (token === null || token.type !== types.Ident || !utils.cmpChar(token.value, 0, U)) {
+ return 0;
+ }
+
+ token = getNextToken(++length);
+ if (token === null) {
+ return 0;
+ }
+
+ // u '+' <ident-token> '?'*
+ // u '+' '?'+
+ if (isDelim(token, PLUSSIGN)) {
+ token = getNextToken(++length);
+ if (token === null) {
+ return 0;
+ }
+
+ if (token.type === types.Ident) {
+ // u '+' <ident-token> '?'*
+ return withQuestionMarkSequence(hexSequence(token, 0, true), ++length, getNextToken);
+ }
+
+ if (isDelim(token, QUESTIONMARK)) {
+ // u '+' '?'+
+ return withQuestionMarkSequence(1, ++length, getNextToken);
+ }
+
+ // Hex digit or question mark is expected
+ return 0;
+ }
+
+ // u <number-token> '?'*
+ // u <number-token> <dimension-token>
+ // u <number-token> <number-token>
+ if (token.type === types.Number) {
+ const consumedHexLength = hexSequence(token, 1, true);
+ if (consumedHexLength === 0) {
+ return 0;
+ }
+
+ token = getNextToken(++length);
+ if (token === null) {
+ // u <number-token> <eof>
+ return length;
+ }
+
+ if (token.type === types.Dimension || token.type === types.Number) {
+ // u <number-token> <dimension-token>
+ // u <number-token> <number-token>
+ if (!startsWith(token, HYPHENMINUS) || !hexSequence(token, 1, false)) {
+ return 0;
+ }
+
+ return length + 1;
+ }
+
+ // u <number-token> '?'*
+ return withQuestionMarkSequence(consumedHexLength, length, getNextToken);
+ }
+
+ // u <dimension-token> '?'*
+ if (token.type === types.Dimension) {
+ return withQuestionMarkSequence(hexSequence(token, 1, true), ++length, getNextToken);
+ }
+
+ return 0;
+}
+
+module.exports = urange;