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:
433
node_modules/css-tree/lib/lexer/Lexer.js
generated
vendored
433
node_modules/css-tree/lib/lexer/Lexer.js
generated
vendored
@@ -1,27 +1,24 @@
|
||||
var SyntaxReferenceError = require('./error').SyntaxReferenceError;
|
||||
var SyntaxMatchError = require('./error').SyntaxMatchError;
|
||||
var names = require('../utils/names');
|
||||
var generic = require('./generic');
|
||||
var parse = require('../definition-syntax/parse');
|
||||
var generate = require('../definition-syntax/generate');
|
||||
var walk = require('../definition-syntax/walk');
|
||||
var prepareTokens = require('./prepare-tokens');
|
||||
var buildMatchGraph = require('./match-graph').buildMatchGraph;
|
||||
var matchAsTree = require('./match').matchAsTree;
|
||||
var trace = require('./trace');
|
||||
var search = require('./search');
|
||||
var getStructureFromConfig = require('./structure').getStructureFromConfig;
|
||||
var cssWideKeywords = buildMatchGraph('inherit | initial | unset');
|
||||
var cssWideKeywordsWithExpression = buildMatchGraph('inherit | initial | unset | <-ms-legacy-expression>');
|
||||
import { SyntaxReferenceError, SyntaxMatchError } from './error.js';
|
||||
import * as names from '../utils/names.js';
|
||||
import { cssWideKeywords } from './generic-const.js';
|
||||
import { createGenericTypes } from './generic.js';
|
||||
import * as units from './units.js';
|
||||
import { parse, generate, walk } from '../definition-syntax/index.js';
|
||||
import prepareTokens from './prepare-tokens.js';
|
||||
import { buildMatchGraph } from './match-graph.js';
|
||||
import { matchAsTree } from './match.js';
|
||||
import * as trace from './trace.js';
|
||||
import { matchFragments } from './search.js';
|
||||
import { getStructureFromConfig } from './structure.js';
|
||||
|
||||
function dumpMapSyntax(map, compact, syntaxAsAst) {
|
||||
var result = {};
|
||||
const result = {};
|
||||
|
||||
for (var name in map) {
|
||||
for (const name in map) {
|
||||
if (map[name].syntax) {
|
||||
result[name] = syntaxAsAst
|
||||
? map[name].syntax
|
||||
: generate(map[name].syntax, { compact: compact });
|
||||
: generate(map[name].syntax, { compact });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +43,7 @@ function dumpAtruleMapSyntax(map, compact, syntaxAsAst) {
|
||||
}
|
||||
|
||||
function valueHasVar(tokens) {
|
||||
for (var i = 0; i < tokens.length; i++) {
|
||||
for (let i = 0; i < tokens.length; i++) {
|
||||
if (tokens[i].value.toLowerCase() === 'var(') {
|
||||
return true;
|
||||
}
|
||||
@@ -55,31 +52,39 @@ function valueHasVar(tokens) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function buildMatchResult(match, error, iterations) {
|
||||
function syntaxHasTopLevelCommaMultiplier(syntax) {
|
||||
const singleTerm = syntax.terms[0];
|
||||
|
||||
return (
|
||||
syntax.explicit === false &&
|
||||
syntax.terms.length === 1 &&
|
||||
singleTerm.type === 'Multiplier' &&
|
||||
singleTerm.comma === true
|
||||
);
|
||||
}
|
||||
|
||||
function buildMatchResult(matched, error, iterations) {
|
||||
return {
|
||||
matched: match,
|
||||
iterations: iterations,
|
||||
error: error,
|
||||
getTrace: trace.getTrace,
|
||||
isType: trace.isType,
|
||||
isProperty: trace.isProperty,
|
||||
isKeyword: trace.isKeyword
|
||||
matched,
|
||||
iterations,
|
||||
error,
|
||||
...trace
|
||||
};
|
||||
}
|
||||
|
||||
function matchSyntax(lexer, syntax, value, useCommon) {
|
||||
var tokens = prepareTokens(value, lexer.syntax);
|
||||
var result;
|
||||
function matchSyntax(lexer, syntax, value, useCssWideKeywords) {
|
||||
const tokens = prepareTokens(value, lexer.syntax);
|
||||
let result;
|
||||
|
||||
if (valueHasVar(tokens)) {
|
||||
return buildMatchResult(null, new Error('Matching for a tree with var() is not supported'));
|
||||
}
|
||||
|
||||
if (useCommon) {
|
||||
result = matchAsTree(tokens, lexer.valueCommonSyntax, lexer);
|
||||
if (useCssWideKeywords) {
|
||||
result = matchAsTree(tokens, lexer.cssWideKeywordsSyntax, lexer);
|
||||
}
|
||||
|
||||
if (!useCommon || !result.match) {
|
||||
if (!useCssWideKeywords || !result.match) {
|
||||
result = matchAsTree(tokens, syntax.match, lexer);
|
||||
if (!result.match) {
|
||||
return buildMatchResult(
|
||||
@@ -93,55 +98,66 @@ function matchSyntax(lexer, syntax, value, useCommon) {
|
||||
return buildMatchResult(result.match, null, result.iterations);
|
||||
}
|
||||
|
||||
var Lexer = function(config, syntax, structure) {
|
||||
this.valueCommonSyntax = cssWideKeywords;
|
||||
this.syntax = syntax;
|
||||
this.generic = false;
|
||||
this.atrules = {};
|
||||
this.properties = {};
|
||||
this.types = {};
|
||||
this.structure = structure || getStructureFromConfig(config);
|
||||
export class Lexer {
|
||||
constructor(config, syntax, structure) {
|
||||
this.cssWideKeywords = cssWideKeywords;
|
||||
this.syntax = syntax;
|
||||
this.generic = false;
|
||||
this.units = { ...units };
|
||||
this.atrules = Object.create(null);
|
||||
this.properties = Object.create(null);
|
||||
this.types = Object.create(null);
|
||||
this.structure = structure || getStructureFromConfig(config);
|
||||
|
||||
if (config) {
|
||||
if (config.types) {
|
||||
for (var name in config.types) {
|
||||
this.addType_(name, config.types[name]);
|
||||
if (config) {
|
||||
if (config.cssWideKeywords) {
|
||||
this.cssWideKeywords = config.cssWideKeywords;
|
||||
}
|
||||
|
||||
if (config.units) {
|
||||
for (const group of Object.keys(units)) {
|
||||
if (Array.isArray(config.units[group])) {
|
||||
this.units[group] = config.units[group];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.types) {
|
||||
for (const [name, type] of Object.entries(config.types)) {
|
||||
this.addType_(name, type);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.generic) {
|
||||
this.generic = true;
|
||||
for (const [name, value] of Object.entries(createGenericTypes(this.units))) {
|
||||
this.addType_(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.atrules) {
|
||||
for (const [name, atrule] of Object.entries(config.atrules)) {
|
||||
this.addAtrule_(name, atrule);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.properties) {
|
||||
for (const [name, property] of Object.entries(config.properties)) {
|
||||
this.addProperty_(name, property);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.generic) {
|
||||
this.generic = true;
|
||||
for (var name in generic) {
|
||||
this.addType_(name, generic[name]);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.atrules) {
|
||||
for (var name in config.atrules) {
|
||||
this.addAtrule_(name, config.atrules[name]);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.properties) {
|
||||
for (var name in config.properties) {
|
||||
this.addProperty_(name, config.properties[name]);
|
||||
}
|
||||
}
|
||||
this.cssWideKeywordsSyntax = buildMatchGraph(this.cssWideKeywords.join(' | '));
|
||||
}
|
||||
};
|
||||
|
||||
Lexer.prototype = {
|
||||
structure: {},
|
||||
checkStructure: function(ast) {
|
||||
checkStructure(ast) {
|
||||
function collectWarning(node, message) {
|
||||
warns.push({
|
||||
node: node,
|
||||
message: message
|
||||
});
|
||||
warns.push({ node, message });
|
||||
}
|
||||
|
||||
var structure = this.structure;
|
||||
var warns = [];
|
||||
const structure = this.structure;
|
||||
const warns = [];
|
||||
|
||||
this.syntax.walk(ast, function(node) {
|
||||
if (structure.hasOwnProperty(node.type)) {
|
||||
@@ -152,19 +168,21 @@ Lexer.prototype = {
|
||||
});
|
||||
|
||||
return warns.length ? warns : false;
|
||||
},
|
||||
}
|
||||
|
||||
createDescriptor: function(syntax, type, name, parent = null) {
|
||||
var ref = {
|
||||
type: type,
|
||||
name: name
|
||||
createDescriptor(syntax, type, name, parent = null) {
|
||||
const ref = {
|
||||
type,
|
||||
name
|
||||
};
|
||||
var descriptor = {
|
||||
type: type,
|
||||
name: name,
|
||||
parent: parent,
|
||||
const descriptor = {
|
||||
type,
|
||||
name,
|
||||
parent,
|
||||
serializable: typeof syntax === 'string' || (syntax && typeof syntax.type === 'string'),
|
||||
syntax: null,
|
||||
match: null
|
||||
match: null,
|
||||
matchRef: null // used for properties when a syntax referenced as <'property'> in other syntax definitions
|
||||
};
|
||||
|
||||
if (typeof syntax === 'function') {
|
||||
@@ -173,7 +191,7 @@ Lexer.prototype = {
|
||||
if (typeof syntax === 'string') {
|
||||
// lazy parsing on first access
|
||||
Object.defineProperty(descriptor, 'syntax', {
|
||||
get: function() {
|
||||
get() {
|
||||
Object.defineProperty(descriptor, 'syntax', {
|
||||
value: parse(syntax)
|
||||
});
|
||||
@@ -187,7 +205,7 @@ Lexer.prototype = {
|
||||
|
||||
// lazy graph build on first access
|
||||
Object.defineProperty(descriptor, 'match', {
|
||||
get: function() {
|
||||
get() {
|
||||
Object.defineProperty(descriptor, 'match', {
|
||||
value: buildMatchGraph(descriptor.syntax, ref)
|
||||
});
|
||||
@@ -195,11 +213,31 @@ Lexer.prototype = {
|
||||
return descriptor.match;
|
||||
}
|
||||
});
|
||||
|
||||
if (type === 'Property') {
|
||||
Object.defineProperty(descriptor, 'matchRef', {
|
||||
get() {
|
||||
const syntax = descriptor.syntax;
|
||||
const value = syntaxHasTopLevelCommaMultiplier(syntax)
|
||||
? buildMatchGraph({
|
||||
...syntax,
|
||||
terms: [syntax.terms[0].term]
|
||||
}, ref)
|
||||
: null;
|
||||
|
||||
Object.defineProperty(descriptor, 'matchRef', {
|
||||
value
|
||||
});
|
||||
|
||||
return value;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return descriptor;
|
||||
},
|
||||
addAtrule_: function(name, syntax) {
|
||||
}
|
||||
addAtrule_(name, syntax) {
|
||||
if (!syntax) {
|
||||
return;
|
||||
}
|
||||
@@ -209,63 +247,64 @@ Lexer.prototype = {
|
||||
name: name,
|
||||
prelude: syntax.prelude ? this.createDescriptor(syntax.prelude, 'AtrulePrelude', name) : null,
|
||||
descriptors: syntax.descriptors
|
||||
? Object.keys(syntax.descriptors).reduce((res, descName) => {
|
||||
res[descName] = this.createDescriptor(syntax.descriptors[descName], 'AtruleDescriptor', descName, name);
|
||||
return res;
|
||||
}, {})
|
||||
? Object.keys(syntax.descriptors).reduce(
|
||||
(map, descName) => {
|
||||
map[descName] = this.createDescriptor(syntax.descriptors[descName], 'AtruleDescriptor', descName, name);
|
||||
return map;
|
||||
},
|
||||
Object.create(null)
|
||||
)
|
||||
: null
|
||||
};
|
||||
},
|
||||
addProperty_: function(name, syntax) {
|
||||
}
|
||||
addProperty_(name, syntax) {
|
||||
if (!syntax) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.properties[name] = this.createDescriptor(syntax, 'Property', name);
|
||||
},
|
||||
addType_: function(name, syntax) {
|
||||
}
|
||||
addType_(name, syntax) {
|
||||
if (!syntax) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.types[name] = this.createDescriptor(syntax, 'Type', name);
|
||||
}
|
||||
|
||||
if (syntax === generic['-ms-legacy-expression']) {
|
||||
this.valueCommonSyntax = cssWideKeywordsWithExpression;
|
||||
}
|
||||
},
|
||||
|
||||
checkAtruleName: function(atruleName) {
|
||||
checkAtruleName(atruleName) {
|
||||
if (!this.getAtrule(atruleName)) {
|
||||
return new SyntaxReferenceError('Unknown at-rule', '@' + atruleName);
|
||||
}
|
||||
},
|
||||
checkAtrulePrelude: function(atruleName, prelude) {
|
||||
let error = this.checkAtruleName(atruleName);
|
||||
}
|
||||
checkAtrulePrelude(atruleName, prelude) {
|
||||
const error = this.checkAtruleName(atruleName);
|
||||
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
var atrule = this.getAtrule(atruleName);
|
||||
const atrule = this.getAtrule(atruleName);
|
||||
|
||||
if (!atrule.prelude && prelude) {
|
||||
return new SyntaxError('At-rule `@' + atruleName + '` should not contain a prelude');
|
||||
}
|
||||
|
||||
if (atrule.prelude && !prelude) {
|
||||
return new SyntaxError('At-rule `@' + atruleName + '` should contain a prelude');
|
||||
if (!matchSyntax(this, atrule.prelude, '', false).matched) {
|
||||
return new SyntaxError('At-rule `@' + atruleName + '` should contain a prelude');
|
||||
}
|
||||
}
|
||||
},
|
||||
checkAtruleDescriptorName: function(atruleName, descriptorName) {
|
||||
let error = this.checkAtruleName(atruleName);
|
||||
}
|
||||
checkAtruleDescriptorName(atruleName, descriptorName) {
|
||||
const error = this.checkAtruleName(atruleName);
|
||||
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
var atrule = this.getAtrule(atruleName);
|
||||
var descriptor = names.keyword(descriptorName);
|
||||
const atrule = this.getAtrule(atruleName);
|
||||
const descriptor = names.keyword(descriptorName);
|
||||
|
||||
if (!atrule.descriptors) {
|
||||
return new SyntaxError('At-rule `@' + atruleName + '` has no known descriptors');
|
||||
@@ -275,71 +314,71 @@ Lexer.prototype = {
|
||||
!atrule.descriptors[descriptor.basename]) {
|
||||
return new SyntaxReferenceError('Unknown at-rule descriptor', descriptorName);
|
||||
}
|
||||
},
|
||||
checkPropertyName: function(propertyName) {
|
||||
var property = names.property(propertyName);
|
||||
|
||||
// don't match syntax for a custom property
|
||||
if (property.custom) {
|
||||
return new Error('Lexer matching doesn\'t applicable for custom properties');
|
||||
}
|
||||
|
||||
}
|
||||
checkPropertyName(propertyName) {
|
||||
if (!this.getProperty(propertyName)) {
|
||||
return new SyntaxReferenceError('Unknown property', propertyName);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
matchAtrulePrelude: function(atruleName, prelude) {
|
||||
var error = this.checkAtrulePrelude(atruleName, prelude);
|
||||
matchAtrulePrelude(atruleName, prelude) {
|
||||
const error = this.checkAtrulePrelude(atruleName, prelude);
|
||||
|
||||
if (error) {
|
||||
return buildMatchResult(null, error);
|
||||
}
|
||||
|
||||
if (!prelude) {
|
||||
const atrule = this.getAtrule(atruleName);
|
||||
|
||||
if (!atrule.prelude) {
|
||||
return buildMatchResult(null, null);
|
||||
}
|
||||
|
||||
return matchSyntax(this, this.getAtrule(atruleName).prelude, prelude, false);
|
||||
},
|
||||
matchAtruleDescriptor: function(atruleName, descriptorName, value) {
|
||||
var error = this.checkAtruleDescriptorName(atruleName, descriptorName);
|
||||
return matchSyntax(this, atrule.prelude, prelude || '', false);
|
||||
}
|
||||
matchAtruleDescriptor(atruleName, descriptorName, value) {
|
||||
const error = this.checkAtruleDescriptorName(atruleName, descriptorName);
|
||||
|
||||
if (error) {
|
||||
return buildMatchResult(null, error);
|
||||
}
|
||||
|
||||
var atrule = this.getAtrule(atruleName);
|
||||
var descriptor = names.keyword(descriptorName);
|
||||
const atrule = this.getAtrule(atruleName);
|
||||
const descriptor = names.keyword(descriptorName);
|
||||
|
||||
return matchSyntax(this, atrule.descriptors[descriptor.name] || atrule.descriptors[descriptor.basename], value, false);
|
||||
},
|
||||
matchDeclaration: function(node) {
|
||||
}
|
||||
matchDeclaration(node) {
|
||||
if (node.type !== 'Declaration') {
|
||||
return buildMatchResult(null, new Error('Not a Declaration node'));
|
||||
}
|
||||
|
||||
return this.matchProperty(node.property, node.value);
|
||||
},
|
||||
matchProperty: function(propertyName, value) {
|
||||
var error = this.checkPropertyName(propertyName);
|
||||
}
|
||||
matchProperty(propertyName, value) {
|
||||
// don't match syntax for a custom property at the moment
|
||||
if (names.property(propertyName).custom) {
|
||||
return buildMatchResult(null, new Error('Lexer matching doesn\'t applicable for custom properties'));
|
||||
}
|
||||
|
||||
const error = this.checkPropertyName(propertyName);
|
||||
|
||||
if (error) {
|
||||
return buildMatchResult(null, error);
|
||||
}
|
||||
|
||||
return matchSyntax(this, this.getProperty(propertyName), value, true);
|
||||
},
|
||||
matchType: function(typeName, value) {
|
||||
var typeSyntax = this.getType(typeName);
|
||||
}
|
||||
matchType(typeName, value) {
|
||||
const typeSyntax = this.getType(typeName);
|
||||
|
||||
if (!typeSyntax) {
|
||||
return buildMatchResult(null, new SyntaxReferenceError('Unknown type', typeName));
|
||||
}
|
||||
|
||||
return matchSyntax(this, typeSyntax, value, false);
|
||||
},
|
||||
match: function(syntax, value) {
|
||||
}
|
||||
match(syntax, value) {
|
||||
if (typeof syntax !== 'string' && (!syntax || !syntax.type)) {
|
||||
return buildMatchResult(null, new SyntaxReferenceError('Bad syntax'));
|
||||
}
|
||||
@@ -349,118 +388,124 @@ Lexer.prototype = {
|
||||
}
|
||||
|
||||
return matchSyntax(this, syntax, value, false);
|
||||
},
|
||||
}
|
||||
|
||||
findValueFragments: function(propertyName, value, type, name) {
|
||||
return search.matchFragments(this, value, this.matchProperty(propertyName, value), type, name);
|
||||
},
|
||||
findDeclarationValueFragments: function(declaration, type, name) {
|
||||
return search.matchFragments(this, declaration.value, this.matchDeclaration(declaration), type, name);
|
||||
},
|
||||
findAllFragments: function(ast, type, name) {
|
||||
var result = [];
|
||||
findValueFragments(propertyName, value, type, name) {
|
||||
return matchFragments(this, value, this.matchProperty(propertyName, value), type, name);
|
||||
}
|
||||
findDeclarationValueFragments(declaration, type, name) {
|
||||
return matchFragments(this, declaration.value, this.matchDeclaration(declaration), type, name);
|
||||
}
|
||||
findAllFragments(ast, type, name) {
|
||||
const result = [];
|
||||
|
||||
this.syntax.walk(ast, {
|
||||
visit: 'Declaration',
|
||||
enter: function(declaration) {
|
||||
enter: (declaration) => {
|
||||
result.push.apply(result, this.findDeclarationValueFragments(declaration, type, name));
|
||||
}.bind(this)
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
},
|
||||
}
|
||||
|
||||
getAtrule: function(atruleName, fallbackBasename = true) {
|
||||
var atrule = names.keyword(atruleName);
|
||||
var atruleEntry = atrule.vendor && fallbackBasename
|
||||
getAtrule(atruleName, fallbackBasename = true) {
|
||||
const atrule = names.keyword(atruleName);
|
||||
const atruleEntry = atrule.vendor && fallbackBasename
|
||||
? this.atrules[atrule.name] || this.atrules[atrule.basename]
|
||||
: this.atrules[atrule.name];
|
||||
|
||||
return atruleEntry || null;
|
||||
},
|
||||
getAtrulePrelude: function(atruleName, fallbackBasename = true) {
|
||||
}
|
||||
getAtrulePrelude(atruleName, fallbackBasename = true) {
|
||||
const atrule = this.getAtrule(atruleName, fallbackBasename);
|
||||
|
||||
return atrule && atrule.prelude || null;
|
||||
},
|
||||
getAtruleDescriptor: function(atruleName, name) {
|
||||
}
|
||||
getAtruleDescriptor(atruleName, name) {
|
||||
return this.atrules.hasOwnProperty(atruleName) && this.atrules.declarators
|
||||
? this.atrules[atruleName].declarators[name] || null
|
||||
: null;
|
||||
},
|
||||
getProperty: function(propertyName, fallbackBasename = true) {
|
||||
var property = names.property(propertyName);
|
||||
var propertyEntry = property.vendor && fallbackBasename
|
||||
}
|
||||
getProperty(propertyName, fallbackBasename = true) {
|
||||
const property = names.property(propertyName);
|
||||
const propertyEntry = property.vendor && fallbackBasename
|
||||
? this.properties[property.name] || this.properties[property.basename]
|
||||
: this.properties[property.name];
|
||||
|
||||
return propertyEntry || null;
|
||||
},
|
||||
getType: function(name) {
|
||||
return this.types.hasOwnProperty(name) ? this.types[name] : null;
|
||||
},
|
||||
}
|
||||
getType(name) {
|
||||
return hasOwnProperty.call(this.types, name) ? this.types[name] : null;
|
||||
}
|
||||
|
||||
validate() {
|
||||
function syntaxRef(name, isType) {
|
||||
return isType ? `<${name}>` : `<'${name}'>`;
|
||||
}
|
||||
|
||||
validate: function() {
|
||||
function validate(syntax, name, broken, descriptor) {
|
||||
if (broken.hasOwnProperty(name)) {
|
||||
return broken[name];
|
||||
if (broken.has(name)) {
|
||||
return broken.get(name);
|
||||
}
|
||||
|
||||
broken[name] = false;
|
||||
broken.set(name, false);
|
||||
if (descriptor.syntax !== null) {
|
||||
walk(descriptor.syntax, function(node) {
|
||||
if (node.type !== 'Type' && node.type !== 'Property') {
|
||||
return;
|
||||
}
|
||||
|
||||
var map = node.type === 'Type' ? syntax.types : syntax.properties;
|
||||
var brokenMap = node.type === 'Type' ? brokenTypes : brokenProperties;
|
||||
const map = node.type === 'Type' ? syntax.types : syntax.properties;
|
||||
const brokenMap = node.type === 'Type' ? brokenTypes : brokenProperties;
|
||||
|
||||
if (!map.hasOwnProperty(node.name) || validate(syntax, node.name, brokenMap, map[node.name])) {
|
||||
broken[name] = true;
|
||||
if (!hasOwnProperty.call(map, node.name)) {
|
||||
errors.push(`${syntaxRef(name, broken === brokenTypes)} used missed syntax definition ${syntaxRef(node.name, node.type === 'Type')}`);
|
||||
broken.set(name, true);
|
||||
} else if (validate(syntax, node.name, brokenMap, map[node.name])) {
|
||||
errors.push(`${syntaxRef(name, broken === brokenTypes)} used broken syntax definition ${syntaxRef(node.name, node.type === 'Type')}`);
|
||||
broken.set(name, true);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
|
||||
var brokenTypes = {};
|
||||
var brokenProperties = {};
|
||||
const errors = [];
|
||||
let brokenTypes = new Map();
|
||||
let brokenProperties = new Map();
|
||||
|
||||
for (var key in this.types) {
|
||||
for (const key in this.types) {
|
||||
validate(this, key, brokenTypes, this.types[key]);
|
||||
}
|
||||
|
||||
for (var key in this.properties) {
|
||||
for (const key in this.properties) {
|
||||
validate(this, key, brokenProperties, this.properties[key]);
|
||||
}
|
||||
|
||||
brokenTypes = Object.keys(brokenTypes).filter(function(name) {
|
||||
return brokenTypes[name];
|
||||
});
|
||||
brokenProperties = Object.keys(brokenProperties).filter(function(name) {
|
||||
return brokenProperties[name];
|
||||
});
|
||||
const brokenTypesArray = [...brokenTypes.keys()].filter(name => brokenTypes.get(name));
|
||||
const brokenPropertiesArray = [...brokenProperties.keys()].filter(name => brokenProperties.get(name));
|
||||
|
||||
if (brokenTypes.length || brokenProperties.length) {
|
||||
if (brokenTypesArray.length || brokenPropertiesArray.length) {
|
||||
return {
|
||||
types: brokenTypes,
|
||||
properties: brokenProperties
|
||||
errors,
|
||||
types: brokenTypesArray,
|
||||
properties: brokenPropertiesArray
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
dump: function(syntaxAsAst, pretty) {
|
||||
}
|
||||
dump(syntaxAsAst, pretty) {
|
||||
return {
|
||||
generic: this.generic,
|
||||
cssWideKeywords: this.cssWideKeywords,
|
||||
units: this.units,
|
||||
types: dumpMapSyntax(this.types, !pretty, syntaxAsAst),
|
||||
properties: dumpMapSyntax(this.properties, !pretty, syntaxAsAst),
|
||||
atrules: dumpAtruleMapSyntax(this.atrules, !pretty, syntaxAsAst)
|
||||
};
|
||||
},
|
||||
toString: function() {
|
||||
}
|
||||
toString() {
|
||||
return JSON.stringify(this.dump());
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Lexer;
|
||||
|
||||
14
node_modules/css-tree/lib/lexer/error.js
generated
vendored
14
node_modules/css-tree/lib/lexer/error.js
generated
vendored
@@ -1,5 +1,6 @@
|
||||
const createCustomError = require('../utils/createCustomError');
|
||||
const generate = require('../definition-syntax/generate');
|
||||
import { createCustomError } from '../utils/create-custom-error.js';
|
||||
import { generate } from '../definition-syntax/generate.js';
|
||||
|
||||
const defaultLoc = { offset: 0, line: 1, column: 1 };
|
||||
|
||||
function locateMismatch(matchResult, node) {
|
||||
@@ -80,7 +81,7 @@ function buildLoc({ offset, line, column }, extra) {
|
||||
return loc;
|
||||
}
|
||||
|
||||
const SyntaxReferenceError = function(type, referenceName) {
|
||||
export const SyntaxReferenceError = function(type, referenceName) {
|
||||
const error = createCustomError(
|
||||
'SyntaxReferenceError',
|
||||
type + (referenceName ? ' `' + referenceName + '`' : '')
|
||||
@@ -91,7 +92,7 @@ const SyntaxReferenceError = function(type, referenceName) {
|
||||
return error;
|
||||
};
|
||||
|
||||
const SyntaxMatchError = function(message, syntax, node, matchResult) {
|
||||
export const SyntaxMatchError = function(message, syntax, node, matchResult) {
|
||||
const error = createCustomError('SyntaxMatchError', message);
|
||||
const {
|
||||
css,
|
||||
@@ -120,8 +121,3 @@ const SyntaxMatchError = function(message, syntax, node, matchResult) {
|
||||
|
||||
return error;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
SyntaxReferenceError,
|
||||
SyntaxMatchError
|
||||
};
|
||||
|
||||
66
node_modules/css-tree/lib/lexer/generic-an-plus-b.js
generated
vendored
66
node_modules/css-tree/lib/lexer/generic-an-plus-b.js
generated
vendored
@@ -1,25 +1,26 @@
|
||||
var isDigit = require('../tokenizer').isDigit;
|
||||
var cmpChar = require('../tokenizer').cmpChar;
|
||||
var TYPE = require('../tokenizer').TYPE;
|
||||
import {
|
||||
isDigit,
|
||||
cmpChar,
|
||||
Delim,
|
||||
WhiteSpace,
|
||||
Comment,
|
||||
Ident,
|
||||
Number as NumberToken,
|
||||
Dimension
|
||||
} from '../tokenizer/index.js';
|
||||
|
||||
var DELIM = TYPE.Delim;
|
||||
var WHITESPACE = TYPE.WhiteSpace;
|
||||
var COMMENT = TYPE.Comment;
|
||||
var IDENT = TYPE.Ident;
|
||||
var NUMBER = TYPE.Number;
|
||||
var DIMENSION = TYPE.Dimension;
|
||||
var PLUSSIGN = 0x002B; // U+002B PLUS SIGN (+)
|
||||
var HYPHENMINUS = 0x002D; // U+002D HYPHEN-MINUS (-)
|
||||
var N = 0x006E; // U+006E LATIN SMALL LETTER N (n)
|
||||
var DISALLOW_SIGN = true;
|
||||
var ALLOW_SIGN = false;
|
||||
const PLUSSIGN = 0x002B; // U+002B PLUS SIGN (+)
|
||||
const HYPHENMINUS = 0x002D; // U+002D HYPHEN-MINUS (-)
|
||||
const N = 0x006E; // U+006E LATIN SMALL LETTER N (n)
|
||||
const DISALLOW_SIGN = true;
|
||||
const ALLOW_SIGN = false;
|
||||
|
||||
function isDelim(token, code) {
|
||||
return token !== null && token.type === DELIM && token.value.charCodeAt(0) === code;
|
||||
return token !== null && token.type === Delim && token.value.charCodeAt(0) === code;
|
||||
}
|
||||
|
||||
function skipSC(token, offset, getNextToken) {
|
||||
while (token !== null && (token.type === WHITESPACE || token.type === COMMENT)) {
|
||||
while (token !== null && (token.type === WhiteSpace || token.type === Comment)) {
|
||||
token = getNextToken(++offset);
|
||||
}
|
||||
|
||||
@@ -31,7 +32,7 @@ function checkInteger(token, valueOffset, disallowSign, offset) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var code = token.value.charCodeAt(valueOffset);
|
||||
const code = token.value.charCodeAt(valueOffset);
|
||||
|
||||
if (code === PLUSSIGN || code === HYPHENMINUS) {
|
||||
if (disallowSign) {
|
||||
@@ -54,8 +55,8 @@ function checkInteger(token, valueOffset, disallowSign, offset) {
|
||||
// ... <signed-integer>
|
||||
// ... ['+' | '-'] <signless-integer>
|
||||
function consumeB(token, offset_, getNextToken) {
|
||||
var sign = false;
|
||||
var offset = skipSC(token, offset_, getNextToken);
|
||||
let sign = false;
|
||||
let offset = skipSC(token, offset_, getNextToken);
|
||||
|
||||
token = getNextToken(offset);
|
||||
|
||||
@@ -63,13 +64,13 @@ function consumeB(token, offset_, getNextToken) {
|
||||
return offset_;
|
||||
}
|
||||
|
||||
if (token.type !== NUMBER) {
|
||||
if (token.type !== NumberToken) {
|
||||
if (isDelim(token, PLUSSIGN) || isDelim(token, HYPHENMINUS)) {
|
||||
sign = true;
|
||||
offset = skipSC(getNextToken(++offset), offset, getNextToken);
|
||||
token = getNextToken(offset);
|
||||
|
||||
if (token === null && token.type !== NUMBER) {
|
||||
if (token === null || token.type !== NumberToken) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
@@ -78,7 +79,7 @@ function consumeB(token, offset_, getNextToken) {
|
||||
}
|
||||
|
||||
if (!sign) {
|
||||
var code = token.value.charCodeAt(0);
|
||||
const code = token.value.charCodeAt(0);
|
||||
if (code !== PLUSSIGN && code !== HYPHENMINUS) {
|
||||
// Number sign is expected
|
||||
return 0;
|
||||
@@ -89,16 +90,16 @@ function consumeB(token, offset_, getNextToken) {
|
||||
}
|
||||
|
||||
// An+B microsyntax https://www.w3.org/TR/css-syntax-3/#anb
|
||||
module.exports = function anPlusB(token, getNextToken) {
|
||||
export default function anPlusB(token, getNextToken) {
|
||||
/* eslint-disable brace-style*/
|
||||
var offset = 0;
|
||||
let offset = 0;
|
||||
|
||||
if (!token) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// <integer>
|
||||
if (token.type === NUMBER) {
|
||||
if (token.type === NumberToken) {
|
||||
return checkInteger(token, 0, ALLOW_SIGN, offset); // b
|
||||
}
|
||||
|
||||
@@ -107,7 +108,7 @@ module.exports = function anPlusB(token, getNextToken) {
|
||||
// -n ['+' | '-'] <signless-integer>
|
||||
// -n- <signless-integer>
|
||||
// <dashndashdigit-ident>
|
||||
else if (token.type === IDENT && token.value.charCodeAt(0) === HYPHENMINUS) {
|
||||
else if (token.type === Ident && token.value.charCodeAt(0) === HYPHENMINUS) {
|
||||
// expect 1st char is N
|
||||
if (!cmpChar(token.value, 1, N)) {
|
||||
return 0;
|
||||
@@ -146,9 +147,9 @@ module.exports = function anPlusB(token, getNextToken) {
|
||||
// '+'? n ['+' | '-'] <signless-integer>
|
||||
// '+'? n- <signless-integer>
|
||||
// '+'? <ndashdigit-ident>
|
||||
else if (token.type === IDENT || (isDelim(token, PLUSSIGN) && getNextToken(offset + 1).type === IDENT)) {
|
||||
else if (token.type === Ident || (isDelim(token, PLUSSIGN) && getNextToken(offset + 1).type === Ident)) {
|
||||
// just ignore a plus
|
||||
if (token.type !== IDENT) {
|
||||
if (token.type !== Ident) {
|
||||
token = getNextToken(++offset);
|
||||
}
|
||||
|
||||
@@ -189,11 +190,12 @@ module.exports = function anPlusB(token, getNextToken) {
|
||||
// <n-dimension>
|
||||
// <n-dimension> <signed-integer>
|
||||
// <n-dimension> ['+' | '-'] <signless-integer>
|
||||
else if (token.type === DIMENSION) {
|
||||
var code = token.value.charCodeAt(0);
|
||||
var sign = code === PLUSSIGN || code === HYPHENMINUS ? 1 : 0;
|
||||
else if (token.type === Dimension) {
|
||||
let code = token.value.charCodeAt(0);
|
||||
let sign = code === PLUSSIGN || code === HYPHENMINUS ? 1 : 0;
|
||||
let i = sign;
|
||||
|
||||
for (var i = sign; i < token.value.length; i++) {
|
||||
for (; i < token.value.length; i++) {
|
||||
if (!isDigit(token.value.charCodeAt(i))) {
|
||||
break;
|
||||
}
|
||||
|
||||
8
node_modules/css-tree/lib/lexer/generic-const.js
generated
vendored
Normal file
8
node_modules/css-tree/lib/lexer/generic-const.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
// https://drafts.csswg.org/css-cascade-5/
|
||||
export const cssWideKeywords = [
|
||||
'initial',
|
||||
'inherit',
|
||||
'unset',
|
||||
'revert',
|
||||
'revert-layer'
|
||||
];
|
||||
62
node_modules/css-tree/lib/lexer/generic-urange.js
generated
vendored
62
node_modules/css-tree/lib/lexer/generic-urange.js
generated
vendored
@@ -1,18 +1,19 @@
|
||||
var isHexDigit = require('../tokenizer').isHexDigit;
|
||||
var cmpChar = require('../tokenizer').cmpChar;
|
||||
var TYPE = require('../tokenizer').TYPE;
|
||||
import {
|
||||
isHexDigit,
|
||||
cmpChar,
|
||||
Ident,
|
||||
Delim,
|
||||
Number as NumberToken,
|
||||
Dimension
|
||||
} from '../tokenizer/index.js';
|
||||
|
||||
var IDENT = TYPE.Ident;
|
||||
var DELIM = TYPE.Delim;
|
||||
var NUMBER = TYPE.Number;
|
||||
var DIMENSION = TYPE.Dimension;
|
||||
var PLUSSIGN = 0x002B; // U+002B PLUS SIGN (+)
|
||||
var HYPHENMINUS = 0x002D; // U+002D HYPHEN-MINUS (-)
|
||||
var QUESTIONMARK = 0x003F; // U+003F QUESTION MARK (?)
|
||||
var U = 0x0075; // U+0075 LATIN SMALL LETTER U (u)
|
||||
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 === DELIM && token.value.charCodeAt(0) === code;
|
||||
return token !== null && token.type === Delim && token.value.charCodeAt(0) === code;
|
||||
}
|
||||
|
||||
function startsWith(token, code) {
|
||||
@@ -20,15 +21,14 @@ function startsWith(token, code) {
|
||||
}
|
||||
|
||||
function hexSequence(token, offset, allowDash) {
|
||||
for (var pos = offset, hexlen = 0; pos < token.value.length; pos++) {
|
||||
var code = token.value.charCodeAt(pos);
|
||||
let hexlen = 0;
|
||||
|
||||
for (let pos = offset; pos < token.value.length; pos++) {
|
||||
const code = token.value.charCodeAt(pos);
|
||||
|
||||
if (code === HYPHENMINUS && allowDash && hexlen !== 0) {
|
||||
if (hexSequence(token, offset + hexlen + 1, false) > 0) {
|
||||
return 6; // dissallow following question marks
|
||||
}
|
||||
|
||||
return 0; // dash at the ending of a hex sequence is not allowed
|
||||
hexSequence(token, offset + hexlen + 1, false);
|
||||
return 6; // dissallow following question marks
|
||||
}
|
||||
|
||||
if (!isHexDigit(code)) {
|
||||
@@ -78,11 +78,11 @@ function withQuestionMarkSequence(consumed, length, getNextToken) {
|
||||
// u <number-token> <dimension-token> |
|
||||
// u <number-token> <number-token> |
|
||||
// u '+' '?'+
|
||||
module.exports = function urange(token, getNextToken) {
|
||||
var length = 0;
|
||||
export default function urange(token, getNextToken) {
|
||||
let length = 0;
|
||||
|
||||
// should start with `u` or `U`
|
||||
if (token === null || token.type !== IDENT || !cmpChar(token.value, 0, U)) {
|
||||
if (token === null || token.type !== Ident || !cmpChar(token.value, 0, U)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ module.exports = function urange(token, getNextToken) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (token.type === IDENT) {
|
||||
if (token.type === Ident) {
|
||||
// u '+' <ident-token> '?'*
|
||||
return withQuestionMarkSequence(hexSequence(token, 0, true), ++length, getNextToken);
|
||||
}
|
||||
@@ -116,12 +116,8 @@ module.exports = function urange(token, getNextToken) {
|
||||
// u <number-token> '?'*
|
||||
// u <number-token> <dimension-token>
|
||||
// u <number-token> <number-token>
|
||||
if (token.type === NUMBER) {
|
||||
if (!startsWith(token, PLUSSIGN)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var consumedHexLength = hexSequence(token, 1, true);
|
||||
if (token.type === NumberToken) {
|
||||
const consumedHexLength = hexSequence(token, 1, true);
|
||||
if (consumedHexLength === 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -132,7 +128,7 @@ module.exports = function urange(token, getNextToken) {
|
||||
return length;
|
||||
}
|
||||
|
||||
if (token.type === DIMENSION || token.type === NUMBER) {
|
||||
if (token.type === Dimension || token.type === NumberToken) {
|
||||
// u <number-token> <dimension-token>
|
||||
// u <number-token> <number-token>
|
||||
if (!startsWith(token, HYPHENMINUS) || !hexSequence(token, 1, false)) {
|
||||
@@ -147,11 +143,7 @@ module.exports = function urange(token, getNextToken) {
|
||||
}
|
||||
|
||||
// u <dimension-token> '?'*
|
||||
if (token.type === DIMENSION) {
|
||||
if (!startsWith(token, PLUSSIGN)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (token.type === Dimension) {
|
||||
return withQuestionMarkSequence(hexSequence(token, 1, true), ++length, getNextToken);
|
||||
}
|
||||
|
||||
|
||||
479
node_modules/css-tree/lib/lexer/generic.js
generated
vendored
479
node_modules/css-tree/lib/lexer/generic.js
generated
vendored
@@ -1,83 +1,49 @@
|
||||
var tokenizer = require('../tokenizer');
|
||||
var isIdentifierStart = tokenizer.isIdentifierStart;
|
||||
var isHexDigit = tokenizer.isHexDigit;
|
||||
var isDigit = tokenizer.isDigit;
|
||||
var cmpStr = tokenizer.cmpStr;
|
||||
var consumeNumber = tokenizer.consumeNumber;
|
||||
var TYPE = tokenizer.TYPE;
|
||||
var anPlusB = require('./generic-an-plus-b');
|
||||
var urange = require('./generic-urange');
|
||||
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,
|
||||
|
||||
var cssWideKeywords = ['unset', 'initial', 'inherit'];
|
||||
var calcFunctionNames = ['calc(', '-moz-calc(', '-webkit-calc('];
|
||||
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';
|
||||
|
||||
// https://www.w3.org/TR/css-values-3/#lengths
|
||||
var LENGTH = {
|
||||
// absolute length units
|
||||
'px': true,
|
||||
'mm': true,
|
||||
'cm': true,
|
||||
'in': true,
|
||||
'pt': true,
|
||||
'pc': true,
|
||||
'q': true,
|
||||
|
||||
// relative length units
|
||||
'em': true,
|
||||
'ex': true,
|
||||
'ch': true,
|
||||
'rem': true,
|
||||
|
||||
// viewport-percentage lengths
|
||||
'vh': true,
|
||||
'vw': true,
|
||||
'vmin': true,
|
||||
'vmax': true,
|
||||
'vm': true
|
||||
};
|
||||
|
||||
var ANGLE = {
|
||||
'deg': true,
|
||||
'grad': true,
|
||||
'rad': true,
|
||||
'turn': true
|
||||
};
|
||||
|
||||
var TIME = {
|
||||
's': true,
|
||||
'ms': true
|
||||
};
|
||||
|
||||
var FREQUENCY = {
|
||||
'hz': true,
|
||||
'khz': true
|
||||
};
|
||||
|
||||
// https://www.w3.org/TR/css-values-3/#resolution (https://drafts.csswg.org/css-values/#resolution)
|
||||
var RESOLUTION = {
|
||||
'dpi': true,
|
||||
'dpcm': true,
|
||||
'dppx': true,
|
||||
'x': true // https://github.com/w3c/csswg-drafts/issues/461
|
||||
};
|
||||
|
||||
// https://drafts.csswg.org/css-grid/#fr-unit
|
||||
var FLEX = {
|
||||
'fr': true
|
||||
};
|
||||
|
||||
// https://www.w3.org/TR/css3-speech/#mixing-props-voice-volume
|
||||
var DECIBEL = {
|
||||
'db': true
|
||||
};
|
||||
|
||||
// https://www.w3.org/TR/css3-speech/#voice-props-voice-pitch
|
||||
var SEMITONES = {
|
||||
'st': true
|
||||
};
|
||||
const calcFunctionNames = ['calc(', '-moz-calc(', '-webkit-calc('];
|
||||
const balancePair = new Map([
|
||||
[FunctionToken, RightParenthesis],
|
||||
[LeftParenthesis, RightParenthesis],
|
||||
[LeftSquareBracket, RightSquareBracket],
|
||||
[LeftCurlyBracket, RightCurlyBracket]
|
||||
]);
|
||||
|
||||
// safe char code getter
|
||||
function charCode(str, index) {
|
||||
function charCodeAt(str, index) {
|
||||
return index < str.length ? str.charCodeAt(index) : 0;
|
||||
}
|
||||
|
||||
@@ -86,7 +52,7 @@ function eqStr(actual, expected) {
|
||||
}
|
||||
|
||||
function eqStrAny(actual, expected) {
|
||||
for (var i = 0; i < expected.length; i++) {
|
||||
for (let i = 0; i < expected.length; i++) {
|
||||
if (eqStr(actual, expected[i])) {
|
||||
return true;
|
||||
}
|
||||
@@ -102,14 +68,14 @@ function isPostfixIeHack(str, offset) {
|
||||
}
|
||||
|
||||
return (
|
||||
str.charCodeAt(offset) === 0x005C && // U+005C REVERSE SOLIDUS (\)
|
||||
isDigit(str.charCodeAt(offset + 1))
|
||||
charCodeAt(str, offset) === 0x005C && // U+005C REVERSE SOLIDUS (\)
|
||||
isDigit(charCodeAt(str, offset + 1))
|
||||
);
|
||||
}
|
||||
|
||||
function outOfRange(opts, value, numEnd) {
|
||||
if (opts && opts.type === 'Range') {
|
||||
var num = Number(
|
||||
const num = Number(
|
||||
numEnd !== undefined && numEnd !== value.length
|
||||
? value.substr(0, numEnd)
|
||||
: value
|
||||
@@ -119,11 +85,15 @@ function outOfRange(opts, value, numEnd) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (opts.min !== null && num < opts.min) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
if (opts.max !== null && num > opts.max) {
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
@@ -132,16 +102,40 @@ function outOfRange(opts, value, numEnd) {
|
||||
}
|
||||
|
||||
function consumeFunction(token, getNextToken) {
|
||||
var startIdx = token.index;
|
||||
var length = 0;
|
||||
let balanceCloseType = 0;
|
||||
let balanceStash = [];
|
||||
let length = 0;
|
||||
|
||||
// balanced token consuming
|
||||
scan:
|
||||
do {
|
||||
length++;
|
||||
switch (token.type) {
|
||||
case RightCurlyBracket:
|
||||
case RightParenthesis:
|
||||
case RightSquareBracket:
|
||||
if (token.type !== balanceCloseType) {
|
||||
break scan;
|
||||
}
|
||||
|
||||
if (token.balance <= startIdx) {
|
||||
break;
|
||||
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;
|
||||
@@ -156,7 +150,7 @@ function calc(next) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (token.type === TYPE.Function && eqStrAny(token.value, calcFunctionNames)) {
|
||||
if (token.type === FunctionToken && eqStrAny(token.value, calcFunctionNames)) {
|
||||
return consumeFunction(token, getNextToken);
|
||||
}
|
||||
|
||||
@@ -174,18 +168,6 @@ function tokenType(expectedTokenType) {
|
||||
};
|
||||
}
|
||||
|
||||
function func(name) {
|
||||
name = name + '(';
|
||||
|
||||
return function(token, getNextToken) {
|
||||
if (token !== null && eqStr(token.value, name)) {
|
||||
return consumeFunction(token, getNextToken);
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
// =========================
|
||||
// Complex types
|
||||
//
|
||||
@@ -198,11 +180,11 @@ function func(name) {
|
||||
//
|
||||
// See also: https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident
|
||||
function customIdent(token) {
|
||||
if (token === null || token.type !== TYPE.Ident) {
|
||||
if (token === null || token.type !== Ident) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var name = token.value.toLowerCase();
|
||||
const name = token.value.toLowerCase();
|
||||
|
||||
// The CSS-wide keywords are not valid <custom-ident>s
|
||||
if (eqStrAny(name, cssWideKeywords)) {
|
||||
@@ -223,19 +205,34 @@ function customIdent(token) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/css-variables/#typedef-custom-property-name
|
||||
// A custom property is any property whose name starts with two dashes (U+002D HYPHEN-MINUS), like --foo.
|
||||
// The <custom-property-name> production corresponds to this: it’s defined as any valid identifier
|
||||
// that starts with two dashes, except -- itself, which is reserved for future use by CSS.
|
||||
// NOTE: Current implementation treat `--` as a valid name since most (all?) major browsers treat it as valid.
|
||||
function customPropertyName(token) {
|
||||
// ... defined as any valid identifier
|
||||
if (token === null || token.type !== TYPE.Ident) {
|
||||
// https://drafts.csswg.org/css-values-4/#dashed-idents
|
||||
// The <dashed-ident> production is a <custom-ident>, with all the case-sensitivity that implies,
|
||||
// with the additional restriction that it must start with two dashes (U+002D HYPHEN-MINUS).
|
||||
function dashedIdent(token) {
|
||||
if (token === null || token.type !== Ident) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ... that starts with two dashes (U+002D HYPHEN-MINUS)
|
||||
if (charCode(token.value, 0) !== 0x002D || charCode(token.value, 1) !== 0x002D) {
|
||||
// ... must start with two dashes (U+002D HYPHEN-MINUS)
|
||||
if (charCodeAt(token.value, 0) !== 0x002D || charCodeAt(token.value, 1) !== 0x002D) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/css-variables/#typedef-custom-property-name
|
||||
// A custom property is any property whose name starts with two dashes (U+002D HYPHEN-MINUS), like --foo.
|
||||
// The <custom-property-name> production corresponds to this: it’s defined as any <dashed-ident>
|
||||
// (a valid identifier that starts with two dashes), except -- itself, which is reserved for future use by CSS.
|
||||
function customPropertyName(token) {
|
||||
// ... it’s defined as any <dashed-ident>
|
||||
if (!dashedIdent(token)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ... except -- itself, which is reserved for future use by CSS
|
||||
if (token.value === '--') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -247,19 +244,19 @@ function customPropertyName(token) {
|
||||
// In other words, a hex color is written as a hash character, "#", followed by some number of digits 0-9 or
|
||||
// letters a-f (the case of the letters doesn’t matter - #00ff00 is identical to #00FF00).
|
||||
function hexColor(token) {
|
||||
if (token === null || token.type !== TYPE.Hash) {
|
||||
if (token === null || token.type !== Hash) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var length = token.value.length;
|
||||
const length = token.value.length;
|
||||
|
||||
// valid values (length): #rgb (4), #rgba (5), #rrggbb (7), #rrggbbaa (9)
|
||||
if (length !== 4 && length !== 5 && length !== 7 && length !== 9) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (var i = 1; i < length; i++) {
|
||||
if (!isHexDigit(token.value.charCodeAt(i))) {
|
||||
for (let i = 1; i < length; i++) {
|
||||
if (!isHexDigit(charCodeAt(token.value, i))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -268,11 +265,11 @@ function hexColor(token) {
|
||||
}
|
||||
|
||||
function idSelector(token) {
|
||||
if (token === null || token.type !== TYPE.Hash) {
|
||||
if (token === null || token.type !== Hash) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!isIdentifierStart(charCode(token.value, 1), charCode(token.value, 2), charCode(token.value, 3))) {
|
||||
if (!isIdentifierStart(charCodeAt(token.value, 1), charCodeAt(token.value, 2), charCodeAt(token.value, 3))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -286,61 +283,57 @@ function declarationValue(token, getNextToken) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var length = 0;
|
||||
var level = 0;
|
||||
var startIdx = token.index;
|
||||
let balanceCloseType = 0;
|
||||
let balanceStash = [];
|
||||
let length = 0;
|
||||
|
||||
// The <declaration-value> production matches any sequence of one or more tokens,
|
||||
// so long as the sequence ...
|
||||
// so long as the sequence does not contain ...
|
||||
scan:
|
||||
do {
|
||||
switch (token.type) {
|
||||
// ... does not contain <bad-string-token>, <bad-url-token>,
|
||||
case TYPE.BadString:
|
||||
case TYPE.BadUrl:
|
||||
// ... <bad-string-token>, <bad-url-token>,
|
||||
case BadString:
|
||||
case BadUrl:
|
||||
break scan;
|
||||
|
||||
// ... unmatched <)-token>, <]-token>, or <}-token>,
|
||||
case TYPE.RightCurlyBracket:
|
||||
case TYPE.RightParenthesis:
|
||||
case TYPE.RightSquareBracket:
|
||||
if (token.balance > token.index || token.balance < startIdx) {
|
||||
case RightCurlyBracket:
|
||||
case RightParenthesis:
|
||||
case RightSquareBracket:
|
||||
if (token.type !== balanceCloseType) {
|
||||
break scan;
|
||||
}
|
||||
|
||||
level--;
|
||||
balanceCloseType = balanceStash.pop();
|
||||
break;
|
||||
|
||||
// ... or top-level <semicolon-token> tokens
|
||||
case TYPE.Semicolon:
|
||||
if (level === 0) {
|
||||
case Semicolon:
|
||||
if (balanceCloseType === 0) {
|
||||
break scan;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// ... or <delim-token> tokens with a value of "!"
|
||||
case TYPE.Delim:
|
||||
if (token.value === '!' && level === 0) {
|
||||
case Delim:
|
||||
if (balanceCloseType === 0 && token.value === '!') {
|
||||
break scan;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TYPE.Function:
|
||||
case TYPE.LeftParenthesis:
|
||||
case TYPE.LeftSquareBracket:
|
||||
case TYPE.LeftCurlyBracket:
|
||||
level++;
|
||||
case FunctionToken:
|
||||
case LeftParenthesis:
|
||||
case LeftSquareBracket:
|
||||
case LeftCurlyBracket:
|
||||
balanceStash.push(balanceCloseType);
|
||||
balanceCloseType = balancePair.get(token.type);
|
||||
break;
|
||||
}
|
||||
|
||||
length++;
|
||||
|
||||
// until balance closing
|
||||
if (token.balance <= startIdx) {
|
||||
break;
|
||||
}
|
||||
} while (token = getNextToken(length));
|
||||
|
||||
return length;
|
||||
@@ -355,8 +348,9 @@ function anyValue(token, getNextToken) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var startIdx = token.index;
|
||||
var length = 0;
|
||||
let balanceCloseType = 0;
|
||||
let balanceStash = [];
|
||||
let length = 0;
|
||||
|
||||
// The <any-value> production matches any sequence of one or more tokens,
|
||||
// so long as the sequence ...
|
||||
@@ -364,27 +358,31 @@ function anyValue(token, getNextToken) {
|
||||
do {
|
||||
switch (token.type) {
|
||||
// ... does not contain <bad-string-token>, <bad-url-token>,
|
||||
case TYPE.BadString:
|
||||
case TYPE.BadUrl:
|
||||
case BadString:
|
||||
case BadUrl:
|
||||
break scan;
|
||||
|
||||
// ... unmatched <)-token>, <]-token>, or <}-token>,
|
||||
case TYPE.RightCurlyBracket:
|
||||
case TYPE.RightParenthesis:
|
||||
case TYPE.RightSquareBracket:
|
||||
if (token.balance > token.index || token.balance < startIdx) {
|
||||
case RightCurlyBracket:
|
||||
case RightParenthesis:
|
||||
case RightSquareBracket:
|
||||
if (token.type !== balanceCloseType) {
|
||||
break scan;
|
||||
}
|
||||
|
||||
balanceCloseType = balanceStash.pop();
|
||||
break;
|
||||
|
||||
case FunctionToken:
|
||||
case LeftParenthesis:
|
||||
case LeftSquareBracket:
|
||||
case LeftCurlyBracket:
|
||||
balanceStash.push(balanceCloseType);
|
||||
balanceCloseType = balancePair.get(token.type);
|
||||
break;
|
||||
}
|
||||
|
||||
length++;
|
||||
|
||||
// until balance closing
|
||||
if (token.balance <= startIdx) {
|
||||
break;
|
||||
}
|
||||
} while (token = getNextToken(length));
|
||||
|
||||
return length;
|
||||
@@ -395,22 +393,26 @@ function anyValue(token, getNextToken) {
|
||||
//
|
||||
|
||||
function dimension(type) {
|
||||
if (type) {
|
||||
type = new Set(type);
|
||||
}
|
||||
|
||||
return function(token, getNextToken, opts) {
|
||||
if (token === null || token.type !== TYPE.Dimension) {
|
||||
if (token === null || token.type !== Dimension) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var numberEnd = consumeNumber(token.value, 0);
|
||||
const numberEnd = consumeNumber(token.value, 0);
|
||||
|
||||
// check unit
|
||||
if (type !== null) {
|
||||
// check for IE postfix hack, i.e. 123px\0 or 123px\9
|
||||
var reverseSolidusOffset = token.value.indexOf('\\', numberEnd);
|
||||
var unit = reverseSolidusOffset === -1 || !isPostfixIeHack(token.value, reverseSolidusOffset)
|
||||
const reverseSolidusOffset = token.value.indexOf('\\', numberEnd);
|
||||
const unit = reverseSolidusOffset === -1 || !isPostfixIeHack(token.value, reverseSolidusOffset)
|
||||
? token.value.substr(numberEnd)
|
||||
: token.value.substring(numberEnd, reverseSolidusOffset);
|
||||
|
||||
if (type.hasOwnProperty(unit.toLowerCase()) === false) {
|
||||
if (type.has(unit.toLowerCase()) === false) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -432,7 +434,7 @@ function dimension(type) {
|
||||
// https://drafts.csswg.org/css-values-4/#percentages
|
||||
function percentage(token, getNextToken, opts) {
|
||||
// ... corresponds to the <percentage-token> production
|
||||
if (token === null || token.type !== TYPE.Percentage) {
|
||||
if (token === null || token.type !== Percentage) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -460,7 +462,7 @@ function zero(next) {
|
||||
}
|
||||
|
||||
return function(token, getNextToken, opts) {
|
||||
if (token !== null && token.type === TYPE.Number) {
|
||||
if (token !== null && token.type === NumberToken) {
|
||||
if (Number(token.value) === 0) {
|
||||
return 1;
|
||||
}
|
||||
@@ -479,8 +481,8 @@ function number(token, getNextToken, opts) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var numberEnd = consumeNumber(token.value, 0);
|
||||
var isNumber = numberEnd === token.value.length;
|
||||
const numberEnd = consumeNumber(token.value, 0);
|
||||
const isNumber = numberEnd === token.value.length;
|
||||
if (!isNumber && !isPostfixIeHack(token.value, numberEnd)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -497,17 +499,17 @@ function number(token, getNextToken, opts) {
|
||||
// https://drafts.csswg.org/css-values-4/#integers
|
||||
function integer(token, getNextToken, opts) {
|
||||
// ... corresponds to a subset of the <number-token> production
|
||||
if (token === null || token.type !== TYPE.Number) {
|
||||
if (token === null || token.type !== NumberToken) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The first digit of an integer may be immediately preceded by `-` or `+` to indicate the integer’s sign.
|
||||
var i = token.value.charCodeAt(0) === 0x002B || // U+002B PLUS SIGN (+)
|
||||
token.value.charCodeAt(0) === 0x002D ? 1 : 0; // U+002D HYPHEN-MINUS (-)
|
||||
let i = charCodeAt(token.value, 0) === 0x002B || // U+002B PLUS SIGN (+)
|
||||
charCodeAt(token.value, 0) === 0x002D ? 1 : 0; // U+002D HYPHEN-MINUS (-)
|
||||
|
||||
// When written literally, an integer is one or more decimal digits 0 through 9 ...
|
||||
for (; i < token.value.length; i++) {
|
||||
if (!isDigit(token.value.charCodeAt(i))) {
|
||||
if (!isDigit(charCodeAt(token.value, i))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -520,57 +522,39 @@ function integer(token, getNextToken, opts) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
// token types
|
||||
'ident-token': tokenType(TYPE.Ident),
|
||||
'function-token': tokenType(TYPE.Function),
|
||||
'at-keyword-token': tokenType(TYPE.AtKeyword),
|
||||
'hash-token': tokenType(TYPE.Hash),
|
||||
'string-token': tokenType(TYPE.String),
|
||||
'bad-string-token': tokenType(TYPE.BadString),
|
||||
'url-token': tokenType(TYPE.Url),
|
||||
'bad-url-token': tokenType(TYPE.BadUrl),
|
||||
'delim-token': tokenType(TYPE.Delim),
|
||||
'number-token': tokenType(TYPE.Number),
|
||||
'percentage-token': tokenType(TYPE.Percentage),
|
||||
'dimension-token': tokenType(TYPE.Dimension),
|
||||
'whitespace-token': tokenType(TYPE.WhiteSpace),
|
||||
'CDO-token': tokenType(TYPE.CDO),
|
||||
'CDC-token': tokenType(TYPE.CDC),
|
||||
'colon-token': tokenType(TYPE.Colon),
|
||||
'semicolon-token': tokenType(TYPE.Semicolon),
|
||||
'comma-token': tokenType(TYPE.Comma),
|
||||
'[-token': tokenType(TYPE.LeftSquareBracket),
|
||||
']-token': tokenType(TYPE.RightSquareBracket),
|
||||
'(-token': tokenType(TYPE.LeftParenthesis),
|
||||
')-token': tokenType(TYPE.RightParenthesis),
|
||||
'{-token': tokenType(TYPE.LeftCurlyBracket),
|
||||
'}-token': tokenType(TYPE.RightCurlyBracket),
|
||||
// token types
|
||||
export const tokenTypes = {
|
||||
'ident-token': tokenType(Ident),
|
||||
'function-token': tokenType(FunctionToken),
|
||||
'at-keyword-token': tokenType(AtKeyword),
|
||||
'hash-token': tokenType(Hash),
|
||||
'string-token': tokenType(StringToken),
|
||||
'bad-string-token': tokenType(BadString),
|
||||
'url-token': tokenType(Url),
|
||||
'bad-url-token': tokenType(BadUrl),
|
||||
'delim-token': tokenType(Delim),
|
||||
'number-token': tokenType(NumberToken),
|
||||
'percentage-token': tokenType(Percentage),
|
||||
'dimension-token': tokenType(Dimension),
|
||||
'whitespace-token': tokenType(WhiteSpace),
|
||||
'CDO-token': tokenType(CDO),
|
||||
'CDC-token': tokenType(CDC),
|
||||
'colon-token': tokenType(Colon),
|
||||
'semicolon-token': tokenType(Semicolon),
|
||||
'comma-token': tokenType(Comma),
|
||||
'[-token': tokenType(LeftSquareBracket),
|
||||
']-token': tokenType(RightSquareBracket),
|
||||
'(-token': tokenType(LeftParenthesis),
|
||||
')-token': tokenType(RightParenthesis),
|
||||
'{-token': tokenType(LeftCurlyBracket),
|
||||
'}-token': tokenType(RightCurlyBracket)
|
||||
};
|
||||
|
||||
// token production types
|
||||
export const productionTypes = {
|
||||
// token type aliases
|
||||
'string': tokenType(TYPE.String),
|
||||
'ident': tokenType(TYPE.Ident),
|
||||
|
||||
// complex types
|
||||
'custom-ident': customIdent,
|
||||
'custom-property-name': customPropertyName,
|
||||
'hex-color': hexColor,
|
||||
'id-selector': idSelector, // element( <id-selector> )
|
||||
'an-plus-b': anPlusB,
|
||||
'urange': urange,
|
||||
'declaration-value': declarationValue,
|
||||
'any-value': anyValue,
|
||||
|
||||
// dimensions
|
||||
'dimension': calc(dimension(null)),
|
||||
'angle': calc(dimension(ANGLE)),
|
||||
'decibel': calc(dimension(DECIBEL)),
|
||||
'frequency': calc(dimension(FREQUENCY)),
|
||||
'flex': calc(dimension(FLEX)),
|
||||
'length': calc(zero(dimension(LENGTH))),
|
||||
'resolution': calc(dimension(RESOLUTION)),
|
||||
'semitones': calc(dimension(SEMITONES)),
|
||||
'time': calc(dimension(TIME)),
|
||||
'string': tokenType(StringToken),
|
||||
'ident': tokenType(Ident),
|
||||
|
||||
// percentage
|
||||
'percentage': calc(percentage),
|
||||
@@ -580,6 +564,59 @@ module.exports = {
|
||||
'number': calc(number),
|
||||
'integer': calc(integer),
|
||||
|
||||
// old IE stuff
|
||||
'-ms-legacy-expression': func('expression')
|
||||
// complex types
|
||||
'custom-ident': customIdent,
|
||||
'dashed-ident': dashedIdent,
|
||||
'custom-property-name': customPropertyName,
|
||||
'hex-color': hexColor,
|
||||
'id-selector': idSelector, // element( <id-selector> )
|
||||
'an-plus-b': anPlusB,
|
||||
'urange': urange,
|
||||
'declaration-value': declarationValue,
|
||||
'any-value': anyValue
|
||||
};
|
||||
|
||||
export const unitGroups = [
|
||||
'length',
|
||||
'angle',
|
||||
'time',
|
||||
'frequency',
|
||||
'resolution',
|
||||
'flex',
|
||||
'decibel',
|
||||
'semitones'
|
||||
];
|
||||
|
||||
// dimensions types depend on units set
|
||||
export function createDemensionTypes(units) {
|
||||
const {
|
||||
angle,
|
||||
decibel,
|
||||
frequency,
|
||||
flex,
|
||||
length,
|
||||
resolution,
|
||||
semitones,
|
||||
time
|
||||
} = units || {};
|
||||
|
||||
return {
|
||||
'dimension': calc(dimension(null)),
|
||||
'angle': calc(dimension(angle)),
|
||||
'decibel': calc(dimension(decibel)),
|
||||
'frequency': calc(dimension(frequency)),
|
||||
'flex': calc(dimension(flex)),
|
||||
'length': calc(zero(dimension(length))),
|
||||
'resolution': calc(dimension(resolution)),
|
||||
'semitones': calc(dimension(semitones)),
|
||||
'time': calc(dimension(time))
|
||||
};
|
||||
}
|
||||
|
||||
export function createGenericTypes(units) {
|
||||
return {
|
||||
...tokenTypes,
|
||||
...productionTypes,
|
||||
...createDemensionTypes(units)
|
||||
};
|
||||
};
|
||||
|
||||
4
node_modules/css-tree/lib/lexer/index.js
generated
vendored
4
node_modules/css-tree/lib/lexer/index.js
generated
vendored
@@ -1,3 +1 @@
|
||||
module.exports = {
|
||||
Lexer: require('./Lexer')
|
||||
};
|
||||
export { Lexer } from './Lexer.js';
|
||||
|
||||
180
node_modules/css-tree/lib/lexer/match-graph.js
generated
vendored
180
node_modules/css-tree/lib/lexer/match-graph.js
generated
vendored
@@ -1,10 +1,11 @@
|
||||
var parse = require('../definition-syntax/parse');
|
||||
import { parse } from '../definition-syntax/parse.js';
|
||||
|
||||
var MATCH = { type: 'Match' };
|
||||
var MISMATCH = { type: 'Mismatch' };
|
||||
var DISALLOW_EMPTY = { type: 'DisallowEmpty' };
|
||||
var LEFTPARENTHESIS = 40; // (
|
||||
var RIGHTPARENTHESIS = 41; // )
|
||||
export const MATCH = { type: 'Match' };
|
||||
export const MISMATCH = { type: 'Mismatch' };
|
||||
export const DISALLOW_EMPTY = { type: 'DisallowEmpty' };
|
||||
|
||||
const LEFTPARENTHESIS = 40; // (
|
||||
const RIGHTPARENTHESIS = 41; // )
|
||||
|
||||
function createCondition(match, thenBranch, elseBranch) {
|
||||
// reduce node count
|
||||
@@ -23,7 +24,7 @@ function createCondition(match, thenBranch, elseBranch) {
|
||||
|
||||
return {
|
||||
type: 'If',
|
||||
match: match,
|
||||
match,
|
||||
then: thenBranch,
|
||||
else: elseBranch
|
||||
};
|
||||
@@ -46,9 +47,38 @@ function isEnumCapatible(term) {
|
||||
);
|
||||
}
|
||||
|
||||
function groupNode(terms, combinator = ' ', explicit = false) {
|
||||
return {
|
||||
type: 'Group',
|
||||
terms,
|
||||
combinator,
|
||||
disallowEmpty: false,
|
||||
explicit
|
||||
};
|
||||
}
|
||||
|
||||
function replaceTypeInGraph(node, replacements, visited = new Set()) {
|
||||
if (!visited.has(node)) {
|
||||
visited.add(node);
|
||||
|
||||
switch (node.type) {
|
||||
case 'If':
|
||||
node.match = replaceTypeInGraph(node.match, replacements, visited);
|
||||
node.then = replaceTypeInGraph(node.then, replacements, visited);
|
||||
node.else = replaceTypeInGraph(node.else, replacements, visited);
|
||||
break;
|
||||
|
||||
case 'Type':
|
||||
return replacements[node.name] || node;
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
function buildGroupMatchGraph(combinator, terms, atLeastOneTermMatched) {
|
||||
switch (combinator) {
|
||||
case ' ':
|
||||
case ' ': {
|
||||
// Juxtaposing components means that all of them must occur, in the given order.
|
||||
//
|
||||
// a b c
|
||||
@@ -60,10 +90,10 @@ function buildGroupMatchGraph(combinator, terms, atLeastOneTermMatched) {
|
||||
// else MISMATCH
|
||||
// else MISMATCH
|
||||
// else MISMATCH
|
||||
var result = MATCH;
|
||||
let result = MATCH;
|
||||
|
||||
for (var i = terms.length - 1; i >= 0; i--) {
|
||||
var term = terms[i];
|
||||
for (let i = terms.length - 1; i >= 0; i--) {
|
||||
const term = terms[i];
|
||||
|
||||
result = createCondition(
|
||||
term,
|
||||
@@ -73,8 +103,9 @@ function buildGroupMatchGraph(combinator, terms, atLeastOneTermMatched) {
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
case '|':
|
||||
case '|': {
|
||||
// A bar (|) separates two or more alternatives: exactly one of them must occur.
|
||||
//
|
||||
// a | b | c
|
||||
@@ -87,11 +118,11 @@ function buildGroupMatchGraph(combinator, terms, atLeastOneTermMatched) {
|
||||
// then MATCH
|
||||
// else MISMATCH
|
||||
|
||||
var result = MISMATCH;
|
||||
var map = null;
|
||||
let result = MISMATCH;
|
||||
let map = null;
|
||||
|
||||
for (var i = terms.length - 1; i >= 0; i--) {
|
||||
var term = terms[i];
|
||||
for (let i = terms.length - 1; i >= 0; i--) {
|
||||
let term = terms[i];
|
||||
|
||||
// reduce sequence of keywords into a Enum
|
||||
if (isEnumCapatible(term)) {
|
||||
@@ -100,7 +131,7 @@ function buildGroupMatchGraph(combinator, terms, atLeastOneTermMatched) {
|
||||
result = createCondition(
|
||||
{
|
||||
type: 'Enum',
|
||||
map: map
|
||||
map
|
||||
},
|
||||
MATCH,
|
||||
result
|
||||
@@ -108,7 +139,7 @@ function buildGroupMatchGraph(combinator, terms, atLeastOneTermMatched) {
|
||||
}
|
||||
|
||||
if (map !== null) {
|
||||
var key = (isFunctionType(term.name) ? term.name.slice(0, -1) : term.name).toLowerCase();
|
||||
const key = (isFunctionType(term.name) ? term.name.slice(0, -1) : term.name).toLowerCase();
|
||||
if (key in map === false) {
|
||||
map[key] = term;
|
||||
continue;
|
||||
@@ -127,8 +158,9 @@ function buildGroupMatchGraph(combinator, terms, atLeastOneTermMatched) {
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
case '&&':
|
||||
case '&&': {
|
||||
// A double ampersand (&&) separates two or more components,
|
||||
// all of which must occur, in any order.
|
||||
|
||||
@@ -137,7 +169,7 @@ function buildGroupMatchGraph(combinator, terms, atLeastOneTermMatched) {
|
||||
if (terms.length > 5) {
|
||||
return {
|
||||
type: 'MatchOnce',
|
||||
terms: terms,
|
||||
terms,
|
||||
all: true
|
||||
};
|
||||
}
|
||||
@@ -165,11 +197,11 @@ function buildGroupMatchGraph(combinator, terms, atLeastOneTermMatched) {
|
||||
// then MATCH
|
||||
// else MISMATCH
|
||||
// else MISMATCH
|
||||
var result = MISMATCH;
|
||||
let result = MISMATCH;
|
||||
|
||||
for (var i = terms.length - 1; i >= 0; i--) {
|
||||
var term = terms[i];
|
||||
var thenClause;
|
||||
for (let i = terms.length - 1; i >= 0; i--) {
|
||||
const term = terms[i];
|
||||
let thenClause;
|
||||
|
||||
if (terms.length > 1) {
|
||||
thenClause = buildGroupMatchGraph(
|
||||
@@ -191,8 +223,9 @@ function buildGroupMatchGraph(combinator, terms, atLeastOneTermMatched) {
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
case '||':
|
||||
case '||': {
|
||||
// A double bar (||) separates two or more options:
|
||||
// one or more of them must occur, in any order.
|
||||
|
||||
@@ -201,7 +234,7 @@ function buildGroupMatchGraph(combinator, terms, atLeastOneTermMatched) {
|
||||
if (terms.length > 5) {
|
||||
return {
|
||||
type: 'MatchOnce',
|
||||
terms: terms,
|
||||
terms,
|
||||
all: false
|
||||
};
|
||||
}
|
||||
@@ -229,11 +262,11 @@ function buildGroupMatchGraph(combinator, terms, atLeastOneTermMatched) {
|
||||
// then MATCH
|
||||
// else MATCH
|
||||
// else MISMATCH
|
||||
var result = atLeastOneTermMatched ? MATCH : MISMATCH;
|
||||
let result = atLeastOneTermMatched ? MATCH : MISMATCH;
|
||||
|
||||
for (var i = terms.length - 1; i >= 0; i--) {
|
||||
var term = terms[i];
|
||||
var thenClause;
|
||||
for (let i = terms.length - 1; i >= 0; i--) {
|
||||
const term = terms[i];
|
||||
let thenClause;
|
||||
|
||||
if (terms.length > 1) {
|
||||
thenClause = buildGroupMatchGraph(
|
||||
@@ -255,12 +288,13 @@ function buildGroupMatchGraph(combinator, terms, atLeastOneTermMatched) {
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function buildMultiplierMatchGraph(node) {
|
||||
var result = MATCH;
|
||||
var matchTerm = buildMatchGraph(node.term);
|
||||
let result = MATCH;
|
||||
let matchTerm = buildMatchGraphInternal(node.term);
|
||||
|
||||
if (node.max === 0) {
|
||||
// disable repeating of empty match to prevent infinite loop
|
||||
@@ -293,7 +327,7 @@ function buildMultiplierMatchGraph(node) {
|
||||
}
|
||||
} else {
|
||||
// create a match node chain for [min .. max] interval with optional matches
|
||||
for (var i = node.min || 1; i <= node.max; i++) {
|
||||
for (let i = node.min || 1; i <= node.max; i++) {
|
||||
if (node.comma && result !== MATCH) {
|
||||
result = createCondition(
|
||||
{ type: 'Comma', syntax: node },
|
||||
@@ -323,7 +357,7 @@ function buildMultiplierMatchGraph(node) {
|
||||
);
|
||||
} else {
|
||||
// create a match node chain to collect [0 ... min - 1] required matches
|
||||
for (var i = 0; i < node.min - 1; i++) {
|
||||
for (let i = 0; i < node.min - 1; i++) {
|
||||
if (node.comma && result !== MATCH) {
|
||||
result = createCondition(
|
||||
{ type: 'Comma', syntax: node },
|
||||
@@ -343,7 +377,7 @@ function buildMultiplierMatchGraph(node) {
|
||||
return result;
|
||||
}
|
||||
|
||||
function buildMatchGraph(node) {
|
||||
function buildMatchGraphInternal(node) {
|
||||
if (typeof node === 'function') {
|
||||
return {
|
||||
type: 'Generic',
|
||||
@@ -352,10 +386,10 @@ function buildMatchGraph(node) {
|
||||
}
|
||||
|
||||
switch (node.type) {
|
||||
case 'Group':
|
||||
var result = buildGroupMatchGraph(
|
||||
case 'Group': {
|
||||
let result = buildGroupMatchGraph(
|
||||
node.combinator,
|
||||
node.terms.map(buildMatchGraph),
|
||||
node.terms.map(buildMatchGraphInternal),
|
||||
false
|
||||
);
|
||||
|
||||
@@ -368,10 +402,53 @@ function buildMatchGraph(node) {
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
case 'Multiplier':
|
||||
return buildMultiplierMatchGraph(node);
|
||||
|
||||
// https://drafts.csswg.org/css-values-5/#boolean
|
||||
case 'Boolean': {
|
||||
const term = buildMatchGraphInternal(node.term);
|
||||
// <boolean-expr[ <test> ]> = not <boolean-expr-group> | <boolean-expr-group> [ [ and <boolean-expr-group> ]* | [ or <boolean-expr-group> ]* ]
|
||||
const matchNode = buildMatchGraphInternal(groupNode([
|
||||
groupNode([
|
||||
{ type: 'Keyword', name: 'not' },
|
||||
{ type: 'Type', name: '!boolean-group' }
|
||||
]),
|
||||
groupNode([
|
||||
{ type: 'Type', name: '!boolean-group' },
|
||||
groupNode([
|
||||
{ type: 'Multiplier', comma: false, min: 0, max: 0, term: groupNode([
|
||||
{ type: 'Keyword', name: 'and' },
|
||||
{ type: 'Type', name: '!boolean-group' }
|
||||
]) },
|
||||
{ type: 'Multiplier', comma: false, min: 0, max: 0, term: groupNode([
|
||||
{ type: 'Keyword', name: 'or' },
|
||||
{ type: 'Type', name: '!boolean-group' }
|
||||
]) }
|
||||
], '|')
|
||||
])
|
||||
], '|'));
|
||||
// <boolean-expr-group> = <test> | ( <boolean-expr[ <test> ]> ) | <general-enclosed>
|
||||
const booleanGroup = buildMatchGraphInternal(
|
||||
groupNode([
|
||||
{ type: 'Type', name: '!term' },
|
||||
groupNode([
|
||||
{ type: 'Token', value: '(' },
|
||||
{ type: 'Type', name: '!self' },
|
||||
{ type: 'Token', value: ')' }
|
||||
]),
|
||||
{ type: 'Type', name: 'general-enclosed' }
|
||||
], '|')
|
||||
);
|
||||
|
||||
replaceTypeInGraph(booleanGroup, { '!term': term, '!self': matchNode });
|
||||
replaceTypeInGraph(matchNode, { '!boolean-group': booleanGroup });
|
||||
|
||||
return matchNode;
|
||||
}
|
||||
|
||||
case 'Type':
|
||||
case 'Property':
|
||||
return {
|
||||
@@ -436,20 +513,15 @@ function buildMatchGraph(node) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
MATCH: MATCH,
|
||||
MISMATCH: MISMATCH,
|
||||
DISALLOW_EMPTY: DISALLOW_EMPTY,
|
||||
buildMatchGraph: function(syntaxTree, ref) {
|
||||
if (typeof syntaxTree === 'string') {
|
||||
syntaxTree = parse(syntaxTree);
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'MatchGraph',
|
||||
match: buildMatchGraph(syntaxTree),
|
||||
syntax: ref || null,
|
||||
source: syntaxTree
|
||||
};
|
||||
export function buildMatchGraph(syntaxTree, ref) {
|
||||
if (typeof syntaxTree === 'string') {
|
||||
syntaxTree = parse(syntaxTree);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
type: 'MatchGraph',
|
||||
match: buildMatchGraphInternal(syntaxTree),
|
||||
syntax: ref || null,
|
||||
source: syntaxTree
|
||||
};
|
||||
}
|
||||
|
||||
155
node_modules/css-tree/lib/lexer/match.js
generated
vendored
155
node_modules/css-tree/lib/lexer/match.js
generated
vendored
@@ -1,26 +1,23 @@
|
||||
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
var matchGraph = require('./match-graph');
|
||||
var MATCH = matchGraph.MATCH;
|
||||
var MISMATCH = matchGraph.MISMATCH;
|
||||
var DISALLOW_EMPTY = matchGraph.DISALLOW_EMPTY;
|
||||
var TYPE = require('../tokenizer/const').TYPE;
|
||||
import { MATCH, MISMATCH, DISALLOW_EMPTY } from './match-graph.js';
|
||||
import * as TYPE from '../tokenizer/types.js';
|
||||
|
||||
var STUB = 0;
|
||||
var TOKEN = 1;
|
||||
var OPEN_SYNTAX = 2;
|
||||
var CLOSE_SYNTAX = 3;
|
||||
const { hasOwnProperty } = Object.prototype;
|
||||
const STUB = 0;
|
||||
const TOKEN = 1;
|
||||
const OPEN_SYNTAX = 2;
|
||||
const CLOSE_SYNTAX = 3;
|
||||
|
||||
var EXIT_REASON_MATCH = 'Match';
|
||||
var EXIT_REASON_MISMATCH = 'Mismatch';
|
||||
var EXIT_REASON_ITERATION_LIMIT = 'Maximum iteration number exceeded (please fill an issue on https://github.com/csstree/csstree/issues)';
|
||||
const EXIT_REASON_MATCH = 'Match';
|
||||
const EXIT_REASON_MISMATCH = 'Mismatch';
|
||||
const EXIT_REASON_ITERATION_LIMIT = 'Maximum iteration number exceeded (please fill an issue on https://github.com/csstree/csstree/issues)';
|
||||
|
||||
var ITERATION_LIMIT = 15000;
|
||||
var totalIterationCount = 0;
|
||||
const ITERATION_LIMIT = 15000;
|
||||
export let totalIterationCount = 0;
|
||||
|
||||
function reverseList(list) {
|
||||
var prev = null;
|
||||
var next = null;
|
||||
var item = list;
|
||||
let prev = null;
|
||||
let next = null;
|
||||
let item = list;
|
||||
|
||||
while (item !== null) {
|
||||
next = item.prev;
|
||||
@@ -37,9 +34,9 @@ function areStringsEqualCaseInsensitive(testStr, referenceStr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < testStr.length; i++) {
|
||||
var testCode = testStr.charCodeAt(i);
|
||||
var referenceCode = referenceStr.charCodeAt(i);
|
||||
for (let i = 0; i < testStr.length; i++) {
|
||||
const referenceCode = referenceStr.charCodeAt(i);
|
||||
let testCode = testStr.charCodeAt(i);
|
||||
|
||||
// testCode.toLowerCase() for U+0041 LATIN CAPITAL LETTER A (A) .. U+005A LATIN CAPITAL LETTER Z (Z).
|
||||
if (testCode >= 0x0041 && testCode <= 0x005A) {
|
||||
@@ -88,7 +85,7 @@ function isCommaContextEnd(token) {
|
||||
token.type === TYPE.RightParenthesis ||
|
||||
token.type === TYPE.RightSquareBracket ||
|
||||
token.type === TYPE.RightCurlyBracket ||
|
||||
token.type === TYPE.Delim
|
||||
(token.type === TYPE.Delim && token.value === '/')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -101,27 +98,27 @@ function internalMatch(tokens, state, syntaxes) {
|
||||
}
|
||||
|
||||
function getNextToken(offset) {
|
||||
var nextIndex = tokenIndex + offset;
|
||||
const nextIndex = tokenIndex + offset;
|
||||
|
||||
return nextIndex < tokens.length ? tokens[nextIndex] : null;
|
||||
}
|
||||
|
||||
function stateSnapshotFromSyntax(nextState, prev) {
|
||||
return {
|
||||
nextState: nextState,
|
||||
matchStack: matchStack,
|
||||
syntaxStack: syntaxStack,
|
||||
thenStack: thenStack,
|
||||
tokenIndex: tokenIndex,
|
||||
prev: prev
|
||||
nextState,
|
||||
matchStack,
|
||||
syntaxStack,
|
||||
thenStack,
|
||||
tokenIndex,
|
||||
prev
|
||||
};
|
||||
}
|
||||
|
||||
function pushThenStack(nextState) {
|
||||
thenStack = {
|
||||
nextState: nextState,
|
||||
matchStack: matchStack,
|
||||
syntaxStack: syntaxStack,
|
||||
nextState,
|
||||
matchStack,
|
||||
syntaxStack,
|
||||
prev: thenStack
|
||||
};
|
||||
}
|
||||
@@ -134,7 +131,7 @@ function internalMatch(tokens, state, syntaxes) {
|
||||
matchStack = {
|
||||
type: TOKEN,
|
||||
syntax: state.syntax,
|
||||
token: token,
|
||||
token,
|
||||
prev: matchStack
|
||||
};
|
||||
|
||||
@@ -176,22 +173,22 @@ function internalMatch(tokens, state, syntaxes) {
|
||||
syntaxStack = syntaxStack.prev;
|
||||
}
|
||||
|
||||
var syntaxStack = null;
|
||||
var thenStack = null;
|
||||
var elseStack = null;
|
||||
let syntaxStack = null;
|
||||
let thenStack = null;
|
||||
let elseStack = null;
|
||||
|
||||
// null – stashing allowed, nothing stashed
|
||||
// false – stashing disabled, nothing stashed
|
||||
// anithing else – fail stashable syntaxes, some syntax stashed
|
||||
var syntaxStash = null;
|
||||
let syntaxStash = null;
|
||||
|
||||
var iterationCount = 0; // count iterations and prevent infinite loop
|
||||
var exitReason = null;
|
||||
let iterationCount = 0; // count iterations and prevent infinite loop
|
||||
let exitReason = null;
|
||||
|
||||
var token = null;
|
||||
var tokenIndex = -1;
|
||||
var longestMatch = 0;
|
||||
var matchStack = {
|
||||
let token = null;
|
||||
let tokenIndex = -1;
|
||||
let longestMatch = 0;
|
||||
let matchStack = {
|
||||
type: STUB,
|
||||
syntax: null,
|
||||
token: null,
|
||||
@@ -202,7 +199,7 @@ function internalMatch(tokens, state, syntaxes) {
|
||||
|
||||
while (exitReason === null && ++iterationCount < ITERATION_LIMIT) {
|
||||
// function mapList(list, fn) {
|
||||
// var result = [];
|
||||
// const result = [];
|
||||
// while (list) {
|
||||
// result.unshift(fn(list));
|
||||
// list = list.prev;
|
||||
@@ -314,8 +311,8 @@ function internalMatch(tokens, state, syntaxes) {
|
||||
};
|
||||
break;
|
||||
|
||||
case 'MatchOnceBuffer':
|
||||
var terms = state.syntax.terms;
|
||||
case 'MatchOnceBuffer': {
|
||||
const terms = state.syntax.terms;
|
||||
|
||||
if (state.index === terms.length) {
|
||||
// no matches at all or it's required all terms to be matched
|
||||
@@ -336,7 +333,7 @@ function internalMatch(tokens, state, syntaxes) {
|
||||
}
|
||||
|
||||
for (; state.index < terms.length; state.index++) {
|
||||
var matchFlag = 1 << state.index;
|
||||
const matchFlag = 1 << state.index;
|
||||
|
||||
if ((state.mask & matchFlag) === 0) {
|
||||
// IMPORTANT: else stack push must go first,
|
||||
@@ -354,6 +351,7 @@ function internalMatch(tokens, state, syntaxes) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'AddMatchOnce':
|
||||
state = {
|
||||
@@ -366,7 +364,7 @@ function internalMatch(tokens, state, syntaxes) {
|
||||
|
||||
case 'Enum':
|
||||
if (token !== null) {
|
||||
var name = token.value.toLowerCase();
|
||||
let name = token.value.toLowerCase();
|
||||
|
||||
// drop \0 and \9 hack from keyword name
|
||||
if (name.indexOf('\\') !== -1) {
|
||||
@@ -382,9 +380,9 @@ function internalMatch(tokens, state, syntaxes) {
|
||||
state = MISMATCH;
|
||||
break;
|
||||
|
||||
case 'Generic':
|
||||
var opts = syntaxStack !== null ? syntaxStack.opts : null;
|
||||
var lastTokenIndex = tokenIndex + Math.floor(state.fn(token, getNextToken, opts));
|
||||
case 'Generic': {
|
||||
const opts = syntaxStack !== null ? syntaxStack.opts : null;
|
||||
const lastTokenIndex = tokenIndex + Math.floor(state.fn(token, getNextToken, opts));
|
||||
|
||||
if (!isNaN(lastTokenIndex) && lastTokenIndex > tokenIndex) {
|
||||
while (tokenIndex < lastTokenIndex) {
|
||||
@@ -397,11 +395,12 @@ function internalMatch(tokens, state, syntaxes) {
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'Type':
|
||||
case 'Property':
|
||||
var syntaxDict = state.type === 'Type' ? 'types' : 'properties';
|
||||
var dictSyntax = hasOwnProperty.call(syntaxes, syntaxDict) ? syntaxes[syntaxDict][state.name] : null;
|
||||
case 'Property': {
|
||||
const syntaxDict = state.type === 'Type' ? 'types' : 'properties';
|
||||
const dictSyntax = hasOwnProperty.call(syntaxes, syntaxDict) ? syntaxes[syntaxDict][state.name] : null;
|
||||
|
||||
if (!dictSyntax || !dictSyntax.match) {
|
||||
throw new Error(
|
||||
@@ -414,7 +413,7 @@ function internalMatch(tokens, state, syntaxes) {
|
||||
|
||||
// stash a syntax for types with low priority
|
||||
if (syntaxStash !== false && token !== null && state.type === 'Type') {
|
||||
var lowPriorityMatching =
|
||||
const lowPriorityMatching =
|
||||
// https://drafts.csswg.org/css-values-4/#custom-idents
|
||||
// When parsing positionally-ambiguous keywords in a property value, a <custom-ident> production
|
||||
// can only claim the keyword if no other unfulfilled production can claim it.
|
||||
@@ -436,14 +435,15 @@ function internalMatch(tokens, state, syntaxes) {
|
||||
}
|
||||
|
||||
openSyntax();
|
||||
state = dictSyntax.match;
|
||||
state = dictSyntax.matchRef || dictSyntax.match;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'Keyword':
|
||||
var name = state.name;
|
||||
case 'Keyword': {
|
||||
const name = state.name;
|
||||
|
||||
if (token !== null) {
|
||||
var keywordName = token.value;
|
||||
let keywordName = token.value;
|
||||
|
||||
// drop \0 and \9 hack from keyword name
|
||||
if (keywordName.indexOf('\\') !== -1) {
|
||||
@@ -459,6 +459,7 @@ function internalMatch(tokens, state, syntaxes) {
|
||||
|
||||
state = MISMATCH;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'AtKeyword':
|
||||
case 'Function':
|
||||
@@ -496,9 +497,10 @@ function internalMatch(tokens, state, syntaxes) {
|
||||
break;
|
||||
|
||||
case 'String':
|
||||
var string = '';
|
||||
let string = '';
|
||||
let lastTokenIndex = tokenIndex;
|
||||
|
||||
for (var lastTokenIndex = tokenIndex; lastTokenIndex < tokens.length && string.length < state.value.length; lastTokenIndex++) {
|
||||
for (; lastTokenIndex < tokens.length && string.length < state.value.length; lastTokenIndex++) {
|
||||
string += tokens[lastTokenIndex].value;
|
||||
}
|
||||
|
||||
@@ -539,27 +541,24 @@ function internalMatch(tokens, state, syntaxes) {
|
||||
}
|
||||
|
||||
return {
|
||||
tokens: tokens,
|
||||
tokens,
|
||||
reason: exitReason,
|
||||
iterations: iterationCount,
|
||||
match: matchStack,
|
||||
longestMatch: longestMatch
|
||||
longestMatch
|
||||
};
|
||||
}
|
||||
|
||||
function matchAsList(tokens, matchGraph, syntaxes) {
|
||||
var matchResult = internalMatch(tokens, matchGraph, syntaxes || {});
|
||||
export function matchAsList(tokens, matchGraph, syntaxes) {
|
||||
const matchResult = internalMatch(tokens, matchGraph, syntaxes || {});
|
||||
|
||||
if (matchResult.match !== null) {
|
||||
var item = reverseList(matchResult.match).prev;
|
||||
let item = reverseList(matchResult.match).prev;
|
||||
|
||||
matchResult.match = [];
|
||||
|
||||
while (item !== null) {
|
||||
switch (item.type) {
|
||||
case STUB:
|
||||
break;
|
||||
|
||||
case OPEN_SYNTAX:
|
||||
case CLOSE_SYNTAX:
|
||||
matchResult.match.push({
|
||||
@@ -583,19 +582,19 @@ function matchAsList(tokens, matchGraph, syntaxes) {
|
||||
return matchResult;
|
||||
}
|
||||
|
||||
function matchAsTree(tokens, matchGraph, syntaxes) {
|
||||
var matchResult = internalMatch(tokens, matchGraph, syntaxes || {});
|
||||
export function matchAsTree(tokens, matchGraph, syntaxes) {
|
||||
const matchResult = internalMatch(tokens, matchGraph, syntaxes || {});
|
||||
|
||||
if (matchResult.match === null) {
|
||||
return matchResult;
|
||||
}
|
||||
|
||||
var item = matchResult.match;
|
||||
var host = matchResult.match = {
|
||||
let item = matchResult.match;
|
||||
let host = matchResult.match = {
|
||||
syntax: matchGraph.syntax || null,
|
||||
match: []
|
||||
};
|
||||
var hostStack = [host];
|
||||
const hostStack = [host];
|
||||
|
||||
// revert a list and start with 2nd item since 1st is a stub item
|
||||
item = reverseList(item).prev;
|
||||
@@ -629,11 +628,3 @@ function matchAsTree(tokens, matchGraph, syntaxes) {
|
||||
|
||||
return matchResult;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
matchAsList: matchAsList,
|
||||
matchAsTree: matchAsTree,
|
||||
getTotalIterationCount: function() {
|
||||
return totalIterationCount;
|
||||
}
|
||||
};
|
||||
|
||||
77
node_modules/css-tree/lib/lexer/prepare-tokens.js
generated
vendored
77
node_modules/css-tree/lib/lexer/prepare-tokens.js
generated
vendored
@@ -1,72 +1,49 @@
|
||||
var tokenize = require('../tokenizer');
|
||||
var TokenStream = require('../common/TokenStream');
|
||||
var tokenStream = new TokenStream();
|
||||
var astToTokens = {
|
||||
decorator: function(handlers) {
|
||||
var curNode = null;
|
||||
var prev = { len: 0, node: null };
|
||||
var nodes = [prev];
|
||||
var buffer = '';
|
||||
import { tokenize } from '../tokenizer/index.js';
|
||||
|
||||
const astToTokens = {
|
||||
decorator(handlers) {
|
||||
const tokens = [];
|
||||
let curNode = null;
|
||||
|
||||
return {
|
||||
children: handlers.children,
|
||||
node: function(node) {
|
||||
var tmp = curNode;
|
||||
...handlers,
|
||||
node(node) {
|
||||
const tmp = curNode;
|
||||
curNode = node;
|
||||
handlers.node.call(this, node);
|
||||
curNode = tmp;
|
||||
},
|
||||
chunk: function(chunk) {
|
||||
buffer += chunk;
|
||||
if (prev.node !== curNode) {
|
||||
nodes.push({
|
||||
len: chunk.length,
|
||||
node: curNode
|
||||
});
|
||||
} else {
|
||||
prev.len += chunk.length;
|
||||
}
|
||||
emit(value, type, auto) {
|
||||
tokens.push({
|
||||
type,
|
||||
value,
|
||||
node: auto ? null : curNode
|
||||
});
|
||||
},
|
||||
result: function() {
|
||||
return prepareTokens(buffer, nodes);
|
||||
result() {
|
||||
return tokens;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
function prepareTokens(str, nodes) {
|
||||
var tokens = [];
|
||||
var nodesOffset = 0;
|
||||
var nodesIndex = 0;
|
||||
var currentNode = nodes ? nodes[nodesIndex].node : null;
|
||||
|
||||
tokenize(str, tokenStream);
|
||||
|
||||
while (!tokenStream.eof) {
|
||||
if (nodes) {
|
||||
while (nodesIndex < nodes.length && nodesOffset + nodes[nodesIndex].len <= tokenStream.tokenStart) {
|
||||
nodesOffset += nodes[nodesIndex++].len;
|
||||
currentNode = nodes[nodesIndex].node;
|
||||
}
|
||||
}
|
||||
function stringToTokens(str) {
|
||||
const tokens = [];
|
||||
|
||||
tokenize(str, (type, start, end) =>
|
||||
tokens.push({
|
||||
type: tokenStream.tokenType,
|
||||
value: tokenStream.getTokenValue(),
|
||||
index: tokenStream.tokenIndex, // TODO: remove it, temporary solution
|
||||
balance: tokenStream.balance[tokenStream.tokenIndex], // TODO: remove it, temporary solution
|
||||
node: currentNode
|
||||
});
|
||||
tokenStream.next();
|
||||
// console.log({ ...tokens[tokens.length - 1], node: undefined });
|
||||
}
|
||||
type,
|
||||
value: str.slice(start, end),
|
||||
node: null
|
||||
})
|
||||
);
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
module.exports = function(value, syntax) {
|
||||
export default function(value, syntax) {
|
||||
if (typeof value === 'string') {
|
||||
return prepareTokens(value, null);
|
||||
return stringToTokens(value);
|
||||
}
|
||||
|
||||
return syntax.generate(value, astToTokens);
|
||||
|
||||
18
node_modules/css-tree/lib/lexer/search.js
generated
vendored
18
node_modules/css-tree/lib/lexer/search.js
generated
vendored
@@ -1,4 +1,4 @@
|
||||
var List = require('../common/List');
|
||||
import { List } from '../utils/List.js';
|
||||
|
||||
function getFirstMatchNode(matchNode) {
|
||||
if ('node' in matchNode) {
|
||||
@@ -16,17 +16,17 @@ function getLastMatchNode(matchNode) {
|
||||
return getLastMatchNode(matchNode.match[matchNode.match.length - 1]);
|
||||
}
|
||||
|
||||
function matchFragments(lexer, ast, match, type, name) {
|
||||
export function matchFragments(lexer, ast, match, type, name) {
|
||||
function findFragments(matchNode) {
|
||||
if (matchNode.syntax !== null &&
|
||||
matchNode.syntax.type === type &&
|
||||
matchNode.syntax.name === name) {
|
||||
var start = getFirstMatchNode(matchNode);
|
||||
var end = getLastMatchNode(matchNode);
|
||||
const start = getFirstMatchNode(matchNode);
|
||||
const end = getLastMatchNode(matchNode);
|
||||
|
||||
lexer.syntax.walk(ast, function(node, item, list) {
|
||||
if (node === start) {
|
||||
var nodes = new List();
|
||||
const nodes = new List();
|
||||
|
||||
do {
|
||||
nodes.appendData(item.data);
|
||||
@@ -40,7 +40,7 @@ function matchFragments(lexer, ast, match, type, name) {
|
||||
|
||||
fragments.push({
|
||||
parent: list,
|
||||
nodes: nodes
|
||||
nodes
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -51,7 +51,7 @@ function matchFragments(lexer, ast, match, type, name) {
|
||||
}
|
||||
}
|
||||
|
||||
var fragments = [];
|
||||
const fragments = [];
|
||||
|
||||
if (match.matched !== null) {
|
||||
findFragments(match.matched);
|
||||
@@ -59,7 +59,3 @@ function matchFragments(lexer, ast, match, type, name) {
|
||||
|
||||
return fragments;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
matchFragments: matchFragments
|
||||
};
|
||||
|
||||
94
node_modules/css-tree/lib/lexer/structure.js
generated
vendored
94
node_modules/css-tree/lib/lexer/structure.js
generated
vendored
@@ -1,5 +1,6 @@
|
||||
var List = require('../common/List');
|
||||
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
import { List } from '../utils/List.js';
|
||||
|
||||
const { hasOwnProperty } = Object.prototype;
|
||||
|
||||
function isValidNumber(value) {
|
||||
// Number.isInteger(value) && value >= 0
|
||||
@@ -26,8 +27,8 @@ function createNodeStructureChecker(type, fields) {
|
||||
return warn(node, 'Type of node should be an Object');
|
||||
}
|
||||
|
||||
for (var key in node) {
|
||||
var valid = true;
|
||||
for (let key in node) {
|
||||
let valid = true;
|
||||
|
||||
if (hasOwnProperty.call(node, key) === false) {
|
||||
continue;
|
||||
@@ -54,8 +55,10 @@ function createNodeStructureChecker(type, fields) {
|
||||
|
||||
valid = false;
|
||||
} else if (fields.hasOwnProperty(key)) {
|
||||
for (var i = 0, valid = false; !valid && i < fields[key].length; i++) {
|
||||
var fieldType = fields[key][i];
|
||||
valid = false;
|
||||
|
||||
for (let i = 0; !valid && i < fields[key].length; i++) {
|
||||
const fieldType = fields[key][i];
|
||||
|
||||
switch (fieldType) {
|
||||
case String:
|
||||
@@ -87,7 +90,7 @@ function createNodeStructureChecker(type, fields) {
|
||||
}
|
||||
}
|
||||
|
||||
for (var key in fields) {
|
||||
for (const key in fields) {
|
||||
if (hasOwnProperty.call(fields, key) &&
|
||||
hasOwnProperty.call(node, key) === false) {
|
||||
warn(node, 'Field `' + type + '.' + key + '` is missed');
|
||||
@@ -96,68 +99,71 @@ function createNodeStructureChecker(type, fields) {
|
||||
};
|
||||
}
|
||||
|
||||
function genTypesList(fieldTypes, path) {
|
||||
const docsTypes = [];
|
||||
|
||||
for (let i = 0; i < fieldTypes.length; i++) {
|
||||
const fieldType = fieldTypes[i];
|
||||
if (fieldType === String || fieldType === Boolean) {
|
||||
docsTypes.push(fieldType.name.toLowerCase());
|
||||
} else if (fieldType === null) {
|
||||
docsTypes.push('null');
|
||||
} else if (typeof fieldType === 'string') {
|
||||
docsTypes.push(fieldType);
|
||||
} else if (Array.isArray(fieldType)) {
|
||||
docsTypes.push('List<' + (genTypesList(fieldType, path) || 'any') + '>'); // TODO: use type enum
|
||||
} else {
|
||||
throw new Error('Wrong value `' + fieldType + '` in `' + path + '` structure definition');
|
||||
}
|
||||
}
|
||||
|
||||
return docsTypes.join(' | ');
|
||||
}
|
||||
|
||||
function processStructure(name, nodeType) {
|
||||
var structure = nodeType.structure;
|
||||
var fields = {
|
||||
const structure = nodeType.structure;
|
||||
const fields = {
|
||||
type: String,
|
||||
loc: true
|
||||
};
|
||||
var docs = {
|
||||
const docs = {
|
||||
type: '"' + name + '"'
|
||||
};
|
||||
|
||||
for (var key in structure) {
|
||||
for (const key in structure) {
|
||||
if (hasOwnProperty.call(structure, key) === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var docsTypes = [];
|
||||
var fieldTypes = fields[key] = Array.isArray(structure[key])
|
||||
const fieldTypes = fields[key] = Array.isArray(structure[key])
|
||||
? structure[key].slice()
|
||||
: [structure[key]];
|
||||
|
||||
for (var i = 0; i < fieldTypes.length; i++) {
|
||||
var fieldType = fieldTypes[i];
|
||||
if (fieldType === String || fieldType === Boolean) {
|
||||
docsTypes.push(fieldType.name);
|
||||
} else if (fieldType === null) {
|
||||
docsTypes.push('null');
|
||||
} else if (typeof fieldType === 'string') {
|
||||
docsTypes.push('<' + fieldType + '>');
|
||||
} else if (Array.isArray(fieldType)) {
|
||||
docsTypes.push('List'); // TODO: use type enum
|
||||
} else {
|
||||
throw new Error('Wrong value `' + fieldType + '` in `' + name + '.' + key + '` structure definition');
|
||||
}
|
||||
}
|
||||
|
||||
docs[key] = docsTypes.join(' | ');
|
||||
docs[key] = genTypesList(fieldTypes, name + '.' + key);
|
||||
}
|
||||
|
||||
return {
|
||||
docs: docs,
|
||||
docs,
|
||||
check: createNodeStructureChecker(name, fields)
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getStructureFromConfig: function(config) {
|
||||
var structure = {};
|
||||
export function getStructureFromConfig(config) {
|
||||
const structure = {};
|
||||
|
||||
if (config.node) {
|
||||
for (var name in config.node) {
|
||||
if (hasOwnProperty.call(config.node, name)) {
|
||||
var nodeType = config.node[name];
|
||||
if (config.node) {
|
||||
for (const name in config.node) {
|
||||
if (hasOwnProperty.call(config.node, name)) {
|
||||
const nodeType = config.node[name];
|
||||
|
||||
if (nodeType.structure) {
|
||||
structure[name] = processStructure(name, nodeType);
|
||||
} else {
|
||||
throw new Error('Missed `structure` field in `' + name + '` node type definition');
|
||||
}
|
||||
if (nodeType.structure) {
|
||||
structure[name] = processStructure(name, nodeType);
|
||||
} else {
|
||||
throw new Error('Missed `structure` field in `' + name + '` node type definition');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return structure;
|
||||
}
|
||||
|
||||
return structure;
|
||||
};
|
||||
|
||||
45
node_modules/css-tree/lib/lexer/trace.js
generated
vendored
45
node_modules/css-tree/lib/lexer/trace.js
generated
vendored
@@ -1,4 +1,4 @@
|
||||
function getTrace(node) {
|
||||
export function getTrace(node) {
|
||||
function shouldPutToTrace(syntax) {
|
||||
if (syntax === null) {
|
||||
return false;
|
||||
@@ -14,7 +14,7 @@ function getTrace(node) {
|
||||
function hasMatch(matchNode) {
|
||||
if (Array.isArray(matchNode.match)) {
|
||||
// use for-loop for better perfomance
|
||||
for (var i = 0; i < matchNode.match.length; i++) {
|
||||
for (let i = 0; i < matchNode.match.length; i++) {
|
||||
if (hasMatch(matchNode.match[i])) {
|
||||
if (shouldPutToTrace(matchNode.syntax)) {
|
||||
result.unshift(matchNode.syntax);
|
||||
@@ -34,7 +34,7 @@ function getTrace(node) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var result = null;
|
||||
let result = null;
|
||||
|
||||
if (this.matched !== null) {
|
||||
hasMatch(this.matched);
|
||||
@@ -43,8 +43,20 @@ function getTrace(node) {
|
||||
return result;
|
||||
}
|
||||
|
||||
export function isType(node, type) {
|
||||
return testNode(this, node, match => match.type === 'Type' && match.name === type);
|
||||
}
|
||||
|
||||
export function isProperty(node, property) {
|
||||
return testNode(this, node, match => match.type === 'Property' && match.name === property);
|
||||
}
|
||||
|
||||
export function isKeyword(node) {
|
||||
return testNode(this, node, match => match.type === 'Keyword');
|
||||
}
|
||||
|
||||
function testNode(match, node, fn) {
|
||||
var trace = getTrace.call(match, node);
|
||||
const trace = getTrace.call(match, node);
|
||||
|
||||
if (trace === null) {
|
||||
return false;
|
||||
@@ -52,28 +64,3 @@ function testNode(match, node, fn) {
|
||||
|
||||
return trace.some(fn);
|
||||
}
|
||||
|
||||
function isType(node, type) {
|
||||
return testNode(this, node, function(matchNode) {
|
||||
return matchNode.type === 'Type' && matchNode.name === type;
|
||||
});
|
||||
}
|
||||
|
||||
function isProperty(node, property) {
|
||||
return testNode(this, node, function(matchNode) {
|
||||
return matchNode.type === 'Property' && matchNode.name === property;
|
||||
});
|
||||
}
|
||||
|
||||
function isKeyword(node) {
|
||||
return testNode(this, node, function(matchNode) {
|
||||
return matchNode.type === 'Keyword';
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getTrace: getTrace,
|
||||
isType: isType,
|
||||
isProperty: isProperty,
|
||||
isKeyword: isKeyword
|
||||
};
|
||||
|
||||
27
node_modules/css-tree/lib/lexer/units.js
generated
vendored
Normal file
27
node_modules/css-tree/lib/lexer/units.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
export const length = [
|
||||
// absolute length units https://www.w3.org/TR/css-values-3/#lengths
|
||||
'cm', 'mm', 'q', 'in', 'pt', 'pc', 'px',
|
||||
// font-relative length units https://drafts.csswg.org/css-values-4/#font-relative-lengths
|
||||
'em', 'rem',
|
||||
'ex', 'rex',
|
||||
'cap', 'rcap',
|
||||
'ch', 'rch',
|
||||
'ic', 'ric',
|
||||
'lh', 'rlh',
|
||||
// viewport-percentage lengths https://drafts.csswg.org/css-values-4/#viewport-relative-lengths
|
||||
'vw', 'svw', 'lvw', 'dvw',
|
||||
'vh', 'svh', 'lvh', 'dvh',
|
||||
'vi', 'svi', 'lvi', 'dvi',
|
||||
'vb', 'svb', 'lvb', 'dvb',
|
||||
'vmin', 'svmin', 'lvmin', 'dvmin',
|
||||
'vmax', 'svmax', 'lvmax', 'dvmax',
|
||||
// container relative lengths https://drafts.csswg.org/css-contain-3/#container-lengths
|
||||
'cqw', 'cqh', 'cqi', 'cqb', 'cqmin', 'cqmax'
|
||||
];
|
||||
export const angle = ['deg', 'grad', 'rad', 'turn']; // https://www.w3.org/TR/css-values-3/#angles
|
||||
export const time = ['s', 'ms']; // https://www.w3.org/TR/css-values-3/#time
|
||||
export const frequency = ['hz', 'khz']; // https://www.w3.org/TR/css-values-3/#frequency
|
||||
export const resolution = ['dpi', 'dpcm', 'dppx', 'x']; // https://www.w3.org/TR/css-values-3/#resolution
|
||||
export const flex = ['fr']; // https://drafts.csswg.org/css-grid/#fr-unit
|
||||
export const decibel = ['db']; // https://www.w3.org/TR/css3-speech/#mixing-props-voice-volume
|
||||
export const semitones = ['st']; // https://www.w3.org/TR/css3-speech/#voice-props-voice-pitch
|
||||
Reference in New Issue
Block a user