mirror of
https://github.com/sern-handler/website
synced 2026-06-15 04:12:26 +00:00
723 lines
26 KiB
JavaScript
723 lines
26 KiB
JavaScript
import { createMulticharIndex, createRegularIndex, emptyMulticharIndex, emptyRegularIndex } from './indexes.js';
|
|
import { calculatePseudoSignatures, defaultPseudoSignature, emptyPseudoSignatures } from './pseudo-signatures.js';
|
|
import { cssSyntaxDefinitions, extendSyntaxDefinition, getXmlOptions } from './syntax-definitions.js';
|
|
import { digitsChars, isHex, isIdent, isIdentStart, maxHexLength, quoteChars, whitespaceChars } from './utils.js';
|
|
var errorPrefix = "css-selector-parser parse error: ";
|
|
/**
|
|
* Creates a parse function to be used later to parse CSS selectors.
|
|
*/
|
|
export function createParser(options) {
|
|
if (options === void 0) { options = {}; }
|
|
var _a = options.syntax, syntax = _a === void 0 ? 'latest' : _a, substitutes = options.substitutes, _b = options.strict, strict = _b === void 0 ? true : _b;
|
|
var syntaxDefinition = typeof syntax === 'object' ? syntax : cssSyntaxDefinitions[syntax];
|
|
if (syntaxDefinition.baseSyntax) {
|
|
syntaxDefinition = extendSyntaxDefinition(cssSyntaxDefinitions[syntaxDefinition.baseSyntax], syntaxDefinition);
|
|
}
|
|
var _c = syntaxDefinition.tag
|
|
? [true, Boolean(getXmlOptions(syntaxDefinition.tag).wildcard)]
|
|
: [false, false], tagNameEnabled = _c[0], tagNameWildcardEnabled = _c[1];
|
|
var idEnabled = Boolean(syntaxDefinition.ids);
|
|
var classNamesEnabled = Boolean(syntaxDefinition.classNames);
|
|
var namespaceEnabled = Boolean(syntaxDefinition.namespace);
|
|
var namespaceWildcardEnabled = syntaxDefinition.namespace &&
|
|
(syntaxDefinition.namespace === true || syntaxDefinition.namespace.wildcard === true);
|
|
if (namespaceEnabled && !tagNameEnabled) {
|
|
throw new Error("".concat(errorPrefix, "Namespaces cannot be enabled while tags are disabled."));
|
|
}
|
|
var substitutesEnabled = Boolean(substitutes);
|
|
var combinatorsIndex = syntaxDefinition.combinators
|
|
? createMulticharIndex(syntaxDefinition.combinators)
|
|
: emptyMulticharIndex;
|
|
var _d = syntaxDefinition.attributes
|
|
? [
|
|
true,
|
|
syntaxDefinition.attributes.operators
|
|
? createMulticharIndex(syntaxDefinition.attributes.operators)
|
|
: emptyMulticharIndex,
|
|
syntaxDefinition.attributes.caseSensitivityModifiers
|
|
? createRegularIndex(syntaxDefinition.attributes.caseSensitivityModifiers)
|
|
: emptyRegularIndex,
|
|
syntaxDefinition.attributes.unknownCaseSensitivityModifiers === 'accept'
|
|
]
|
|
: [false, emptyMulticharIndex, emptyRegularIndex, false], attributesEnabled = _d[0], attributesOperatorsIndex = _d[1], attributesCaseSensitivityModifiers = _d[2], attributesAcceptUnknownCaseSensitivityModifiers = _d[3];
|
|
var attributesCaseSensitivityModifiersEnabled = attributesAcceptUnknownCaseSensitivityModifiers || Object.keys(attributesCaseSensitivityModifiers).length > 0;
|
|
var _e = syntaxDefinition.pseudoClasses
|
|
? [
|
|
true,
|
|
syntaxDefinition.pseudoClasses.definitions
|
|
? calculatePseudoSignatures(syntaxDefinition.pseudoClasses.definitions)
|
|
: emptyPseudoSignatures,
|
|
syntaxDefinition.pseudoClasses.unknown === 'accept'
|
|
]
|
|
: [false, emptyPseudoSignatures, false], pseudoClassesEnabled = _e[0], pseudoClassesDefinitions = _e[1], pseudoClassesAcceptUnknown = _e[2];
|
|
var _f = syntaxDefinition.pseudoElements
|
|
? [
|
|
true,
|
|
syntaxDefinition.pseudoElements.notation === 'singleColon' ||
|
|
syntaxDefinition.pseudoElements.notation === 'both',
|
|
!syntaxDefinition.pseudoElements.notation ||
|
|
syntaxDefinition.pseudoElements.notation === 'doubleColon' ||
|
|
syntaxDefinition.pseudoElements.notation === 'both',
|
|
syntaxDefinition.pseudoElements.definitions
|
|
? calculatePseudoSignatures(Array.isArray(syntaxDefinition.pseudoElements.definitions)
|
|
? { NoArgument: syntaxDefinition.pseudoElements.definitions }
|
|
: syntaxDefinition.pseudoElements.definitions)
|
|
: emptyPseudoSignatures,
|
|
syntaxDefinition.pseudoElements.unknown === 'accept'
|
|
]
|
|
: [false, false, false, emptyPseudoSignatures, false], pseudoElementsEnabled = _f[0], pseudoElementsSingleColonNotationEnabled = _f[1], pseudoElementsDoubleColonNotationEnabled = _f[2], pseudoElementsDefinitions = _f[3], pseudoElementsAcceptUnknown = _f[4];
|
|
var str = '';
|
|
var l = str.length;
|
|
var pos = 0;
|
|
var chr = '';
|
|
var is = function (comparison) { return chr === comparison; };
|
|
var isTagStart = function () { return is('*') || isIdentStart(chr); };
|
|
var rewind = function (newPos) {
|
|
pos = newPos;
|
|
chr = str.charAt(pos);
|
|
};
|
|
var next = function () {
|
|
pos++;
|
|
chr = str.charAt(pos);
|
|
};
|
|
var readAndNext = function () {
|
|
var current = chr;
|
|
pos++;
|
|
chr = str.charAt(pos);
|
|
return current;
|
|
};
|
|
/** @throws ParserError */
|
|
function fail(errorMessage) {
|
|
var position = Math.min(l - 1, pos);
|
|
var error = new Error("".concat(errorPrefix).concat(errorMessage, " Pos: ").concat(position, "."));
|
|
error.position = position;
|
|
error.name = 'ParserError';
|
|
throw error;
|
|
}
|
|
function assert(condition, errorMessage) {
|
|
if (!condition) {
|
|
return fail(errorMessage);
|
|
}
|
|
}
|
|
var assertNonEof = function () {
|
|
assert(pos < l, 'Unexpected end of input.');
|
|
};
|
|
var isEof = function () { return pos >= l; };
|
|
var pass = function (character) {
|
|
assert(pos < l, "Expected \"".concat(character, "\" but end of input reached."));
|
|
assert(chr === character, "Expected \"".concat(character, "\" but \"").concat(chr, "\" found."));
|
|
pos++;
|
|
chr = str.charAt(pos);
|
|
};
|
|
function matchMulticharIndex(index) {
|
|
var match = matchMulticharIndexPos(index, pos);
|
|
if (match) {
|
|
pos += match.length;
|
|
chr = str.charAt(pos);
|
|
return match;
|
|
}
|
|
}
|
|
function matchMulticharIndexPos(index, subPos) {
|
|
var char = str.charAt(subPos);
|
|
var charIndex = index[char];
|
|
if (charIndex) {
|
|
var subMatch = matchMulticharIndexPos(charIndex.chars, subPos + 1);
|
|
if (subMatch) {
|
|
return subMatch;
|
|
}
|
|
if (charIndex.self) {
|
|
return charIndex.self;
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* @see https://www.w3.org/TR/css-syntax/#hex-digit-diagram
|
|
*/
|
|
function parseHex() {
|
|
var hex = readAndNext();
|
|
var count = 1;
|
|
while (isHex(chr) && count < maxHexLength) {
|
|
hex += readAndNext();
|
|
count++;
|
|
}
|
|
skipSingleWhitespace();
|
|
return String.fromCharCode(parseInt(hex, 16));
|
|
}
|
|
/**
|
|
* @see https://www.w3.org/TR/css-syntax/#string-token-diagram
|
|
*/
|
|
function parseString(quote) {
|
|
var result = '';
|
|
pass(quote);
|
|
while (pos < l) {
|
|
if (is(quote)) {
|
|
next();
|
|
return result;
|
|
}
|
|
else if (is('\\')) {
|
|
next();
|
|
if (is(quote)) {
|
|
result += quote;
|
|
next();
|
|
}
|
|
else if (chr === '\n' || chr === '\f') {
|
|
next();
|
|
}
|
|
else if (chr === '\r') {
|
|
next();
|
|
if (is('\n')) {
|
|
next();
|
|
}
|
|
}
|
|
else if (isHex(chr)) {
|
|
result += parseHex();
|
|
}
|
|
else {
|
|
result += chr;
|
|
next();
|
|
}
|
|
}
|
|
else {
|
|
result += chr;
|
|
next();
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
/**
|
|
* @see https://www.w3.org/TR/css-syntax/#ident-token-diagram
|
|
*/
|
|
function parseIdentifier() {
|
|
if (!isIdentStart(chr)) {
|
|
return null;
|
|
}
|
|
var result = '';
|
|
while (is('-')) {
|
|
result += chr;
|
|
next();
|
|
}
|
|
if (result === '-' && !isIdent(chr) && !is('\\')) {
|
|
fail('Identifiers cannot consist of a single hyphen.');
|
|
}
|
|
if (strict && result.length >= 2) {
|
|
// Checking this only for strict mode since browsers work fine with these identifiers.
|
|
fail('Identifiers cannot start with two hyphens with strict mode on.');
|
|
}
|
|
if (digitsChars[chr]) {
|
|
fail('Identifiers cannot start with hyphens followed by digits.');
|
|
}
|
|
while (pos < l) {
|
|
if (isIdent(chr)) {
|
|
result += readAndNext();
|
|
}
|
|
else if (is('\\')) {
|
|
next();
|
|
assertNonEof();
|
|
if (isHex(chr)) {
|
|
result += parseHex();
|
|
}
|
|
else {
|
|
result += readAndNext();
|
|
}
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
function parsePseudoClassString() {
|
|
var result = '';
|
|
while (pos < l) {
|
|
if (is(')')) {
|
|
break;
|
|
}
|
|
else if (is('\\')) {
|
|
next();
|
|
if (isEof() && !strict) {
|
|
return (result + '\\').trim();
|
|
}
|
|
assertNonEof();
|
|
if (isHex(chr)) {
|
|
result += parseHex();
|
|
}
|
|
else {
|
|
result += readAndNext();
|
|
}
|
|
}
|
|
else {
|
|
result += readAndNext();
|
|
}
|
|
}
|
|
return result.trim();
|
|
}
|
|
function skipSingleWhitespace() {
|
|
if (chr === ' ' || chr === '\t' || chr === '\f' || chr === '\n') {
|
|
next();
|
|
return;
|
|
}
|
|
if (chr === '\r') {
|
|
next();
|
|
}
|
|
if (chr === '\n') {
|
|
next();
|
|
}
|
|
}
|
|
function skipWhitespace() {
|
|
while (whitespaceChars[chr]) {
|
|
next();
|
|
}
|
|
}
|
|
function parseSelector(relative) {
|
|
if (relative === void 0) { relative = false; }
|
|
skipWhitespace();
|
|
var rules = [parseRule(relative)];
|
|
while (is(',')) {
|
|
next();
|
|
skipWhitespace();
|
|
rules.push(parseRule(relative));
|
|
}
|
|
return {
|
|
type: 'Selector',
|
|
rules: rules
|
|
};
|
|
}
|
|
function parseAttribute() {
|
|
pass('[');
|
|
skipWhitespace();
|
|
var attr;
|
|
if (is('|')) {
|
|
assert(namespaceEnabled, 'Namespaces are not enabled.');
|
|
next();
|
|
var name_1 = parseIdentifier();
|
|
assert(name_1, 'Expected attribute name.');
|
|
attr = {
|
|
type: 'Attribute',
|
|
name: name_1,
|
|
namespace: { type: 'NoNamespace' }
|
|
};
|
|
}
|
|
else if (is('*')) {
|
|
assert(namespaceEnabled, 'Namespaces are not enabled.');
|
|
assert(namespaceWildcardEnabled, 'Wildcard namespace is not enabled.');
|
|
next();
|
|
pass('|');
|
|
var name_2 = parseIdentifier();
|
|
assert(name_2, 'Expected attribute name.');
|
|
attr = {
|
|
type: 'Attribute',
|
|
name: name_2,
|
|
namespace: { type: 'WildcardNamespace' }
|
|
};
|
|
}
|
|
else {
|
|
var identifier = parseIdentifier();
|
|
assert(identifier, 'Expected attribute name.');
|
|
attr = {
|
|
type: 'Attribute',
|
|
name: identifier
|
|
};
|
|
if (is('|')) {
|
|
var savedPos = pos;
|
|
next();
|
|
if (isIdentStart(chr)) {
|
|
assert(namespaceEnabled, 'Namespaces are not enabled.');
|
|
var name_3 = parseIdentifier();
|
|
assert(name_3, 'Expected attribute name.');
|
|
attr = {
|
|
type: 'Attribute',
|
|
name: name_3,
|
|
namespace: { type: 'NamespaceName', name: identifier }
|
|
};
|
|
}
|
|
else {
|
|
rewind(savedPos);
|
|
}
|
|
}
|
|
}
|
|
assert(attr.name, 'Expected attribute name.');
|
|
skipWhitespace();
|
|
if (isEof() && !strict) {
|
|
return attr;
|
|
}
|
|
if (is(']')) {
|
|
next();
|
|
}
|
|
else {
|
|
attr.operator = matchMulticharIndex(attributesOperatorsIndex);
|
|
assert(attr.operator, 'Expected a valid attribute selector operator.');
|
|
skipWhitespace();
|
|
assertNonEof();
|
|
if (quoteChars[chr]) {
|
|
attr.value = {
|
|
type: 'String',
|
|
value: parseString(chr)
|
|
};
|
|
}
|
|
else if (substitutesEnabled && is('$')) {
|
|
next();
|
|
var name_4 = parseIdentifier();
|
|
assert(name_4, 'Expected substitute name.');
|
|
attr.value = {
|
|
type: 'Substitution',
|
|
name: name_4
|
|
};
|
|
}
|
|
else {
|
|
var value = parseIdentifier();
|
|
assert(value, 'Expected attribute value.');
|
|
attr.value = {
|
|
type: 'String',
|
|
value: value
|
|
};
|
|
}
|
|
skipWhitespace();
|
|
if (isEof() && !strict) {
|
|
return attr;
|
|
}
|
|
if (!is(']')) {
|
|
var caseSensitivityModifier = parseIdentifier();
|
|
assert(caseSensitivityModifier, 'Expected end of attribute selector.');
|
|
attr.caseSensitivityModifier = caseSensitivityModifier;
|
|
assert(attributesCaseSensitivityModifiersEnabled, 'Attribute case sensitivity modifiers are not enabled.');
|
|
assert(attributesAcceptUnknownCaseSensitivityModifiers ||
|
|
attributesCaseSensitivityModifiers[attr.caseSensitivityModifier], 'Unknown attribute case sensitivity modifier.');
|
|
skipWhitespace();
|
|
if (isEof() && !strict) {
|
|
return attr;
|
|
}
|
|
}
|
|
pass(']');
|
|
}
|
|
return attr;
|
|
}
|
|
function parseNumber() {
|
|
var result = '';
|
|
while (digitsChars[chr]) {
|
|
result += readAndNext();
|
|
}
|
|
assert(result !== '', 'Formula parse error.');
|
|
return parseInt(result);
|
|
}
|
|
var isNumberStart = function () { return is('-') || is('+') || digitsChars[chr]; };
|
|
function parseFormula() {
|
|
if (is('e') || is('o')) {
|
|
var ident = parseIdentifier();
|
|
if (ident === 'even') {
|
|
skipWhitespace();
|
|
return [2, 0];
|
|
}
|
|
if (ident === 'odd') {
|
|
skipWhitespace();
|
|
return [2, 1];
|
|
}
|
|
}
|
|
var firstNumber = null;
|
|
var firstNumberMultiplier = 1;
|
|
if (is('-')) {
|
|
next();
|
|
firstNumberMultiplier = -1;
|
|
}
|
|
if (isNumberStart()) {
|
|
if (is('+')) {
|
|
next();
|
|
}
|
|
firstNumber = parseNumber();
|
|
if (!is('\\') && !is('n')) {
|
|
return [0, firstNumber * firstNumberMultiplier];
|
|
}
|
|
}
|
|
if (firstNumber === null) {
|
|
firstNumber = 1;
|
|
}
|
|
firstNumber *= firstNumberMultiplier;
|
|
var identifier;
|
|
if (is('\\')) {
|
|
next();
|
|
if (isHex(chr)) {
|
|
identifier = parseHex();
|
|
}
|
|
else {
|
|
identifier = readAndNext();
|
|
}
|
|
}
|
|
else {
|
|
identifier = readAndNext();
|
|
}
|
|
assert(identifier === 'n', 'Formula parse error: expected "n".');
|
|
skipWhitespace();
|
|
if (is('+') || is('-')) {
|
|
var sign = is('+') ? 1 : -1;
|
|
next();
|
|
skipWhitespace();
|
|
return [firstNumber, sign * parseNumber()];
|
|
}
|
|
else {
|
|
return [firstNumber, 0];
|
|
}
|
|
}
|
|
function parsePseudoArgument(pseudoName, type, signature) {
|
|
var argument;
|
|
if (is('(')) {
|
|
next();
|
|
skipWhitespace();
|
|
if (substitutesEnabled && is('$')) {
|
|
next();
|
|
var name_5 = parseIdentifier();
|
|
assert(name_5, 'Expected substitute name.');
|
|
argument = {
|
|
type: 'Substitution',
|
|
name: name_5
|
|
};
|
|
}
|
|
else if (signature.type === 'String') {
|
|
argument = {
|
|
type: 'String',
|
|
value: parsePseudoClassString()
|
|
};
|
|
assert(argument.value, "Expected ".concat(type, " argument value."));
|
|
}
|
|
else if (signature.type === 'Selector') {
|
|
argument = parseSelector(true);
|
|
}
|
|
else if (signature.type === 'Formula') {
|
|
var _a = parseFormula(), a = _a[0], b = _a[1];
|
|
argument = {
|
|
type: 'Formula',
|
|
a: a,
|
|
b: b
|
|
};
|
|
if (signature.ofSelector) {
|
|
skipWhitespace();
|
|
if (is('o') || is('\\')) {
|
|
var ident = parseIdentifier();
|
|
assert(ident === 'of', 'Formula of selector parse error.');
|
|
skipWhitespace();
|
|
argument = {
|
|
type: 'FormulaOfSelector',
|
|
a: a,
|
|
b: b,
|
|
selector: parseRule()
|
|
};
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
return fail("Invalid ".concat(type, " signature."));
|
|
}
|
|
skipWhitespace();
|
|
if (isEof() && !strict) {
|
|
return argument;
|
|
}
|
|
pass(')');
|
|
}
|
|
else {
|
|
assert(signature.optional, "Argument is required for ".concat(type, " \"").concat(pseudoName, "\"."));
|
|
}
|
|
return argument;
|
|
}
|
|
function parseTagName() {
|
|
if (is('*')) {
|
|
assert(tagNameWildcardEnabled, 'Wildcard tag name is not enabled.');
|
|
next();
|
|
return { type: 'WildcardTag' };
|
|
}
|
|
else if (isIdentStart(chr)) {
|
|
assert(tagNameEnabled, 'Tag names are not enabled.');
|
|
var name_6 = parseIdentifier();
|
|
assert(name_6, 'Expected tag name.');
|
|
return {
|
|
type: 'TagName',
|
|
name: name_6
|
|
};
|
|
}
|
|
else {
|
|
return fail('Expected tag name.');
|
|
}
|
|
}
|
|
function parseTagNameWithNamespace() {
|
|
if (is('*')) {
|
|
var savedPos = pos;
|
|
next();
|
|
if (!is('|')) {
|
|
rewind(savedPos);
|
|
return parseTagName();
|
|
}
|
|
next();
|
|
if (!isTagStart()) {
|
|
rewind(savedPos);
|
|
return parseTagName();
|
|
}
|
|
assert(namespaceEnabled, 'Namespaces are not enabled.');
|
|
assert(namespaceWildcardEnabled, 'Wildcard namespace is not enabled.');
|
|
var tagName = parseTagName();
|
|
tagName.namespace = { type: 'WildcardNamespace' };
|
|
return tagName;
|
|
}
|
|
else if (is('|')) {
|
|
assert(namespaceEnabled, 'Namespaces are not enabled.');
|
|
next();
|
|
var tagName = parseTagName();
|
|
tagName.namespace = { type: 'NoNamespace' };
|
|
return tagName;
|
|
}
|
|
else if (isIdentStart(chr)) {
|
|
var identifier = parseIdentifier();
|
|
assert(identifier, 'Expected tag name.');
|
|
if (!is('|')) {
|
|
assert(tagNameEnabled, 'Tag names are not enabled.');
|
|
return {
|
|
type: 'TagName',
|
|
name: identifier
|
|
};
|
|
}
|
|
var savedPos = pos;
|
|
next();
|
|
if (!isTagStart()) {
|
|
rewind(savedPos);
|
|
return {
|
|
type: 'TagName',
|
|
name: identifier
|
|
};
|
|
}
|
|
assert(namespaceEnabled, 'Namespaces are not enabled.');
|
|
var tagName = parseTagName();
|
|
tagName.namespace = { type: 'NamespaceName', name: identifier };
|
|
return tagName;
|
|
}
|
|
else {
|
|
return fail('Expected tag name.');
|
|
}
|
|
}
|
|
function parseRule(relative) {
|
|
var _a, _b;
|
|
if (relative === void 0) { relative = false; }
|
|
var rule = { type: 'Rule', items: [] };
|
|
if (relative) {
|
|
var combinator = matchMulticharIndex(combinatorsIndex);
|
|
if (combinator) {
|
|
rule.combinator = combinator;
|
|
skipWhitespace();
|
|
}
|
|
}
|
|
while (pos < l) {
|
|
if (isTagStart()) {
|
|
assert(rule.items.length === 0, 'Unexpected tag/namespace start.');
|
|
rule.items.push(parseTagNameWithNamespace());
|
|
}
|
|
else if (is('|')) {
|
|
var savedPos = pos;
|
|
next();
|
|
if (isTagStart()) {
|
|
assert(rule.items.length === 0, 'Unexpected tag/namespace start.');
|
|
rewind(savedPos);
|
|
rule.items.push(parseTagNameWithNamespace());
|
|
}
|
|
else {
|
|
rewind(savedPos);
|
|
break;
|
|
}
|
|
}
|
|
else if (is('.')) {
|
|
assert(classNamesEnabled, 'Class names are not enabled.');
|
|
next();
|
|
var className = parseIdentifier();
|
|
assert(className, 'Expected class name.');
|
|
rule.items.push({ type: 'ClassName', name: className });
|
|
}
|
|
else if (is('#')) {
|
|
assert(idEnabled, 'IDs are not enabled.');
|
|
next();
|
|
var idName = parseIdentifier();
|
|
assert(idName, 'Expected ID name.');
|
|
rule.items.push({ type: 'Id', name: idName });
|
|
}
|
|
else if (is('[')) {
|
|
assert(attributesEnabled, 'Attributes are not enabled.');
|
|
rule.items.push(parseAttribute());
|
|
}
|
|
else if (is(':')) {
|
|
var isDoubleColon = false;
|
|
var isPseudoElement = false;
|
|
next();
|
|
if (is(':')) {
|
|
assert(pseudoElementsEnabled, 'Pseudo elements are not enabled.');
|
|
assert(pseudoElementsDoubleColonNotationEnabled, 'Pseudo elements double colon notation is not enabled.');
|
|
isDoubleColon = true;
|
|
next();
|
|
}
|
|
var pseudoName = parseIdentifier();
|
|
assert(isDoubleColon || pseudoName, 'Expected pseudo-class name.');
|
|
assert(!isDoubleColon || pseudoName, 'Expected pseudo-element name.');
|
|
assert(pseudoName, 'Expected pseudo-class name.');
|
|
assert(!isDoubleColon ||
|
|
pseudoElementsAcceptUnknown ||
|
|
Object.prototype.hasOwnProperty.call(pseudoElementsDefinitions, pseudoName), "Unknown pseudo-element \"".concat(pseudoName, "\"."));
|
|
isPseudoElement =
|
|
pseudoElementsEnabled &&
|
|
(isDoubleColon ||
|
|
(!isDoubleColon &&
|
|
pseudoElementsSingleColonNotationEnabled &&
|
|
Object.prototype.hasOwnProperty.call(pseudoElementsDefinitions, pseudoName)));
|
|
if (isPseudoElement) {
|
|
var signature = (_a = pseudoElementsDefinitions[pseudoName]) !== null && _a !== void 0 ? _a : (pseudoElementsAcceptUnknown && defaultPseudoSignature);
|
|
var pseudoElement = {
|
|
type: 'PseudoElement',
|
|
name: pseudoName
|
|
};
|
|
var argument = parsePseudoArgument(pseudoName, 'pseudo-element', signature);
|
|
if (argument) {
|
|
assert(argument.type !== 'Formula' && argument.type !== 'FormulaOfSelector', 'Pseudo-elements cannot have formula argument.');
|
|
pseudoElement.argument = argument;
|
|
}
|
|
rule.items.push(pseudoElement);
|
|
}
|
|
else {
|
|
assert(pseudoClassesEnabled, 'Pseudo-classes are not enabled.');
|
|
var signature = (_b = pseudoClassesDefinitions[pseudoName]) !== null && _b !== void 0 ? _b : (pseudoClassesAcceptUnknown && defaultPseudoSignature);
|
|
assert(signature, "Unknown pseudo-class: \"".concat(pseudoName, "\"."));
|
|
var argument = parsePseudoArgument(pseudoName, 'pseudo-class', signature);
|
|
var pseudoClass = {
|
|
type: 'PseudoClass',
|
|
name: pseudoName
|
|
};
|
|
if (argument) {
|
|
pseudoClass.argument = argument;
|
|
}
|
|
rule.items.push(pseudoClass);
|
|
}
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
if (rule.items.length === 0) {
|
|
if (isEof()) {
|
|
return fail('Expected rule but end of input reached.');
|
|
}
|
|
else {
|
|
return fail("Expected rule but \"".concat(chr, "\" found."));
|
|
}
|
|
}
|
|
skipWhitespace();
|
|
if (!isEof() && !is(',') && !is(')')) {
|
|
var combinator = matchMulticharIndex(combinatorsIndex);
|
|
skipWhitespace();
|
|
rule.nestedRule = parseRule();
|
|
rule.nestedRule.combinator = combinator;
|
|
}
|
|
return rule;
|
|
}
|
|
return function (input) {
|
|
// noinspection SuspiciousTypeOfGuard
|
|
if (typeof input !== 'string') {
|
|
throw new Error("".concat(errorPrefix, "Expected string input."));
|
|
}
|
|
str = input;
|
|
l = str.length;
|
|
pos = 0;
|
|
chr = str.charAt(0);
|
|
return parseSelector();
|
|
};
|
|
}
|