aboutsummaryrefslogtreecommitdiffstats
path: root/vanilla/node_modules/css-tree/lib/definition-syntax/parse.js
diff options
context:
space:
mode:
Diffstat (limited to 'vanilla/node_modules/css-tree/lib/definition-syntax/parse.js')
-rw-r--r--vanilla/node_modules/css-tree/lib/definition-syntax/parse.js552
1 files changed, 0 insertions, 552 deletions
diff --git a/vanilla/node_modules/css-tree/lib/definition-syntax/parse.js b/vanilla/node_modules/css-tree/lib/definition-syntax/parse.js
deleted file mode 100644
index 4e13ad8..0000000
--- a/vanilla/node_modules/css-tree/lib/definition-syntax/parse.js
+++ /dev/null
@@ -1,552 +0,0 @@
-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 readMultiplierRange(scanner) {
- let min = null;
- let max = null;
-
- scanner.eat(LEFTCURLYBRACKET);
- scanner.skipWs();
-
- min = scanner.scanNumber(scanner);
- scanner.skipWs();
-
- if (scanner.charCode() === COMMA) {
- scanner.pos++;
- scanner.skipWs();
-
- if (scanner.charCode() !== RIGHTCURLYBRACKET) {
- max = scanner.scanNumber(scanner);
- scanner.skipWs();
- }
- } else {
- max = min;
- }
-
- scanner.eat(RIGHTCURLYBRACKET);
-
- return {
- min: Number(min),
- max: max ? Number(max) : 0
- };
-}
-
-function readMultiplier(scanner) {
- let range = null;
- let comma = false;
-
- switch (scanner.charCode()) {
- case ASTERISK:
- scanner.pos++;
-
- range = {
- min: 0,
- max: 0
- };
-
- break;
-
- case PLUSSIGN:
- scanner.pos++;
-
- range = {
- min: 1,
- max: 0
- };
-
- break;
-
- case QUESTIONMARK:
- scanner.pos++;
-
- range = {
- min: 0,
- max: 1
- };
-
- break;
-
- case NUMBERSIGN:
- scanner.pos++;
-
- comma = true;
-
- 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,
- max: 0
- };
- }
-
- break;
-
- case LEFTCURLYBRACKET:
- range = readMultiplierRange(scanner);
- break;
-
- default:
- return null;
- }
-
- return {
- type: 'Multiplier',
- comma,
- min: range.min,
- max: range.max,
- term: null
- };
-}
-
-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(scanner) {
- const ch = scanner.peek();
-
- if (ch === '') {
- return null;
- }
-
- return maybeMultiplied(scanner, {
- type: 'Token',
- value: ch
- });
-}
-
-function readProperty(scanner) {
- let name;
-
- scanner.eat(LESSTHANSIGN);
- scanner.eat(APOSTROPHE);
-
- name = scanner.scanWord();
-
- scanner.eat(APOSTROPHE);
- scanner.eat(GREATERTHANSIGN);
-
- return maybeMultiplied(scanner, {
- type: 'Property',
- name
- });
-}
-
-// https://drafts.csswg.org/css-values-3/#numeric-ranges
-// 4.1. Range Restrictions and Range Definition Notation
-//
-// Range restrictions can be annotated in the numeric type notation using CSS bracketed
-// 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(scanner) {
- // use null for Infinity to make AST format JSON serializable/deserializable
- let min = null; // -Infinity
- let max = null; // Infinity
- let sign = 1;
-
- scanner.eat(LEFTSQUAREBRACKET);
-
- if (scanner.charCode() === HYPERMINUS) {
- scanner.peek();
- sign = -1;
- }
-
- if (sign == -1 && scanner.charCode() === INFINITY) {
- scanner.peek();
- } else {
- min = sign * Number(scanner.scanNumber(scanner));
-
- if (scanner.isNameCharCode()) {
- min += scanner.scanWord();
- }
- }
-
- scanner.skipWs();
- scanner.eat(COMMA);
- scanner.skipWs();
-
- if (scanner.charCode() === INFINITY) {
- scanner.peek();
- } else {
- sign = 1;
-
- if (scanner.charCode() === HYPERMINUS) {
- scanner.peek();
- sign = -1;
- }
-
- max = sign * Number(scanner.scanNumber(scanner));
-
- if (scanner.isNameCharCode()) {
- max += scanner.scanWord();
- }
- }
-
- scanner.eat(RIGHTSQUAREBRACKET);
-
- return {
- type: 'Range',
- min,
- max
- };
-}
-
-function readType(scanner) {
- let name;
- let opts = null;
-
- scanner.eat(LESSTHANSIGN);
- name = scanner.scanWord();
-
- // 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 (scanner.charCodeAt(scanner.findWsEnd(scanner.pos)) === LEFTSQUAREBRACKET) {
- scanner.skipWs();
- opts = readTypeRange(scanner);
- }
-
- scanner.eat(GREATERTHANSIGN);
-
- return maybeMultiplied(scanner, {
- type: 'Type',
- name,
- opts
- });
-}
-
-function readKeywordOrFunction(scanner) {
- const name = scanner.scanWord();
-
- if (scanner.charCode() === LEFTPARENTHESIS) {
- scanner.pos++;
-
- return {
- type: 'Function',
- name
- };
- }
-
- return maybeMultiplied(scanner, {
- type: 'Keyword',
- name
- });
-}
-
-function regroupTerms(terms, combinators) {
- function createGroup(terms, combinator) {
- return {
- type: 'Group',
- terms,
- combinator,
- disallowEmpty: false,
- explicit: false
- };
- }
-
- let combinator;
-
- combinators = Object.keys(combinators)
- .sort((a, b) => COMBINATOR_PRECEDENCE[a] - COMBINATOR_PRECEDENCE[b]);
-
- while (combinators.length > 0) {
- 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) {
- subgroupStart = i - 1;
- }
- terms.splice(i, 1);
- i--;
- } else {
- if (subgroupStart !== -1 && i - subgroupStart > 1) {
- terms.splice(
- subgroupStart,
- i - subgroupStart,
- createGroup(terms.slice(subgroupStart, i), combinator)
- );
- i = subgroupStart + 1;
- }
- subgroupStart = -1;
- }
- }
- }
-
- if (subgroupStart !== -1 && combinators.length) {
- terms.splice(
- subgroupStart,
- i - subgroupStart,
- createGroup(terms.slice(subgroupStart, i), combinator)
- );
- }
- }
-
- return combinator;
-}
-
-function readImplicitGroup(scanner, stopCharCode) {
- const combinators = Object.create(null);
- const terms = [];
- let token;
- let prevToken = null;
- let prevTokenPos = scanner.pos;
-
- 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') {
- scanner.pos = prevTokenPos;
- scanner.error('Unexpected combinator');
- }
-
- combinators[token.value] = true;
- } else if (prevToken !== null && prevToken.type !== 'Combinator') {
- combinators[' '] = true; // a b
- terms.push({
- type: 'Combinator',
- value: ' '
- });
- }
-
- terms.push(token);
- prevToken = token;
- prevTokenPos = scanner.pos;
- }
- }
-
- // check for combinator in group ending
- if (prevToken !== null && prevToken.type === 'Combinator') {
- scanner.pos -= prevTokenPos;
- scanner.error('Unexpected combinator');
- }
-
- return {
- type: 'Group',
- terms,
- combinator: regroupTerms(terms, combinators) || ' ',
- disallowEmpty: false,
- explicit: false
- };
-}
-
-function readGroup(scanner, stopCharCode) {
- let result;
-
- scanner.eat(LEFTSQUAREBRACKET);
- result = readImplicitGroup(scanner, stopCharCode);
- scanner.eat(RIGHTSQUAREBRACKET);
-
- result.explicit = true;
-
- if (scanner.charCode() === EXCLAMATIONMARK) {
- scanner.pos++;
- result.disallowEmpty = true;
- }
-
- return result;
-}
-
-function peek(scanner, stopCharCode) {
- let code = scanner.charCode();
-
- switch (code) {
- case RIGHTSQUAREBRACKET:
- // don't eat, stop scan a group
- break;
-
- case LEFTSQUAREBRACKET:
- return maybeMultiplied(scanner, readGroup(scanner, stopCharCode));
-
- case LESSTHANSIGN:
- return scanner.nextCharCode() === APOSTROPHE
- ? readProperty(scanner)
- : readType(scanner);
-
- case VERTICALLINE:
- return {
- type: 'Combinator',
- value: scanner.substringToPos(
- scanner.pos + (scanner.nextCharCode() === VERTICALLINE ? 2 : 1)
- )
- };
-
- case AMPERSAND:
- scanner.pos++;
- scanner.eat(AMPERSAND);
-
- return {
- type: 'Combinator',
- value: '&&'
- };
-
- case COMMA:
- scanner.pos++;
- return {
- type: 'Comma'
- };
-
- case APOSTROPHE:
- return maybeMultiplied(scanner, {
- type: 'String',
- value: scanner.scanString()
- });
-
- case SPACE:
- case TAB:
- case N:
- case R:
- case F:
- return {
- type: 'Spaces',
- value: scanner.scanSpaces()
- };
-
- case COMMERCIALAT:
- code = scanner.nextCharCode();
-
- if (scanner.isNameCharCode(code)) {
- scanner.pos++;
- return {
- type: 'AtKeyword',
- name: scanner.scanWord()
- };
- }
-
- return maybeToken(scanner);
-
- case ASTERISK:
- case PLUSSIGN:
- case QUESTIONMARK:
- case NUMBERSIGN:
- case EXCLAMATIONMARK:
- // prohibited tokens (used as a multiplier start)
- break;
-
- 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 = scanner.nextCharCode();
-
- if (code < 48 || code > 57) {
- return maybeToken(scanner);
- }
-
- break;
-
- default:
- if (scanner.isNameCharCode(code)) {
- return readKeywordOrFunction(scanner);
- }
-
- return maybeToken(scanner);
- }
-}
-
-export function parse(source) {
- const scanner = new Scanner(source);
- const result = readImplicitGroup(scanner);
-
- 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') {
- return result.terms[0];
- }
-
- return result;
-};