Fix code quality violations and exclude Manifest from checks
Document application modes (development/debug/production) Add global file drop handler, order column normalization, SPA hash fix Serve CDN assets via /_vendor/ URLs instead of merging into bundles Add production minification with license preservation Improve JSON formatting for debugging and production optimization Add CDN asset caching with CSS URL inlining for production builds Add three-mode system (development, debug, production) Update Manifest CLAUDE.md to reflect helper class architecture Refactor Manifest.php into helper classes for better organization Pre-manifest-refactor checkpoint: Add app_mode documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
474
node_modules/css-tree/lib/definition-syntax/parse.js
generated
vendored
474
node_modules/css-tree/lib/definition-syntax/parse.js
generated
vendored
@@ -1,116 +1,60 @@
|
||||
var Tokenizer = require('./tokenizer');
|
||||
var TAB = 9;
|
||||
var N = 10;
|
||||
var F = 12;
|
||||
var R = 13;
|
||||
var SPACE = 32;
|
||||
var EXCLAMATIONMARK = 33; // !
|
||||
var NUMBERSIGN = 35; // #
|
||||
var AMPERSAND = 38; // &
|
||||
var APOSTROPHE = 39; // '
|
||||
var LEFTPARENTHESIS = 40; // (
|
||||
var RIGHTPARENTHESIS = 41; // )
|
||||
var ASTERISK = 42; // *
|
||||
var PLUSSIGN = 43; // +
|
||||
var COMMA = 44; // ,
|
||||
var HYPERMINUS = 45; // -
|
||||
var LESSTHANSIGN = 60; // <
|
||||
var GREATERTHANSIGN = 62; // >
|
||||
var QUESTIONMARK = 63; // ?
|
||||
var COMMERCIALAT = 64; // @
|
||||
var LEFTSQUAREBRACKET = 91; // [
|
||||
var RIGHTSQUAREBRACKET = 93; // ]
|
||||
var LEFTCURLYBRACKET = 123; // {
|
||||
var VERTICALLINE = 124; // |
|
||||
var RIGHTCURLYBRACKET = 125; // }
|
||||
var INFINITY = 8734; // ∞
|
||||
var NAME_CHAR = createCharMap(function(ch) {
|
||||
return /[a-zA-Z0-9\-]/.test(ch);
|
||||
});
|
||||
var COMBINATOR_PRECEDENCE = {
|
||||
import { Scanner } from './scanner.js';
|
||||
|
||||
const TAB = 9;
|
||||
const N = 10;
|
||||
const F = 12;
|
||||
const R = 13;
|
||||
const SPACE = 32;
|
||||
const EXCLAMATIONMARK = 33; // !
|
||||
const NUMBERSIGN = 35; // #
|
||||
const AMPERSAND = 38; // &
|
||||
const APOSTROPHE = 39; // '
|
||||
const LEFTPARENTHESIS = 40; // (
|
||||
const RIGHTPARENTHESIS = 41; // )
|
||||
const ASTERISK = 42; // *
|
||||
const PLUSSIGN = 43; // +
|
||||
const COMMA = 44; // ,
|
||||
const HYPERMINUS = 45; // -
|
||||
const LESSTHANSIGN = 60; // <
|
||||
const GREATERTHANSIGN = 62; // >
|
||||
const QUESTIONMARK = 63; // ?
|
||||
const COMMERCIALAT = 64; // @
|
||||
const LEFTSQUAREBRACKET = 91; // [
|
||||
const RIGHTSQUAREBRACKET = 93; // ]
|
||||
const LEFTCURLYBRACKET = 123; // {
|
||||
const VERTICALLINE = 124; // |
|
||||
const RIGHTCURLYBRACKET = 125; // }
|
||||
const INFINITY = 8734; // ∞
|
||||
const COMBINATOR_PRECEDENCE = {
|
||||
' ': 1,
|
||||
'&&': 2,
|
||||
'||': 3,
|
||||
'|': 4
|
||||
};
|
||||
|
||||
function createCharMap(fn) {
|
||||
var array = typeof Uint32Array === 'function' ? new Uint32Array(128) : new Array(128);
|
||||
for (var i = 0; i < 128; i++) {
|
||||
array[i] = fn(String.fromCharCode(i)) ? 1 : 0;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
function readMultiplierRange(scanner) {
|
||||
let min = null;
|
||||
let max = null;
|
||||
|
||||
function scanSpaces(tokenizer) {
|
||||
return tokenizer.substringToPos(
|
||||
tokenizer.findWsEnd(tokenizer.pos)
|
||||
);
|
||||
}
|
||||
scanner.eat(LEFTCURLYBRACKET);
|
||||
scanner.skipWs();
|
||||
|
||||
function scanWord(tokenizer) {
|
||||
var end = tokenizer.pos;
|
||||
min = scanner.scanNumber(scanner);
|
||||
scanner.skipWs();
|
||||
|
||||
for (; end < tokenizer.str.length; end++) {
|
||||
var code = tokenizer.str.charCodeAt(end);
|
||||
if (code >= 128 || NAME_CHAR[code] === 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (scanner.charCode() === COMMA) {
|
||||
scanner.pos++;
|
||||
scanner.skipWs();
|
||||
|
||||
if (tokenizer.pos === end) {
|
||||
tokenizer.error('Expect a keyword');
|
||||
}
|
||||
|
||||
return tokenizer.substringToPos(end);
|
||||
}
|
||||
|
||||
function scanNumber(tokenizer) {
|
||||
var end = tokenizer.pos;
|
||||
|
||||
for (; end < tokenizer.str.length; end++) {
|
||||
var code = tokenizer.str.charCodeAt(end);
|
||||
if (code < 48 || code > 57) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tokenizer.pos === end) {
|
||||
tokenizer.error('Expect a number');
|
||||
}
|
||||
|
||||
return tokenizer.substringToPos(end);
|
||||
}
|
||||
|
||||
function scanString(tokenizer) {
|
||||
var end = tokenizer.str.indexOf('\'', tokenizer.pos + 1);
|
||||
|
||||
if (end === -1) {
|
||||
tokenizer.pos = tokenizer.str.length;
|
||||
tokenizer.error('Expect an apostrophe');
|
||||
}
|
||||
|
||||
return tokenizer.substringToPos(end + 1);
|
||||
}
|
||||
|
||||
function readMultiplierRange(tokenizer) {
|
||||
var min = null;
|
||||
var max = null;
|
||||
|
||||
tokenizer.eat(LEFTCURLYBRACKET);
|
||||
|
||||
min = scanNumber(tokenizer);
|
||||
|
||||
if (tokenizer.charCode() === COMMA) {
|
||||
tokenizer.pos++;
|
||||
if (tokenizer.charCode() !== RIGHTCURLYBRACKET) {
|
||||
max = scanNumber(tokenizer);
|
||||
if (scanner.charCode() !== RIGHTCURLYBRACKET) {
|
||||
max = scanner.scanNumber(scanner);
|
||||
scanner.skipWs();
|
||||
}
|
||||
} else {
|
||||
max = min;
|
||||
}
|
||||
|
||||
tokenizer.eat(RIGHTCURLYBRACKET);
|
||||
scanner.eat(RIGHTCURLYBRACKET);
|
||||
|
||||
return {
|
||||
min: Number(min),
|
||||
@@ -118,13 +62,13 @@ function readMultiplierRange(tokenizer) {
|
||||
};
|
||||
}
|
||||
|
||||
function readMultiplier(tokenizer) {
|
||||
var range = null;
|
||||
var comma = false;
|
||||
function readMultiplier(scanner) {
|
||||
let range = null;
|
||||
let comma = false;
|
||||
|
||||
switch (tokenizer.charCode()) {
|
||||
switch (scanner.charCode()) {
|
||||
case ASTERISK:
|
||||
tokenizer.pos++;
|
||||
scanner.pos++;
|
||||
|
||||
range = {
|
||||
min: 0,
|
||||
@@ -134,7 +78,7 @@ function readMultiplier(tokenizer) {
|
||||
break;
|
||||
|
||||
case PLUSSIGN:
|
||||
tokenizer.pos++;
|
||||
scanner.pos++;
|
||||
|
||||
range = {
|
||||
min: 1,
|
||||
@@ -144,7 +88,7 @@ function readMultiplier(tokenizer) {
|
||||
break;
|
||||
|
||||
case QUESTIONMARK:
|
||||
tokenizer.pos++;
|
||||
scanner.pos++;
|
||||
|
||||
range = {
|
||||
min: 0,
|
||||
@@ -154,12 +98,22 @@ function readMultiplier(tokenizer) {
|
||||
break;
|
||||
|
||||
case NUMBERSIGN:
|
||||
tokenizer.pos++;
|
||||
scanner.pos++;
|
||||
|
||||
comma = true;
|
||||
|
||||
if (tokenizer.charCode() === LEFTCURLYBRACKET) {
|
||||
range = readMultiplierRange(tokenizer);
|
||||
if (scanner.charCode() === LEFTCURLYBRACKET) {
|
||||
range = readMultiplierRange(scanner);
|
||||
} else if (scanner.charCode() === QUESTIONMARK) {
|
||||
// https://www.w3.org/TR/css-values-4/#component-multipliers
|
||||
// > the # and ? multipliers may be stacked as #?
|
||||
// In this case just treat "#?" as a single multiplier
|
||||
// { min: 0, max: 0, comma: true }
|
||||
scanner.pos++;
|
||||
range = {
|
||||
min: 0,
|
||||
max: 0
|
||||
};
|
||||
} else {
|
||||
range = {
|
||||
min: 1,
|
||||
@@ -170,7 +124,7 @@ function readMultiplier(tokenizer) {
|
||||
break;
|
||||
|
||||
case LEFTCURLYBRACKET:
|
||||
range = readMultiplierRange(tokenizer);
|
||||
range = readMultiplierRange(scanner);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -179,51 +133,66 @@ function readMultiplier(tokenizer) {
|
||||
|
||||
return {
|
||||
type: 'Multiplier',
|
||||
comma: comma,
|
||||
comma,
|
||||
min: range.min,
|
||||
max: range.max,
|
||||
term: null
|
||||
};
|
||||
}
|
||||
|
||||
function maybeMultiplied(tokenizer, node) {
|
||||
var multiplier = readMultiplier(tokenizer);
|
||||
function maybeMultiplied(scanner, node) {
|
||||
const multiplier = readMultiplier(scanner);
|
||||
|
||||
if (multiplier !== null) {
|
||||
multiplier.term = node;
|
||||
|
||||
// https://www.w3.org/TR/css-values-4/#component-multipliers
|
||||
// > The + and # multipliers may be stacked as +#;
|
||||
// Represent "+#" as nested multipliers:
|
||||
// { ...<multiplier #>,
|
||||
// term: {
|
||||
// ...<multipler +>,
|
||||
// term: node
|
||||
// }
|
||||
// }
|
||||
if (scanner.charCode() === NUMBERSIGN &&
|
||||
scanner.charCodeAt(scanner.pos - 1) === PLUSSIGN) {
|
||||
return maybeMultiplied(scanner, multiplier);
|
||||
}
|
||||
|
||||
return multiplier;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
function maybeToken(tokenizer) {
|
||||
var ch = tokenizer.peek();
|
||||
function maybeToken(scanner) {
|
||||
const ch = scanner.peek();
|
||||
|
||||
if (ch === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
return maybeMultiplied(scanner, {
|
||||
type: 'Token',
|
||||
value: ch
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function readProperty(tokenizer) {
|
||||
var name;
|
||||
function readProperty(scanner) {
|
||||
let name;
|
||||
|
||||
tokenizer.eat(LESSTHANSIGN);
|
||||
tokenizer.eat(APOSTROPHE);
|
||||
scanner.eat(LESSTHANSIGN);
|
||||
scanner.eat(APOSTROPHE);
|
||||
|
||||
name = scanWord(tokenizer);
|
||||
name = scanner.scanWord();
|
||||
|
||||
tokenizer.eat(APOSTROPHE);
|
||||
tokenizer.eat(GREATERTHANSIGN);
|
||||
scanner.eat(APOSTROPHE);
|
||||
scanner.eat(GREATERTHANSIGN);
|
||||
|
||||
return maybeMultiplied(tokenizer, {
|
||||
return maybeMultiplied(scanner, {
|
||||
type: 'Property',
|
||||
name: name
|
||||
name
|
||||
});
|
||||
}
|
||||
|
||||
@@ -234,101 +203,118 @@ function readProperty(tokenizer) {
|
||||
// range notation—[min,max]—within the angle brackets, after the identifying keyword,
|
||||
// indicating a closed range between (and including) min and max.
|
||||
// For example, <integer [0, 10]> indicates an integer between 0 and 10, inclusive.
|
||||
function readTypeRange(tokenizer) {
|
||||
function readTypeRange(scanner) {
|
||||
// use null for Infinity to make AST format JSON serializable/deserializable
|
||||
var min = null; // -Infinity
|
||||
var max = null; // Infinity
|
||||
var sign = 1;
|
||||
let min = null; // -Infinity
|
||||
let max = null; // Infinity
|
||||
let sign = 1;
|
||||
|
||||
tokenizer.eat(LEFTSQUAREBRACKET);
|
||||
scanner.eat(LEFTSQUAREBRACKET);
|
||||
|
||||
if (tokenizer.charCode() === HYPERMINUS) {
|
||||
tokenizer.peek();
|
||||
if (scanner.charCode() === HYPERMINUS) {
|
||||
scanner.peek();
|
||||
sign = -1;
|
||||
}
|
||||
|
||||
if (sign == -1 && tokenizer.charCode() === INFINITY) {
|
||||
tokenizer.peek();
|
||||
if (sign == -1 && scanner.charCode() === INFINITY) {
|
||||
scanner.peek();
|
||||
} else {
|
||||
min = sign * Number(scanNumber(tokenizer));
|
||||
min = sign * Number(scanner.scanNumber(scanner));
|
||||
|
||||
if (scanner.isNameCharCode()) {
|
||||
min += scanner.scanWord();
|
||||
}
|
||||
}
|
||||
|
||||
scanSpaces(tokenizer);
|
||||
tokenizer.eat(COMMA);
|
||||
scanSpaces(tokenizer);
|
||||
scanner.skipWs();
|
||||
scanner.eat(COMMA);
|
||||
scanner.skipWs();
|
||||
|
||||
if (tokenizer.charCode() === INFINITY) {
|
||||
tokenizer.peek();
|
||||
if (scanner.charCode() === INFINITY) {
|
||||
scanner.peek();
|
||||
} else {
|
||||
sign = 1;
|
||||
|
||||
if (tokenizer.charCode() === HYPERMINUS) {
|
||||
tokenizer.peek();
|
||||
if (scanner.charCode() === HYPERMINUS) {
|
||||
scanner.peek();
|
||||
sign = -1;
|
||||
}
|
||||
|
||||
max = sign * Number(scanNumber(tokenizer));
|
||||
max = sign * Number(scanner.scanNumber(scanner));
|
||||
|
||||
if (scanner.isNameCharCode()) {
|
||||
max += scanner.scanWord();
|
||||
}
|
||||
}
|
||||
|
||||
tokenizer.eat(RIGHTSQUAREBRACKET);
|
||||
|
||||
// If no range is indicated, either by using the bracketed range notation
|
||||
// or in the property description, then [−∞,∞] is assumed.
|
||||
if (min === null && max === null) {
|
||||
return null;
|
||||
}
|
||||
scanner.eat(RIGHTSQUAREBRACKET);
|
||||
|
||||
return {
|
||||
type: 'Range',
|
||||
min: min,
|
||||
max: max
|
||||
min,
|
||||
max
|
||||
};
|
||||
}
|
||||
|
||||
function readType(tokenizer) {
|
||||
var name;
|
||||
var opts = null;
|
||||
function readType(scanner) {
|
||||
let name;
|
||||
let opts = null;
|
||||
|
||||
tokenizer.eat(LESSTHANSIGN);
|
||||
name = scanWord(tokenizer);
|
||||
scanner.eat(LESSTHANSIGN);
|
||||
name = scanner.scanWord();
|
||||
|
||||
if (tokenizer.charCode() === LEFTPARENTHESIS &&
|
||||
tokenizer.nextCharCode() === RIGHTPARENTHESIS) {
|
||||
tokenizer.pos += 2;
|
||||
// https://drafts.csswg.org/css-values-5/#boolean
|
||||
if (name === 'boolean-expr') {
|
||||
scanner.eat(LEFTSQUAREBRACKET);
|
||||
|
||||
const implicitGroup = readImplicitGroup(scanner, RIGHTSQUAREBRACKET);
|
||||
|
||||
scanner.eat(RIGHTSQUAREBRACKET);
|
||||
scanner.eat(GREATERTHANSIGN);
|
||||
|
||||
return maybeMultiplied(scanner, {
|
||||
type: 'Boolean',
|
||||
term: implicitGroup.terms.length === 1
|
||||
? implicitGroup.terms[0]
|
||||
: implicitGroup
|
||||
});
|
||||
}
|
||||
|
||||
if (scanner.charCode() === LEFTPARENTHESIS &&
|
||||
scanner.nextCharCode() === RIGHTPARENTHESIS) {
|
||||
scanner.pos += 2;
|
||||
name += '()';
|
||||
}
|
||||
|
||||
if (tokenizer.charCodeAt(tokenizer.findWsEnd(tokenizer.pos)) === LEFTSQUAREBRACKET) {
|
||||
scanSpaces(tokenizer);
|
||||
opts = readTypeRange(tokenizer);
|
||||
if (scanner.charCodeAt(scanner.findWsEnd(scanner.pos)) === LEFTSQUAREBRACKET) {
|
||||
scanner.skipWs();
|
||||
opts = readTypeRange(scanner);
|
||||
}
|
||||
|
||||
tokenizer.eat(GREATERTHANSIGN);
|
||||
scanner.eat(GREATERTHANSIGN);
|
||||
|
||||
return maybeMultiplied(tokenizer, {
|
||||
return maybeMultiplied(scanner, {
|
||||
type: 'Type',
|
||||
name: name,
|
||||
opts: opts
|
||||
name,
|
||||
opts
|
||||
});
|
||||
}
|
||||
|
||||
function readKeywordOrFunction(tokenizer) {
|
||||
var name;
|
||||
function readKeywordOrFunction(scanner) {
|
||||
const name = scanner.scanWord();
|
||||
|
||||
name = scanWord(tokenizer);
|
||||
|
||||
if (tokenizer.charCode() === LEFTPARENTHESIS) {
|
||||
tokenizer.pos++;
|
||||
if (scanner.charCode() === LEFTPARENTHESIS) {
|
||||
scanner.pos++;
|
||||
|
||||
return {
|
||||
type: 'Function',
|
||||
name: name
|
||||
name
|
||||
};
|
||||
}
|
||||
|
||||
return maybeMultiplied(tokenizer, {
|
||||
return maybeMultiplied(scanner, {
|
||||
type: 'Keyword',
|
||||
name: name
|
||||
name
|
||||
});
|
||||
}
|
||||
|
||||
@@ -336,21 +322,27 @@ function regroupTerms(terms, combinators) {
|
||||
function createGroup(terms, combinator) {
|
||||
return {
|
||||
type: 'Group',
|
||||
terms: terms,
|
||||
combinator: combinator,
|
||||
terms,
|
||||
combinator,
|
||||
disallowEmpty: false,
|
||||
explicit: false
|
||||
};
|
||||
}
|
||||
|
||||
combinators = Object.keys(combinators).sort(function(a, b) {
|
||||
return COMBINATOR_PRECEDENCE[a] - COMBINATOR_PRECEDENCE[b];
|
||||
});
|
||||
let combinator;
|
||||
|
||||
combinators = Object.keys(combinators)
|
||||
.sort((a, b) => COMBINATOR_PRECEDENCE[a] - COMBINATOR_PRECEDENCE[b]);
|
||||
|
||||
while (combinators.length > 0) {
|
||||
var combinator = combinators.shift();
|
||||
for (var i = 0, subgroupStart = 0; i < terms.length; i++) {
|
||||
var term = terms[i];
|
||||
combinator = combinators.shift();
|
||||
|
||||
let i = 0;
|
||||
let subgroupStart = 0;
|
||||
|
||||
for (; i < terms.length; i++) {
|
||||
const term = terms[i];
|
||||
|
||||
if (term.type === 'Combinator') {
|
||||
if (term.value === combinator) {
|
||||
if (subgroupStart === -1) {
|
||||
@@ -384,20 +376,20 @@ function regroupTerms(terms, combinators) {
|
||||
return combinator;
|
||||
}
|
||||
|
||||
function readImplicitGroup(tokenizer) {
|
||||
var terms = [];
|
||||
var combinators = {};
|
||||
var token;
|
||||
var prevToken = null;
|
||||
var prevTokenPos = tokenizer.pos;
|
||||
function readImplicitGroup(scanner, stopCharCode) {
|
||||
const combinators = Object.create(null);
|
||||
const terms = [];
|
||||
let token;
|
||||
let prevToken = null;
|
||||
let prevTokenPos = scanner.pos;
|
||||
|
||||
while (token = peek(tokenizer)) {
|
||||
while (scanner.charCode() !== stopCharCode && (token = peek(scanner, stopCharCode))) {
|
||||
if (token.type !== 'Spaces') {
|
||||
if (token.type === 'Combinator') {
|
||||
// check for combinator in group beginning and double combinator sequence
|
||||
if (prevToken === null || prevToken.type === 'Combinator') {
|
||||
tokenizer.pos = prevTokenPos;
|
||||
tokenizer.error('Unexpected combinator');
|
||||
scanner.pos = prevTokenPos;
|
||||
scanner.error('Unexpected combinator');
|
||||
}
|
||||
|
||||
combinators[token.value] = true;
|
||||
@@ -411,48 +403,44 @@ function readImplicitGroup(tokenizer) {
|
||||
|
||||
terms.push(token);
|
||||
prevToken = token;
|
||||
prevTokenPos = tokenizer.pos;
|
||||
prevTokenPos = scanner.pos;
|
||||
}
|
||||
}
|
||||
|
||||
// check for combinator in group ending
|
||||
if (prevToken !== null && prevToken.type === 'Combinator') {
|
||||
tokenizer.pos -= prevTokenPos;
|
||||
tokenizer.error('Unexpected combinator');
|
||||
scanner.pos -= prevTokenPos;
|
||||
scanner.error('Unexpected combinator');
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'Group',
|
||||
terms: terms,
|
||||
terms,
|
||||
combinator: regroupTerms(terms, combinators) || ' ',
|
||||
disallowEmpty: false,
|
||||
explicit: false
|
||||
};
|
||||
}
|
||||
|
||||
function readGroup(tokenizer) {
|
||||
var result;
|
||||
function readGroup(scanner, stopCharCode) {
|
||||
let result;
|
||||
|
||||
tokenizer.eat(LEFTSQUAREBRACKET);
|
||||
result = readImplicitGroup(tokenizer);
|
||||
tokenizer.eat(RIGHTSQUAREBRACKET);
|
||||
scanner.eat(LEFTSQUAREBRACKET);
|
||||
result = readImplicitGroup(scanner, stopCharCode);
|
||||
scanner.eat(RIGHTSQUAREBRACKET);
|
||||
|
||||
result.explicit = true;
|
||||
|
||||
if (tokenizer.charCode() === EXCLAMATIONMARK) {
|
||||
tokenizer.pos++;
|
||||
if (scanner.charCode() === EXCLAMATIONMARK) {
|
||||
scanner.pos++;
|
||||
result.disallowEmpty = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function peek(tokenizer) {
|
||||
var code = tokenizer.charCode();
|
||||
|
||||
if (code < 128 && NAME_CHAR[code] === 1) {
|
||||
return readKeywordOrFunction(tokenizer);
|
||||
}
|
||||
function peek(scanner, stopCharCode) {
|
||||
let code = scanner.charCode();
|
||||
|
||||
switch (code) {
|
||||
case RIGHTSQUAREBRACKET:
|
||||
@@ -460,26 +448,24 @@ function peek(tokenizer) {
|
||||
break;
|
||||
|
||||
case LEFTSQUAREBRACKET:
|
||||
return maybeMultiplied(tokenizer, readGroup(tokenizer));
|
||||
return maybeMultiplied(scanner, readGroup(scanner, stopCharCode));
|
||||
|
||||
case LESSTHANSIGN:
|
||||
return tokenizer.nextCharCode() === APOSTROPHE
|
||||
? readProperty(tokenizer)
|
||||
: readType(tokenizer);
|
||||
return scanner.nextCharCode() === APOSTROPHE
|
||||
? readProperty(scanner)
|
||||
: readType(scanner);
|
||||
|
||||
case VERTICALLINE:
|
||||
return {
|
||||
type: 'Combinator',
|
||||
value: tokenizer.substringToPos(
|
||||
tokenizer.nextCharCode() === VERTICALLINE
|
||||
? tokenizer.pos + 2
|
||||
: tokenizer.pos + 1
|
||||
value: scanner.substringToPos(
|
||||
scanner.pos + (scanner.nextCharCode() === VERTICALLINE ? 2 : 1)
|
||||
)
|
||||
};
|
||||
|
||||
case AMPERSAND:
|
||||
tokenizer.pos++;
|
||||
tokenizer.eat(AMPERSAND);
|
||||
scanner.pos++;
|
||||
scanner.eat(AMPERSAND);
|
||||
|
||||
return {
|
||||
type: 'Combinator',
|
||||
@@ -487,15 +473,15 @@ function peek(tokenizer) {
|
||||
};
|
||||
|
||||
case COMMA:
|
||||
tokenizer.pos++;
|
||||
scanner.pos++;
|
||||
return {
|
||||
type: 'Comma'
|
||||
};
|
||||
|
||||
case APOSTROPHE:
|
||||
return maybeMultiplied(tokenizer, {
|
||||
return maybeMultiplied(scanner, {
|
||||
type: 'String',
|
||||
value: scanString(tokenizer)
|
||||
value: scanner.scanString()
|
||||
});
|
||||
|
||||
case SPACE:
|
||||
@@ -505,21 +491,21 @@ function peek(tokenizer) {
|
||||
case F:
|
||||
return {
|
||||
type: 'Spaces',
|
||||
value: scanSpaces(tokenizer)
|
||||
value: scanner.scanSpaces()
|
||||
};
|
||||
|
||||
case COMMERCIALAT:
|
||||
code = tokenizer.nextCharCode();
|
||||
code = scanner.nextCharCode();
|
||||
|
||||
if (code < 128 && NAME_CHAR[code] === 1) {
|
||||
tokenizer.pos++;
|
||||
if (scanner.isNameCharCode(code)) {
|
||||
scanner.pos++;
|
||||
return {
|
||||
type: 'AtKeyword',
|
||||
name: scanWord(tokenizer)
|
||||
name: scanner.scanWord()
|
||||
};
|
||||
}
|
||||
|
||||
return maybeToken(tokenizer);
|
||||
return maybeToken(scanner);
|
||||
|
||||
case ASTERISK:
|
||||
case PLUSSIGN:
|
||||
@@ -532,37 +518,35 @@ function peek(tokenizer) {
|
||||
case LEFTCURLYBRACKET:
|
||||
// LEFTCURLYBRACKET is allowed since mdn/data uses it w/o quoting
|
||||
// check next char isn't a number, because it's likely a disjoined multiplier
|
||||
code = tokenizer.nextCharCode();
|
||||
code = scanner.nextCharCode();
|
||||
|
||||
if (code < 48 || code > 57) {
|
||||
return maybeToken(tokenizer);
|
||||
return maybeToken(scanner);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return maybeToken(tokenizer);
|
||||
if (scanner.isNameCharCode(code)) {
|
||||
return readKeywordOrFunction(scanner);
|
||||
}
|
||||
|
||||
return maybeToken(scanner);
|
||||
}
|
||||
}
|
||||
|
||||
function parse(source) {
|
||||
var tokenizer = new Tokenizer(source);
|
||||
var result = readImplicitGroup(tokenizer);
|
||||
export function parse(source) {
|
||||
const scanner = new Scanner(source);
|
||||
const result = readImplicitGroup(scanner);
|
||||
|
||||
if (tokenizer.pos !== source.length) {
|
||||
tokenizer.error('Unexpected input');
|
||||
if (scanner.pos !== source.length) {
|
||||
scanner.error('Unexpected input');
|
||||
}
|
||||
|
||||
// reduce redundant groups with single group term
|
||||
if (result.terms.length === 1 && result.terms[0].type === 'Group') {
|
||||
result = result.terms[0];
|
||||
return result.terms[0];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// warm up parse to elimitate code branches that never execute
|
||||
// fix soft deoptimizations (insufficient type feedback)
|
||||
parse('[a&&<b>#|<\'c\'>*||e() f{2} /,(% g#{1,2} h{2,})]!');
|
||||
|
||||
module.exports = parse;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user