first commit

This commit is contained in:
s.golasch
2023-08-01 13:49:46 +02:00
commit 1fc239fd54
20238 changed files with 3112246 additions and 0 deletions

347
build/node_modules/css-tree/lib/lexer/Lexer.js generated vendored Normal file
View File

@@ -0,0 +1,347 @@
'use strict';
var SyntaxReferenceError = require('./error').SyntaxReferenceError;
var MatchError = require('./error').MatchError;
var names = require('../utils/names');
var generic = require('./generic');
var parse = require('./grammar/parse');
var translate = require('./grammar/translate');
var walk = require('./grammar/walk');
var match = require('./match');
var trace = require('./trace');
var search = require('./search');
var getStructureFromConfig = require('./structure').getStructureFromConfig;
var cssWideKeywords = parse('inherit | initial | unset');
var cssWideKeywordsWithExpression = parse('inherit | initial | unset | <expression>');
function dumpMapSyntax(map, syntaxAsAst) {
var result = {};
for (var name in map) {
if (map[name].syntax) {
result[name] = syntaxAsAst ? map[name].syntax : translate(map[name].syntax);
}
}
return result;
}
function unwrapNode(item) {
return item && item.data;
}
function valueHasVar(value) {
var hasVar = false;
this.syntax.walk(value, function(node) {
if (node.type === 'Function' && node.name.toLowerCase() === 'var') {
hasVar = true;
}
});
return hasVar;
}
// check node is \0 or \9 hack
function isHack(node) {
return node.type === 'Identifier' && /^\\[09]/.test(node.name);
}
// white spaces, comments and some hacks can to be ignored at the end of value
function isNextMayToBeIgnored(cursor) {
while (cursor !== null) {
if (cursor.data.type !== 'WhiteSpace' &&
cursor.data.type !== 'Comment' &&
!isHack(cursor.data)) {
return false;
}
cursor = cursor.next;
}
return true;
}
function buildMatchResult(match, error) {
return {
matched: match,
error: error,
getTrace: trace.getTrace,
isType: trace.isType,
isProperty: trace.isProperty,
isKeyword: trace.isKeyword
};
}
function matchSyntax(lexer, syntax, value) {
var result;
if (!value || value.type !== 'Value') {
return buildMatchResult(null, new Error('Not a Value node'));
}
if (valueHasVar.call(lexer, value)) {
return buildMatchResult(null, new Error('Matching for a value with var() is not supported'));
}
result = match(lexer, lexer.valueCommonSyntax, value.children.head);
if (!result.match) {
result = syntax.match(value.children.head);
if (!result.match) {
return buildMatchResult(null, new MatchError('Mismatch', lexer, syntax.syntax, value, result.badNode || unwrapNode(result.next) || value));
}
}
// enhance top-level match wrapper
if (result.match.type === 'ASTNode') {
result.match = {
syntax: {
type: syntax.type,
name: syntax.name
},
match: [result.match]
};
} else if (result.match.syntax.type === 'Group') {
result.match.syntax = {
type: syntax.type,
name: syntax.name
};
}
if (result.next && !isNextMayToBeIgnored(result.next)) {
return buildMatchResult(null, new MatchError('Uncomplete match', lexer, syntax.syntax, value, result.badNode || unwrapNode(result.next) || value));
}
return buildMatchResult(result.match, null);
}
var Lexer = function(config, syntax, structure) {
this.valueCommonSyntax = cssWideKeywords;
this.syntax = syntax;
this.generic = false;
this.properties = {};
this.types = {};
this.structure = structure || getStructureFromConfig(config);
if (config) {
if (config.generic) {
this.generic = true;
for (var name in generic) {
this.addType_(name, generic[name]);
}
}
if (config.types) {
for (var name in config.types) {
this.addType_(name, config.types[name]);
}
}
if (config.properties) {
for (var name in config.properties) {
this.addProperty_(name, config.properties[name]);
}
}
}
};
Lexer.prototype = {
structure: {},
checkStructure: function(ast) {
function collectWarning(node, message) {
warns.push({
node: node,
message: message
});
}
var structure = this.structure;
var warns = [];
this.syntax.walk(ast, function(node) {
if (structure.hasOwnProperty(node.type)) {
structure[node.type].check(node, collectWarning);
} else {
collectWarning(node, 'Unknown node type `' + node.type + '`');
}
});
return warns.length ? warns : false;
},
createDescriptor: function(syntax, type, name) {
var self = this;
var descriptor = {
type: type,
name: name,
syntax: null,
match: null
};
if (typeof syntax === 'function') {
// convert syntax to pseudo syntax node
// NOTE: that's not a part of match result tree
syntax = {
type: 'ASTNode',
match: syntax
};
descriptor.match = function(item) {
return match(self, syntax, item);
};
} else {
if (typeof syntax === 'string') {
// lazy parsing on first access
Object.defineProperty(descriptor, 'syntax', {
get: function() {
Object.defineProperty(descriptor, 'syntax', {
value: parse(syntax)
});
return descriptor.syntax;
}
});
} else {
descriptor.syntax = syntax;
}
descriptor.match = function(item) {
return match(self, descriptor.syntax, item);
};
}
return descriptor;
},
addProperty_: function(name, syntax) {
this.properties[name] = this.createDescriptor(syntax, 'Property', name);
},
addType_: function(name, syntax) {
this.types[name] = this.createDescriptor(syntax, 'Type', name);
if (syntax === generic.expression) {
this.valueCommonSyntax = cssWideKeywordsWithExpression;
}
},
matchDeclaration: function(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 property = names.property(propertyName);
// don't match syntax for a custom property
if (property.custom) {
return buildMatchResult(null, new Error('Lexer matching doesn\'t applicable for custom properties'));
}
var propertySyntax = property.vendor
? this.getProperty(property.vendor + property.name) || this.getProperty(property.name)
: this.getProperty(property.name);
if (!propertySyntax) {
return buildMatchResult(null, new SyntaxReferenceError('Unknown property', propertyName));
}
return matchSyntax(this, propertySyntax, value);
},
matchType: function(typeName, value) {
var typeSyntax = this.getType(typeName);
if (!typeSyntax) {
return buildMatchResult(null, new SyntaxReferenceError('Unknown type', typeName));
}
return matchSyntax(this, typeSyntax, value);
},
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 = [];
this.syntax.walkDeclarations(ast, function(declaration) {
result.push.apply(result, this.findDeclarationValueFragments(declaration, type, name));
}.bind(this));
return result;
},
getProperty: function(name) {
return this.properties.hasOwnProperty(name) ? this.properties[name] : null;
},
getType: function(name) {
return this.types.hasOwnProperty(name) ? this.types[name] : null;
},
validate: function() {
function validate(syntax, name, broken, descriptor) {
if (broken.hasOwnProperty(name)) {
return broken[name];
}
broken[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;
if (!map.hasOwnProperty(node.name) || validate(syntax, node.name, brokenMap, map[node.name])) {
broken[name] = true;
}
}, this);
}
}
var brokenTypes = {};
var brokenProperties = {};
for (var key in this.types) {
validate(this, key, brokenTypes, this.types[key]);
}
for (var 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];
});
if (brokenTypes.length || brokenProperties.length) {
return {
types: brokenTypes,
properties: brokenProperties
};
}
return null;
},
dump: function(syntaxAsAst) {
return {
generic: this.generic,
types: dumpMapSyntax(this.types, syntaxAsAst),
properties: dumpMapSyntax(this.properties, syntaxAsAst)
};
},
toString: function() {
return JSON.stringify(this.dump());
}
};
module.exports = Lexer;

62
build/node_modules/css-tree/lib/lexer/error.js generated vendored Normal file
View File

@@ -0,0 +1,62 @@
'use strict';
var createCustomError = require('../utils/createCustomError');
var translateGrammar = require('./grammar/translate');
function getLocation(node, point) {
var loc = node && node.loc && node.loc[point];
return loc
? { offset: loc.offset,
line: loc.line,
column: loc.column }
: null;
}
var SyntaxReferenceError = function(type, referenceName) {
var error = createCustomError('SyntaxReferenceError', type + ' `' + referenceName + '`');
error.reference = referenceName;
return error;
};
var MatchError = function(message, lexer, syntax, value, badNode) {
var error = createCustomError('SyntaxMatchError', message);
var errorOffset = -1;
var start = getLocation(badNode, 'start');
var end = getLocation(badNode, 'end');
var css = lexer.syntax.translateMarkup(value, function(node, buffer) {
if (node === badNode) {
errorOffset = buffer.length;
}
});
if (errorOffset === -1) {
errorOffset = css.length;
}
error.rawMessage = message;
error.syntax = syntax ? translateGrammar(syntax) : '<generic>';
error.css = css;
error.mismatchOffset = errorOffset;
error.loc = {
source: badNode && badNode.loc && badNode.loc.source || '<unknown>',
start: start,
end: end
};
error.line = start ? start.line : undefined;
error.column = start ? start.column : undefined;
error.offset = start ? start.offset : undefined;
error.message = message + '\n' +
' syntax: ' + error.syntax + '\n' +
' value: ' + (error.css || '<empty string>') + '\n' +
' --------' + new Array(error.mismatchOffset + 1).join('-') + '^';
return error;
};
module.exports = {
SyntaxReferenceError: SyntaxReferenceError,
MatchError: MatchError
};

221
build/node_modules/css-tree/lib/lexer/generic.js generated vendored Normal file
View File

@@ -0,0 +1,221 @@
'use strict';
var names = require('../utils/names.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
};
// can be used wherever <length>, <frequency>, <angle>, <time>, <percentage>, <number>, or <integer> values are allowed
// https://drafts.csswg.org/css-values/#calc-notation
function isCalc(node) {
if (node.data.type !== 'Function') {
return false;
}
var keyword = names.keyword(node.data.name);
if (keyword.name !== 'calc') {
return false;
}
// there were some prefixed implementations
return keyword.vendor === '' ||
keyword.vendor === '-moz-' ||
keyword.vendor === '-webkit-';
}
function astNode(type) {
return function(node) {
return node.data.type === type;
};
}
function dimension(type) {
return function(node) {
return isCalc(node) ||
(node.data.type === 'Dimension' && type.hasOwnProperty(node.data.unit.toLowerCase()));
};
}
function zeroUnitlessDimension(type) {
return function(node) {
return isCalc(node) ||
(node.data.type === 'Dimension' && type.hasOwnProperty(node.data.unit.toLowerCase())) ||
(node.data.type === 'Number' && Number(node.data.value) === 0);
};
}
function attr(node) {
return node.data.type === 'Function' && node.data.name.toLowerCase() === 'attr';
}
function number(node) {
return isCalc(node) || node.data.type === 'Number';
}
function numberZeroOne(node) {
if (isCalc(node) || node.data.type === 'Number') {
var value = Number(node.data.value);
return value >= 0 && value <= 1;
}
return false;
}
function numberOneOrGreater(node) {
if (isCalc(node) || node.data.type === 'Number') {
return Number(node.data.value) >= 1;
}
return false;
}
// TODO: fail on 10e-2
function integer(node) {
return isCalc(node) ||
(node.data.type === 'Number' && node.data.value.indexOf('.') === -1);
}
// TODO: fail on 10e-2
function positiveInteger(node) {
return isCalc(node) ||
(node.data.type === 'Number' && node.data.value.indexOf('.') === -1 && node.data.value.charAt(0) !== '-');
}
function percentage(node) {
return isCalc(node) ||
node.data.type === 'Percentage';
}
function hexColor(node) {
if (node.data.type !== 'HexColor') {
return false;
}
var hex = node.data.value;
return /^[0-9a-fA-F]{3,8}$/.test(hex) &&
(hex.length === 3 || hex.length === 4 || hex.length === 6 || hex.length === 8);
}
function expression(node) {
return node.data.type === 'Function' && node.data.name.toLowerCase() === 'expression';
}
// https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident
// https://drafts.csswg.org/css-values-4/#identifier-value
function customIdent(node) {
if (node.data.type !== 'Identifier') {
return false;
}
var name = node.data.name.toLowerCase();
// § 3.2. Author-defined Identifiers: the <custom-ident> type
// The CSS-wide keywords are not valid <custom-ident>s
if (name === 'unset' || name === 'initial' || name === 'inherit') {
return false;
}
// The default keyword is reserved and is also not a valid <custom-ident>
if (name === 'default') {
return false;
}
// TODO: ignore property specific keywords (as described https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident)
return true;
}
module.exports = {
'angle': zeroUnitlessDimension(ANGLE),
'attr()': attr,
'custom-ident': customIdent,
'decibel': dimension(DECIBEL),
'dimension': astNode('Dimension'),
'frequency': dimension(FREQUENCY),
'flex': dimension(FLEX),
'hex-color': hexColor,
'id-selector': astNode('IdSelector'), // element( <id-selector> )
'ident': astNode('Identifier'),
'integer': integer,
'length': zeroUnitlessDimension(LENGTH),
'number': number,
'number-zero-one': numberZeroOne,
'number-one-or-greater': numberOneOrGreater,
'percentage': percentage,
'positive-integer': positiveInteger,
'resolution': dimension(RESOLUTION),
'semitones': dimension(SEMITONES),
'string': astNode('String'),
'time': dimension(TIME),
'unicode-range': astNode('UnicodeRange'),
'url': astNode('Url'),
// old IE stuff
'progid': astNode('Raw'),
'expression': expression
};

20
build/node_modules/css-tree/lib/lexer/grammar/error.js generated vendored Normal file
View File

@@ -0,0 +1,20 @@
'use strict';
var createCustomError = require('../../utils/createCustomError');
var SyntaxParseError = function(message, syntaxStr, offset) {
var error = createCustomError('SyntaxParseError', message);
error.rawMessage = message;
error.syntax = syntaxStr;
error.offset = offset;
error.message = error.rawMessage + '\n' +
' ' + error.syntax + '\n' +
'--' + new Array((error.offset || error.syntax.length) + 1).join('-') + '^';
return error;
};
module.exports = {
SyntaxParseError: SyntaxParseError
};

View File

@@ -0,0 +1,6 @@
module.exports = {
SyntaxParseError: require('./error').SyntaxParseError,
parse: require('./parse'),
translate: require('./translate'),
walk: require('./walk')
};

503
build/node_modules/css-tree/lib/lexer/grammar/parse.js generated vendored Normal file
View File

@@ -0,0 +1,503 @@
'use strict';
var SyntaxParseError = require('./error').SyntaxParseError;
var TAB = 9;
var N = 10;
var F = 12;
var R = 13;
var SPACE = 32;
var EXCLAMATIONMARK = 33; // !
var NUMBERSIGN = 35; // #
var PERCENTSIGN = 37; // %
var AMPERSAND = 38; // &
var APOSTROPHE = 39; // '
var LEFTPARENTHESIS = 40; // (
var RIGHTPARENTHESIS = 41; // )
var ASTERISK = 42; // *
var PLUSSIGN = 43; // +
var COMMA = 44; // ,
var SOLIDUS = 47; // /
var LESSTHANSIGN = 60; // <
var GREATERTHANSIGN = 62; // >
var QUESTIONMARK = 63; // ?
var LEFTSQUAREBRACKET = 91; // [
var RIGHTSQUAREBRACKET = 93; // ]
var LEFTCURLYBRACKET = 123; // {
var VERTICALLINE = 124; // |
var RIGHTCURLYBRACKET = 125; // }
var COMBINATOR_PRECEDENCE = {
' ': 1,
'&&': 2,
'||': 3,
'|': 4
};
var MULTIPLIER_DEFAULT = {
comma: false,
min: 1,
max: 1
};
var MULTIPLIER_ZERO_OR_MORE = {
comma: false,
min: 0,
max: 0
};
var MULTIPLIER_ONE_OR_MORE = {
comma: false,
min: 1,
max: 0
};
var MULTIPLIER_ONE_OR_MORE_COMMA_SEPARATED = {
comma: true,
min: 1,
max: 0
};
var MULTIPLIER_ZERO_OR_ONE = {
comma: false,
min: 0,
max: 1
};
var NAME_CHAR = (function() {
var array = typeof Uint32Array === 'function' ? new Uint32Array(128) : new Array(128);
for (var i = 0; i < 128; i++) {
array[i] = /[a-zA-Z0-9\-]/.test(String.fromCharCode(i)) ? 1 : 0;
}
return array;
})();
var Tokenizer = function(str) {
this.str = str;
this.pos = 0;
};
Tokenizer.prototype = {
charCode: function() {
return this.pos < this.str.length ? this.str.charCodeAt(this.pos) : 0;
},
nextCharCode: function() {
return this.pos + 1 < this.str.length ? this.str.charCodeAt(this.pos + 1) : 0;
},
substringToPos: function(end) {
return this.str.substring(this.pos, this.pos = end);
},
eat: function(code) {
if (this.charCode() !== code) {
error(this, this.pos, 'Expect `' + String.fromCharCode(code) + '`');
}
this.pos++;
}
};
function scanSpaces(tokenizer) {
var end = tokenizer.pos + 1;
for (; end < tokenizer.str.length; end++) {
var code = tokenizer.str.charCodeAt(end);
if (code !== R && code !== N && code !== F && code !== SPACE && code !== TAB) {
break;
}
}
return tokenizer.substringToPos(end);
}
function scanWord(tokenizer) {
var end = tokenizer.pos;
for (; end < tokenizer.str.length; end++) {
var code = tokenizer.str.charCodeAt(end);
if (code >= 128 || NAME_CHAR[code] === 0) {
break;
}
}
if (tokenizer.pos === end) {
error(tokenizer, tokenizer.pos, 'Expect a keyword');
}
return tokenizer.substringToPos(end);
}
function scanNumber(tokenizer) {
var end = tokenizer.pos;
for (; end < tokenizer.str.length; end++) {
var code = tokenizer.str.charCodeAt(end);
if (code < 48 || code > 57) {
break;
}
}
if (tokenizer.pos === end) {
error(tokenizer, tokenizer.pos, 'Expect a number');
}
return tokenizer.substringToPos(end);
}
function scanString(tokenizer) {
var end = tokenizer.str.indexOf('\'', tokenizer.pos + 1);
if (end === -1) {
error(tokenizer, tokenizer.str.length, 'Expect a quote');
}
return tokenizer.substringToPos(end + 1);
}
function readMultiplierRange(tokenizer, comma) {
var min = null;
var max = null;
tokenizer.eat(LEFTCURLYBRACKET);
min = scanNumber(tokenizer);
if (tokenizer.charCode() === COMMA) {
tokenizer.pos++;
if (tokenizer.charCode() !== RIGHTCURLYBRACKET) {
max = scanNumber(tokenizer);
}
} else {
max = min;
}
tokenizer.eat(RIGHTCURLYBRACKET);
return {
comma: comma,
min: Number(min),
max: max ? Number(max) : 0
};
}
function readMultiplier(tokenizer) {
switch (tokenizer.charCode()) {
case ASTERISK:
tokenizer.pos++;
return MULTIPLIER_ZERO_OR_MORE;
case PLUSSIGN:
tokenizer.pos++;
return MULTIPLIER_ONE_OR_MORE;
case QUESTIONMARK:
tokenizer.pos++;
return MULTIPLIER_ZERO_OR_ONE;
case NUMBERSIGN:
tokenizer.pos++;
if (tokenizer.charCode() !== LEFTCURLYBRACKET) {
return MULTIPLIER_ONE_OR_MORE_COMMA_SEPARATED;
}
return readMultiplierRange(tokenizer, true);
case LEFTCURLYBRACKET:
return readMultiplierRange(tokenizer, false);
}
return MULTIPLIER_DEFAULT;
}
function maybeMultiplied(tokenizer, node) {
var multiplier = readMultiplier(tokenizer);
if (multiplier !== MULTIPLIER_DEFAULT) {
return {
type: 'Group',
terms: [node],
combinator: '|', // `|` combinator is simplest in implementation (and therefore faster)
disallowEmpty: false,
multiplier: multiplier,
explicit: false
};
}
return node;
}
function readProperty(tokenizer) {
var name;
tokenizer.eat(LESSTHANSIGN);
tokenizer.eat(APOSTROPHE);
name = scanWord(tokenizer);
tokenizer.eat(APOSTROPHE);
tokenizer.eat(GREATERTHANSIGN);
return maybeMultiplied(tokenizer, {
type: 'Property',
name: name
});
}
function readType(tokenizer) {
var name;
tokenizer.eat(LESSTHANSIGN);
name = scanWord(tokenizer);
if (tokenizer.charCode() === LEFTPARENTHESIS &&
tokenizer.nextCharCode() === RIGHTPARENTHESIS) {
tokenizer.pos += 2;
name += '()';
}
tokenizer.eat(GREATERTHANSIGN);
return maybeMultiplied(tokenizer, {
type: 'Type',
name: name
});
}
function readKeywordOrFunction(tokenizer) {
var children = null;
var name;
name = scanWord(tokenizer);
if (tokenizer.charCode() === LEFTPARENTHESIS) {
tokenizer.pos++;
children = readImplicitGroup(tokenizer);
tokenizer.eat(RIGHTPARENTHESIS);
return maybeMultiplied(tokenizer, {
type: 'Function',
name: name,
children: children
});
}
return maybeMultiplied(tokenizer, {
type: 'Keyword',
name: name
});
}
function regroupTerms(terms, combinators) {
function createGroup(terms, combinator) {
return {
type: 'Group',
terms: terms,
combinator: combinator,
disallowEmpty: false,
multiplier: MULTIPLIER_DEFAULT,
explicit: false
};
}
combinators = Object.keys(combinators).sort(function(a, b) {
return COMBINATOR_PRECEDENCE[a] - COMBINATOR_PRECEDENCE[b];
});
while (combinators.length > 0) {
var combinator = combinators.shift();
for (var i = 0, subgroupStart = 0; i < terms.length; i++) {
var term = terms[i];
if (term.type === 'Combinator') {
if (term.value === combinator) {
if (subgroupStart === -1) {
subgroupStart = i - 1;
}
terms.splice(i, 1);
i--;
} else {
if (subgroupStart !== -1 && i - subgroupStart > 1) {
terms.splice(
subgroupStart,
i - subgroupStart,
createGroup(terms.slice(subgroupStart, i), combinator)
);
i = subgroupStart + 1;
}
subgroupStart = -1;
}
}
}
if (subgroupStart !== -1 && combinators.length) {
terms.splice(
subgroupStart,
i - subgroupStart,
createGroup(terms.slice(subgroupStart, i), combinator)
);
}
}
return combinator;
}
function readImplicitGroup(tokenizer) {
var terms = [];
var combinators = {};
var token;
var prevToken = null;
var prevTokenPos = tokenizer.pos;
while (token = peek(tokenizer)) {
if (token.type !== 'Spaces') {
if (token.type === 'Combinator') {
// check for combinator in group beginning and double combinator sequence
if (prevToken === null || prevToken.type === 'Combinator') {
error(tokenizer, prevTokenPos, 'Unexpected combinator');
}
combinators[token.value] = true;
} else if (prevToken !== null && prevToken.type !== 'Combinator') {
combinators[' '] = true; // a b
terms.push({
type: 'Combinator',
value: ' '
});
}
terms.push(token);
prevToken = token;
prevTokenPos = tokenizer.pos;
}
}
// check for combinator in group ending
if (prevToken !== null && prevToken.type === 'Combinator') {
error(tokenizer, tokenizer.pos - prevTokenPos, 'Unexpected combinator');
}
return {
type: 'Group',
terms: terms,
combinator: regroupTerms(terms, combinators) || ' ',
disallowEmpty: false,
multiplier: MULTIPLIER_DEFAULT,
explicit: false
};
}
function readGroup(tokenizer) {
var result;
tokenizer.eat(LEFTSQUAREBRACKET);
result = readImplicitGroup(tokenizer);
tokenizer.eat(RIGHTSQUAREBRACKET);
result.explicit = true;
result.multiplier = readMultiplier(tokenizer);
if (tokenizer.charCode() === EXCLAMATIONMARK) {
tokenizer.pos++;
result.disallowEmpty = true;
}
return result;
}
function peek(tokenizer) {
var code = tokenizer.charCode();
if (code < 128 && NAME_CHAR[code] === 1) {
return readKeywordOrFunction(tokenizer);
}
switch (code) {
case LEFTSQUAREBRACKET:
return readGroup(tokenizer);
case LESSTHANSIGN:
if (tokenizer.nextCharCode() === APOSTROPHE) {
return readProperty(tokenizer);
} else {
return readType(tokenizer);
}
case VERTICALLINE:
return {
type: 'Combinator',
value: tokenizer.substringToPos(tokenizer.nextCharCode() === VERTICALLINE ? tokenizer.pos + 2 : tokenizer.pos + 1)
};
case AMPERSAND:
tokenizer.pos++;
tokenizer.eat(AMPERSAND);
return {
type: 'Combinator',
value: '&&'
};
case COMMA:
tokenizer.pos++;
return {
type: 'Comma',
value: ','
};
case SOLIDUS:
tokenizer.pos++;
return {
type: 'Slash',
value: '/'
};
case PERCENTSIGN: // looks like exception, needs for attr()'s <type-or-unit>
tokenizer.pos++;
return {
type: 'Percent',
value: '%'
};
case LEFTPARENTHESIS:
tokenizer.pos++;
var children = readImplicitGroup(tokenizer);
tokenizer.eat(RIGHTPARENTHESIS);
return {
type: 'Parentheses',
children: children
};
case APOSTROPHE:
return {
type: 'String',
value: scanString(tokenizer)
};
case SPACE:
case TAB:
case N:
case R:
case F:
return {
type: 'Spaces',
value: scanSpaces(tokenizer)
};
}
}
function error(tokenizer, pos, msg) {
throw new SyntaxParseError(msg || 'Unexpected input', tokenizer.str, pos);
}
function parse(str) {
var tokenizer = new Tokenizer(str);
var result = readImplicitGroup(tokenizer);
if (tokenizer.pos !== str.length) {
error(tokenizer, tokenizer.pos);
}
// reduce redundant groups with single group term
if (result.terms.length === 1 && result.terms[0].type === 'Group') {
result = result.terms[0];
}
return result;
}
// warm up parse to elimitate code branches that never execute
// fix soft deoptimizations (insufficient type feedback)
parse('[a&&<b>#|<\'c\'>*||e(){2,} f{2} /,(% g#{1,2})]!');
module.exports = parse;

View File

@@ -0,0 +1,106 @@
'use strict';
function isNodeType(node, type) {
return node && node.type === type;
}
function serializeMultiplier(multiplier) {
if (multiplier.min === 0 && multiplier.max === 0) {
return '*';
}
if (multiplier.min === 0 && multiplier.max === 1) {
return '?';
}
if (multiplier.min === 1 && multiplier.max === 0) {
return multiplier.comma ? '#' : '+';
}
if (multiplier.min === 1 && multiplier.max === 1) {
return '';
}
return (
(multiplier.comma ? '#' : '') +
'{' + multiplier.min + (multiplier.min !== multiplier.max ? ',' + (multiplier.max !== 0 ? multiplier.max : '') : '') + '}'
);
}
function translateSequence(node, forceBraces, decorate) {
var result = '';
if (node.explicit || forceBraces) {
result += '[' + (!isNodeType(node.terms[0], 'Comma') ? ' ' : '');
}
result += node.terms.map(function(term) {
return translate(term, forceBraces, decorate);
}).join(node.combinator === ' ' ? ' ' : ' ' + node.combinator + ' ');
if (node.explicit || forceBraces) {
result += ' ]';
}
return result;
}
function translateParentheses(group, forceBraces, decorate) {
if (!group.terms.length) {
return '()';
}
return '( ' + translateSequence(group, forceBraces, decorate) + ' )';
}
function translate(node, forceBraces, decorate) {
var result;
switch (node.type) {
case 'Group':
result =
translateSequence(node, forceBraces, decorate) +
(node.disallowEmpty ? '!' : '') +
serializeMultiplier(node.multiplier);
break;
case 'Keyword':
result = node.name;
break;
case 'Function':
result = node.name + translateParentheses(node.children, forceBraces, decorate);
break;
case 'Parentheses': // replace for seq('(' seq(...node.children) ')')
result = translateParentheses(node.children, forceBraces, decorate);
break;
case 'Type':
result = '<' + node.name + '>';
break;
case 'Property':
result = '<\'' + node.name + '\'>';
break;
case 'Combinator': // remove?
case 'Slash': // replace for String? '/'
case 'Percent': // replace for String? '%'
case 'String':
case 'Comma':
result = node.value;
break;
default:
throw new Error('Unknown node type `' + node.type + '`');
}
if (typeof decorate === 'function') {
result = decorate(result, node);
}
return result;
}
module.exports = translate;

31
build/node_modules/css-tree/lib/lexer/grammar/walk.js generated vendored Normal file
View File

@@ -0,0 +1,31 @@
'use strict';
module.exports = function walk(node, fn, context) {
switch (node.type) {
case 'Group':
node.terms.forEach(function(term) {
walk(term, fn, context);
});
break;
case 'Function':
case 'Parentheses':
walk(node.children, fn, context);
break;
case 'Keyword':
case 'Type':
case 'Property':
case 'Combinator':
case 'Comma':
case 'Slash':
case 'String':
case 'Percent':
break;
default:
throw new Error('Unknown type: ' + node.type);
}
fn.call(context, node);
};

6
build/node_modules/css-tree/lib/lexer/index.js generated vendored Normal file
View File

@@ -0,0 +1,6 @@
'use strict';
module.exports = {
Lexer: require('./Lexer'),
grammar: require('./grammar')
};

515
build/node_modules/css-tree/lib/lexer/match.js generated vendored Normal file
View File

@@ -0,0 +1,515 @@
'use strict';
var names = require('../utils/names');
var MULTIPLIER_DEFAULT = {
comma: false,
min: 1,
max: 1
};
function skipSpaces(node) {
while (node !== null && (node.data.type === 'WhiteSpace' || node.data.type === 'Comment')) {
node = node.next;
}
return node;
}
function putResult(buffer, match) {
var type = match.type || match.syntax.type;
// ignore groups
if (type === 'Group') {
buffer.push.apply(buffer, match.match);
} else {
buffer.push(match);
}
}
function matchToJSON() {
return {
type: this.syntax.type,
name: this.syntax.name,
match: this.match,
node: this.node
};
}
function buildMatchNode(badNode, lastNode, next, match) {
if (badNode) {
return {
badNode: badNode,
lastNode: null,
next: null,
match: null
};
}
return {
badNode: null,
lastNode: lastNode,
next: next,
match: match
};
}
function matchGroup(lexer, syntaxNode, node) {
var result = [];
var buffer;
var multiplier = syntaxNode.multiplier || MULTIPLIER_DEFAULT;
var min = multiplier.min;
var max = multiplier.max === 0 ? Infinity : multiplier.max;
var lastCommaTermCount;
var lastComma;
var matchCount = 0;
var lastNode = null;
var badNode = null;
mismatch:
while (matchCount < max) {
node = skipSpaces(node);
buffer = [];
switch (syntaxNode.combinator) {
case '|':
for (var i = 0; i < syntaxNode.terms.length; i++) {
var term = syntaxNode.terms[i];
var res = matchSyntax(lexer, term, node);
if (res.match) {
putResult(buffer, res.match);
node = res.next;
break; // continue matching
} else if (res.badNode) {
badNode = res.badNode;
break mismatch;
} else if (res.lastNode) {
lastNode = res.lastNode;
}
}
if (buffer.length === 0) {
break mismatch; // nothing found -> stop matching
}
break;
case ' ':
var beforeMatchNode = node;
var lastMatchedTerm = null;
var hasTailMatch = false;
var commaMissed = false;
for (var i = 0; i < syntaxNode.terms.length; i++) {
var term = syntaxNode.terms[i];
var res = matchSyntax(lexer, term, node);
if (res.match) {
if (term.type === 'Comma' && i !== 0 && !hasTailMatch) {
// recover cursor to state before last match and stop matching
lastNode = node && node.data;
node = beforeMatchNode;
break mismatch;
}
// non-empty match (res.next will refer to another node)
if (res.next !== node) {
// match should be preceded by a comma
if (commaMissed) {
lastNode = node && node.data;
node = beforeMatchNode;
break mismatch;
}
hasTailMatch = term.type !== 'Comma';
lastMatchedTerm = term;
}
putResult(buffer, res.match);
node = skipSpaces(res.next);
} else if (res.badNode) {
badNode = res.badNode;
break mismatch;
} else {
if (res.lastNode) {
lastNode = res.lastNode;
}
// it's ok when comma doesn't match when no matches yet
// but only if comma is not first or last term
if (term.type === 'Comma' && i !== 0 && i !== syntaxNode.terms.length - 1) {
if (hasTailMatch) {
commaMissed = true;
}
continue;
}
// recover cursor to state before last match and stop matching
lastNode = res.lastNode || (node && node.data);
node = beforeMatchNode;
break mismatch;
}
}
// don't allow empty match when [ ]!
if (!lastMatchedTerm && syntaxNode.disallowEmpty) {
// empty match but shouldn't
// recover cursor to state before last match and stop matching
lastNode = node && node.data;
node = beforeMatchNode;
break mismatch;
}
// don't allow comma at the end but only if last term isn't a comma
if (lastMatchedTerm && lastMatchedTerm.type === 'Comma' && term.type !== 'Comma') {
lastNode = node && node.data;
node = beforeMatchNode;
break mismatch;
}
break;
case '&&':
var beforeMatchNode = node;
var lastMatchedTerm = null;
var terms = syntaxNode.terms.slice();
while (terms.length) {
var wasMatch = false;
var emptyMatched = 0;
for (var i = 0; i < terms.length; i++) {
var term = terms[i];
var res = matchSyntax(lexer, term, node);
if (res.match) {
// non-empty match (res.next will refer to another node)
if (res.next !== node) {
lastMatchedTerm = term;
} else {
emptyMatched++;
continue;
}
wasMatch = true;
terms.splice(i--, 1);
putResult(buffer, res.match);
node = skipSpaces(res.next);
break;
} else if (res.badNode) {
badNode = res.badNode;
break mismatch;
} else if (res.lastNode) {
lastNode = res.lastNode;
}
}
if (!wasMatch) {
// terms left, but they all are optional
if (emptyMatched === terms.length) {
break;
}
// not ok
lastNode = node && node.data;
node = beforeMatchNode;
break mismatch;
}
}
if (!lastMatchedTerm && syntaxNode.disallowEmpty) { // don't allow empty match when [ ]!
// empty match but shouldn't
// recover cursor to state before last match and stop matching
lastNode = node && node.data;
node = beforeMatchNode;
break mismatch;
}
break;
case '||':
var beforeMatchNode = node;
var lastMatchedTerm = null;
var terms = syntaxNode.terms.slice();
while (terms.length) {
var wasMatch = false;
var emptyMatched = 0;
for (var i = 0; i < terms.length; i++) {
var term = terms[i];
var res = matchSyntax(lexer, term, node);
if (res.match) {
// non-empty match (res.next will refer to another node)
if (res.next !== node) {
lastMatchedTerm = term;
} else {
emptyMatched++;
continue;
}
wasMatch = true;
terms.splice(i--, 1);
putResult(buffer, res.match);
node = skipSpaces(res.next);
break;
} else if (res.badNode) {
badNode = res.badNode;
break mismatch;
} else if (res.lastNode) {
lastNode = res.lastNode;
}
}
if (!wasMatch) {
break;
}
}
// don't allow empty match
if (!lastMatchedTerm && (emptyMatched !== terms.length || syntaxNode.disallowEmpty)) {
// empty match but shouldn't
// recover cursor to state before last match and stop matching
lastNode = node && node.data;
node = beforeMatchNode;
break mismatch;
}
break;
}
// flush buffer
result.push.apply(result, buffer);
matchCount++;
if (!node) {
break;
}
if (multiplier.comma) {
if (lastComma && lastCommaTermCount === result.length) {
// nothing match after comma
break mismatch;
}
node = skipSpaces(node);
if (node !== null && node.data.type === 'Operator' && node.data.value === ',') {
result.push({
syntax: syntaxNode,
match: [{
type: 'ASTNode',
node: node.data,
childrenMatch: null
}]
});
lastCommaTermCount = result.length;
lastComma = node;
node = node.next;
} else {
lastNode = node !== null ? node.data : null;
break mismatch;
}
}
}
// console.log(syntaxNode.type, badNode, lastNode);
if (lastComma && lastCommaTermCount === result.length) {
// nothing match after comma
node = lastComma;
result.pop();
}
return buildMatchNode(badNode, lastNode, node, matchCount < min ? null : {
syntax: syntaxNode,
match: result,
toJSON: matchToJSON
});
}
function matchSyntax(lexer, syntaxNode, node) {
var badNode = null;
var lastNode = null;
var match = null;
switch (syntaxNode.type) {
case 'Group':
return matchGroup(lexer, syntaxNode, node);
case 'Function':
// expect a function node
if (!node || node.data.type !== 'Function') {
break;
}
var keyword = names.keyword(node.data.name);
var name = syntaxNode.name.toLowerCase();
// check function name with vendor consideration
if (name !== keyword.vendor + keyword.name) {
break;
}
var res = matchSyntax(lexer, syntaxNode.children, node.data.children.head);
if (!res.match || res.next) {
badNode = res.badNode || res.lastNode || (res.next ? res.next.data : null) || node.data;
break;
}
match = [{
type: 'ASTNode',
node: node.data,
childrenMatch: res.match.match
}];
// Use node.next instead of res.next here since syntax is matching
// for internal list and it should be completelly matched (res.next is null at this point).
// Therefore function is matched and we are going to next node
node = node.next;
break;
case 'Parentheses':
if (!node || node.data.type !== 'Parentheses') {
break;
}
var res = matchSyntax(lexer, syntaxNode.children, node.data.children.head);
if (!res.match || res.next) {
badNode = res.badNode || res.lastNode || (res.next ? res.next.data : null) || node.data; // TODO: case when res.next === null
break;
}
match = [{
type: 'ASTNode',
node: node.data,
childrenMatch: res.match.match
}];
node = res.next;
break;
case 'Type':
var typeSyntax = lexer.getType(syntaxNode.name);
if (!typeSyntax) {
throw new Error('Unknown syntax type `' + syntaxNode.name + '`');
}
var res = typeSyntax.match(node);
if (!res.match) {
badNode = res && res.badNode; // TODO: case when res.next === null
lastNode = (res && res.lastNode) || (node && node.data);
break;
}
node = res.next;
putResult(match = [], res.match);
if (match.length === 0) {
match = null;
}
break;
case 'Property':
var propertySyntax = lexer.getProperty(syntaxNode.name);
if (!propertySyntax) {
throw new Error('Unknown property `' + syntaxNode.name + '`');
}
var res = propertySyntax.match(node);
if (!res.match) {
badNode = res && res.badNode; // TODO: case when res.next === null
lastNode = (res && res.lastNode) || (node && node.data);
break;
}
node = res.next;
putResult(match = [], res.match);
if (match.length === 0) {
match = null;
}
break;
case 'Keyword':
if (!node) {
break;
}
if (node.data.type === 'Identifier') {
var keyword = names.keyword(node.data.name);
var keywordName = keyword.name;
var name = syntaxNode.name.toLowerCase();
// drop \0 and \9 hack from keyword name
if (keywordName.indexOf('\\') !== -1) {
keywordName = keywordName.replace(/\\[09].*$/, '');
}
if (name !== keyword.vendor + keywordName) {
break;
}
} else {
// keyword may to be a number (e.g. font-weight: 400 )
if (node.data.type !== 'Number' || node.data.value !== syntaxNode.name) {
break;
}
}
match = [{
type: 'ASTNode',
node: node.data,
childrenMatch: null
}];
node = node.next;
break;
case 'Slash':
case 'Comma':
if (!node || node.data.type !== 'Operator' || node.data.value !== syntaxNode.value) {
break;
}
match = [{
type: 'ASTNode',
node: node.data,
childrenMatch: null
}];
node = node.next;
break;
case 'String':
if (!node || node.data.type !== 'String') {
break;
}
match = [{
type: 'ASTNode',
node: node.data,
childrenMatch: null
}];
node = node.next;
break;
case 'ASTNode':
if (node && syntaxNode.match(node)) {
match = {
type: 'ASTNode',
node: node.data,
childrenMatch: null
};
node = node.next;
}
return buildMatchNode(badNode, lastNode, node, match);
default:
throw new Error('Not implemented yet node type: ' + syntaxNode.type);
}
return buildMatchNode(badNode, lastNode, node, match === null ? null : {
syntax: syntaxNode,
match: match,
toJSON: matchToJSON
});
};
module.exports = matchSyntax;

84
build/node_modules/css-tree/lib/lexer/search.js generated vendored Normal file
View File

@@ -0,0 +1,84 @@
var List = require('../utils/list');
function getFirstMatchNode(matchNode) {
if (matchNode.type === 'ASTNode') {
return matchNode.node;
}
if (matchNode.match.length !== 0) {
return getFirstMatchNode(matchNode.match[0]);
}
return null;
}
function getLastMatchNode(matchNode) {
if (matchNode.type === 'ASTNode') {
return matchNode.node;
}
if (matchNode.match.length !== 0) {
return getLastMatchNode(matchNode.match[matchNode.match.length - 1]);
}
return null;
}
function matchFragments(lexer, ast, match, type, name) {
function findFragments(matchNode) {
if (matchNode.type === 'ASTNode') {
return;
}
if (matchNode.syntax.type === type &&
matchNode.syntax.name === name) {
var start = getFirstMatchNode(matchNode);
var end = getLastMatchNode(matchNode);
lexer.syntax.walk(ast, function(node, item, list) {
if (node === start) {
var nodes = new List();
var loc = null;
do {
nodes.appendData(item.data);
if (item.data === end) {
break;
}
item = item.next;
} while (item !== null);
if (start.loc !== null && end.loc !== null) {
loc = {
source: start.loc.source,
start: start.loc.start,
end: end.loc.end
};
}
fragments.push({
parent: list,
loc: loc,
nodes: nodes
});
}
});
}
matchNode.match.forEach(findFragments);
}
var fragments = [];
if (match.matched !== null) {
findFragments(match.matched);
}
return fragments;
}
module.exports = {
matchFragments: matchFragments
};

163
build/node_modules/css-tree/lib/lexer/structure.js generated vendored Normal file
View File

@@ -0,0 +1,163 @@
var List = require('../utils/list');
var hasOwnProperty = Object.prototype.hasOwnProperty;
function isValidNumber(value) {
// Number.isInteger(value) && value >= 0
return (
typeof value === 'number' &&
isFinite(value) &&
Math.floor(value) === value &&
value >= 0
);
}
function isValidLocation(loc) {
return (
Boolean(loc) &&
isValidNumber(loc.offset) &&
isValidNumber(loc.line) &&
isValidNumber(loc.column)
);
}
function createNodeStructureChecker(type, fields) {
return function checkNode(node, warn) {
if (!node || node.constructor !== Object) {
return warn(node, 'Type of node should be an Object');
}
for (var key in node) {
var valid = true;
if (hasOwnProperty.call(node, key) === false) {
continue;
}
if (key === 'type') {
if (node.type !== type) {
warn(node, 'Wrong node type `' + node.type + '`, expected `' + type + '`');
}
} else if (key === 'loc') {
if (node.loc === null) {
continue;
} else if (node.loc && node.loc.constructor === Object) {
if (typeof node.loc.source !== 'string') {
key += '.source';
} else if (!isValidLocation(node.loc.start)) {
key += '.start';
} else if (!isValidLocation(node.loc.end)) {
key += '.end';
} else {
continue;
}
}
valid = false;
} else if (fields.hasOwnProperty(key)) {
for (var i = 0, valid = false; !valid && i < fields[key].length; i++) {
var fieldType = fields[key][i];
switch (fieldType) {
case String:
valid = typeof node[key] === 'string';
break;
case Boolean:
valid = typeof node[key] === 'boolean';
break;
case null:
valid = node[key] === null;
break;
default:
if (typeof fieldType === 'string') {
valid = node[key] && node[key].type === fieldType;
} else if (Array.isArray(fieldType)) {
valid = node[key] instanceof List;
}
}
}
} else {
warn(node, 'Unknown field `' + key + '` for ' + type + ' node type');
}
if (!valid) {
warn(node, 'Bad value for `' + type + '.' + key + '`');
}
}
for (var key in fields) {
if (hasOwnProperty.call(fields, key) &&
hasOwnProperty.call(node, key) === false) {
warn(node, 'Field `' + type + '.' + key + '` is missed');
}
}
};
}
function processStructure(name, nodeType) {
var structure = nodeType.structure;
var fields = {
type: String,
loc: true
};
var docs = {
type: '"' + name + '"'
};
for (var key in structure) {
if (hasOwnProperty.call(structure, key) === false) {
continue;
}
var docsTypes = [];
var 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(' | ');
}
return {
docs: docs,
check: createNodeStructureChecker(name, fields)
};
}
module.exports = {
getStructureFromConfig: function(config) {
var structure = {};
if (config.node) {
for (var name in config.node) {
if (hasOwnProperty.call(config.node, name)) {
var nodeType = config.node[name];
if (nodeType.structure) {
structure[name] = processStructure(name, nodeType);
} else {
throw new Error('Missed `structure` field in `' + name + '` node type definition');
}
}
}
}
return structure;
}
};

76
build/node_modules/css-tree/lib/lexer/trace.js generated vendored Normal file
View File

@@ -0,0 +1,76 @@
function getTrace(node) {
function hasMatch(matchNode) {
if (matchNode.type === 'ASTNode') {
if (matchNode.node === node) {
result = [];
return true;
}
if (matchNode.childrenMatch) {
// use for-loop for better perfomance
for (var i = 0; i < matchNode.childrenMatch.length; i++) {
if (hasMatch(matchNode.childrenMatch[i])) {
return true;
}
}
}
} else {
// use for-loop for better perfomance
for (var i = 0; i < matchNode.match.length; i++) {
if (hasMatch(matchNode.match[i])) {
if (matchNode.syntax.type === 'Type' ||
matchNode.syntax.type === 'Property' ||
matchNode.syntax.type === 'Keyword') {
result.unshift(matchNode.syntax);
}
return true;
}
}
}
return false;
}
var result = null;
if (this.matched !== null) {
hasMatch(this.matched);
}
return result;
}
function testNode(match, node, fn) {
var trace = getTrace.call(match, node);
if (trace === null) {
return false;
}
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
};