parserlib: cosmetics/simplifications

This commit is contained in:
tophf 2022-08-03 20:29:31 +03:00
parent 6ff5f17140
commit 6995483ec0
2 changed files with 42 additions and 71 deletions

View File

@ -330,7 +330,7 @@ CSSLint.Util = {
/** Gets the lower-cased text without vendor prefix */ /** Gets the lower-cased text without vendor prefix */
getPropName(prop) { getPropName(prop) {
return prop._propName || return prop._propName ||
(prop._propName = prop.text.replace(parserlib.util.rxVendorPrefix, '').toLowerCase()); (prop._propName = prop.text.match(parserlib.util.rxVendorPrefix)[2].toLowerCase());
}, },
registerRuleEvents(parser, {start, property, end}) { registerRuleEvents(parser, {start, property, end}) {
@ -1327,14 +1327,13 @@ CSSLint.addRule['known-pseudos'] = [{
const rx = /^(:+)(?:-(\w+)-)?([^(]+)(\()?/i; const rx = /^(:+)(?:-(\w+)-)?([^(]+)(\()?/i;
const allowsFunc = Func + FuncToo; const allowsFunc = Func + FuncToo;
const allowsPrefix = WK + Moz; const allowsPrefix = WK + Moz;
const {lower} = parserlib.util;
const checkSelector = ({parts}) => { const checkSelector = ({parts}) => {
for (const {modifiers} of parts || []) { for (const {modifiers} of parts || []) {
if (!modifiers) continue; if (!modifiers) continue;
for (const mod of modifiers) { for (const mod of modifiers) {
if (mod.type === 'pseudo') { if (mod.type === 'pseudo') {
const {text} = mod; const {text} = mod;
const [all, colons, prefix, name, paren] = rx.exec(lower(text)) || 0; const [all, colons, prefix, name, paren] = rx.exec(text.toLowerCase()) || 0;
const defPrefixed = definitionsPrefixed[name]; const defPrefixed = definitionsPrefixed[name];
const def = definitions[name] || defPrefixed; const def = definitions[name] || defPrefixed;
for (const err of !def ? ['Unknown pseudo'] : [ for (const err of !def ? ['Unknown pseudo'] : [

View File

@ -715,9 +715,8 @@ self.parserlib = (() => {
const rxNameChar = /[-\\_\da-zA-Z\u00A0-\uFFFF]/u; const rxNameChar = /[-\\_\da-zA-Z\u00A0-\uFFFF]/u;
const rxNameCharNoEsc = /[-_\da-zA-Z\u00A0-\uFFFF]+/yu; // must not match \\ const rxNameCharNoEsc = /[-_\da-zA-Z\u00A0-\uFFFF]+/yu; // must not match \\
const rxUnquotedUrlCharNoEsc = /[-!#$%&*-[\]-~\u00A0-\uFFFF]+/yu; // must not match \\ const rxUnquotedUrlCharNoEsc = /[-!#$%&*-[\]-~\u00A0-\uFFFF]+/yu; // must not match \\
const rxVendorPrefix = /^-(webkit|moz|ms|o)-(.+)/i; const rxVendorPrefix = /^(?:-(webkit|moz|ms|o)-)?(.+)/i;
const rxCalc = /^(?:-(webkit|moz|ms|o)-)?(calc|min|max|clamp)\(/i; const rxCalc = /^(?:-(webkit|moz|ms|o)-)?(calc|min|max|clamp)\(/i;
const lowercaseCache = new Map();
//#endregion //#endregion
//#region ValidationTypes - definitions //#region ValidationTypes - definitions
@ -777,7 +776,7 @@ self.parserlib = (() => {
'<icccolor>': 'cielab() | cielch() | cielchab() | icc-color() | icc-named-color()', '<icccolor>': 'cielab() | cielch() | cielchab() | icc-color() | icc-named-color()',
'<ident-for-grid>': customIdentChecker('span|auto'), '<ident-for-grid>': customIdentChecker('span|auto'),
'<ident-not-generic-family>': p => vtIsIdent(p) && !VTSimple['<generic-family>'](p), '<ident-not-generic-family>': p => vtIsIdent(p) && !VTSimple['<generic-family>'](p),
'<ident-not-none>': p => vtIsIdent(p) && !lowerCmp(p.value, 'none'), '<ident-not-none>': p => vtIsIdent(p) && !/^none$/i.test(p.value),
'<ie-function>': p => p.tokenType === Tokens.IE_FUNCTION, //eslint-disable-line no-use-before-define '<ie-function>': p => p.tokenType === Tokens.IE_FUNCTION, //eslint-disable-line no-use-before-define
'<image>': '<uri> | <gradient> | cross-fade()', '<image>': '<uri> | <gradient> | cross-fade()',
'<inflexible-breadth>': '<len-pct> | min-content | max-content | auto', '<inflexible-breadth>': '<len-pct> | min-content | max-content | auto',
@ -802,7 +801,7 @@ self.parserlib = (() => {
p.expr.parts.every(VTSimple['<ident-for-grid>'], VTSimple) p.expr.parts.every(VTSimple['<ident-for-grid>'], VTSimple)
), ),
//eslint-disable-next-line no-use-before-define //eslint-disable-next-line no-use-before-define
'<named-color>': p => p.text in Colors || ColorsLC.has(lower(p.text)), '<named-color>': p => rxColors.test(p.text),
'<number>': p => p.type === 'number' || p.isCalc, '<number>': p => p.type === 'number' || p.isCalc,
'<num0+>': p => '<num0+>': p =>
p.value >= 0 && p.type === 'number' || p.isCalc, p.value >= 0 && p.type === 'number' || p.isCalc,
@ -830,9 +829,9 @@ self.parserlib = (() => {
'<time>': p => p.type === 'time', '<time>': p => p.type === 'time',
'<track-breadth>': '<len-pct> | <flex> | min-content | max-content | auto', '<track-breadth>': '<len-pct> | <flex> | min-content | max-content | auto',
'<unicode-range>': p => /^U\+[0-9a-f?]{1,6}(-[0-9a-f?]{1,6})?\s*$/i.test(p), '<unicode-range>': p => /^U\+[0-9a-f?]{1,6}(-[0-9a-f?]{1,6})?\s*$/i.test(p),
'<unit>': p => p.text === '%' || p in UNITS || lower(p) in UNITS, '<unit>': ({text: t}) => t === '%' || t in UNITS || t.toLowerCase() in UNITS,
'<uri>': p => p.type === 'uri', '<uri>': p => p.type === 'uri',
'<width>': p => vtIsLength(p) || vtIsPct(p) || lowerCmp(p.text, 'auto'), '<width>': p => /^(0|auto)$/i.test(p.text) || vtIsLength(p) || vtIsPct(p),
'<xywh>': 'xywh( <len-pct>{2} <len-pct0+>{2} <border-radius-round>? )', '<xywh>': 'xywh( <len-pct>{2} <len-pct0+>{2} <border-radius-round>? )',
}; };
@ -1215,7 +1214,7 @@ self.parserlib = (() => {
WindowFrame: '', WindowFrame: '',
WindowText: '', WindowText: '',
}); });
const ColorsLC = new Set(Object.keys(Colors).map(lower)); const rxColors = new RegExp(`^(${Object.keys(Colors).join('|')})$`, 'i');
//#endregion //#endregion
//#region Tokens //#region Tokens
@ -2017,7 +2016,7 @@ self.parserlib = (() => {
} }
get isAttr() { get isAttr() {
let res = this._isAttr; let res = this._isAttr;
if (res === 0) res = this._isAttr = lowerCmp(this.name, 'attr'); if (res === 0) res = this._isAttr = /^attr$/i.test(this.name);
return res; return res;
} }
get isCalc() { get isCalc() {
@ -2031,8 +2030,9 @@ self.parserlib = (() => {
const pp = this.expr && this.expr.parts; const pp = this.expr && this.expr.parts;
res = this._isVar = pp && pp.length > 0 && ( res = this._isVar = pp && pp.length > 0 && (
(pp.length === 1 || pp[1].text === ',') && ( (pp.length === 1 || pp[1].text === ',') && (
pp[0].type === 'custom-property' && lowerCmp(this.name, 'var') || pp[0].type === 'custom-property' && /^var$/i.test(this.name) ||
pp[0].type === 'identifier' && lowerCmp(this.name, 'env'))); pp[0].type === 'identifier' && /^env$/i.test(this.name)
));
} }
return res; return res;
} }
@ -2045,7 +2045,8 @@ self.parserlib = (() => {
* @param {SyntaxUnit|parserlib.Token} token * @param {SyntaxUnit|parserlib.Token} token
* @returns {SyntaxUnit} * @returns {SyntaxUnit}
*/ */
static addFuncInfo(unit, {expr, name} = unit) { static addFuncInfo(unit, token = unit) {
const {expr, name} = token;
const isColor = expr && expr.parts && /^((rgb|hsl)a?|hwb)$/i.test(name); const isColor = expr && expr.parts && /^((rgb|hsl)a?|hwb)$/i.test(name);
if (isColor) unit.type = 'color'; if (isColor) unit.type = 'color';
unit._isAttr = unit._isAttr =
@ -2288,7 +2289,7 @@ self.parserlib = (() => {
this.type = 'custom-property'; this.type = 'custom-property';
this.value = value; this.value = value;
} else { } else {
const namedColor = Colors[value] || Colors[lower(value)]; const namedColor = Colors[value] || Colors[value.toLowerCase()];
this.type = namedColor ? 'color' : 'identifier'; this.type = namedColor ? 'color' : 'identifier';
this.value = namedColor || value; this.value = namedColor || value;
} }
@ -2433,7 +2434,7 @@ self.parserlib = (() => {
} }
if ((text || part.text) === arg || if ((text || part.text) === arg ||
(text || part.text).length >= arg.length && (text || part.text).length >= arg.length &&
lowerCmp(arg, text || (text = rxVendorPrefix.test(part.text) ? RegExp.$2 : part.text))) { lowerCmp(arg, text || (text = part.text.match(rxVendorPrefix)[2]))) {
return true; return true;
} }
} }
@ -2456,8 +2457,8 @@ self.parserlib = (() => {
} }
return; return;
} }
const prop = lower(name); const prop = name.toLowerCase();
const spec = Props[prop] || rxVendorPrefix.test(prop) && Props[RegExp.$2]; const spec = Props[prop.match(rxVendorPrefix)[2]];
if (typeof spec === 'number' || !spec && prop.startsWith('-')) { if (typeof spec === 'number' || !spec && prop.startsWith('-')) {
return; return;
} }
@ -2828,12 +2829,7 @@ self.parserlib = (() => {
const func = /[-hniw]/i.test(b) && const func = /[-hniw]/i.test(b) &&
reader.readMatch(/(has|not|is|where|(-(moz|webkit)-)?any)\(/iy); reader.readMatch(/(has|not|is|where|(-(moz|webkit)-)?any)\(/iy);
if (func) { if (func) {
const first = b.toLowerCase(); tok.type = Tokens[func.match(rxVendorPrefix)[2].slice(0, -1).toUpperCase()];
tok.type =
first === 'h' ? Tokens.HAS :
first === 'n' ? Tokens.NOT :
first === 'i' ? Tokens.IS :
first === 'w' ? Tokens.WHERE : Tokens.ANY;
tok.value += func; tok.value += func;
} else { } else {
tok.type = Tokens.COLON; tok.type = Tokens.COLON;
@ -2869,7 +2865,7 @@ self.parserlib = (() => {
atRuleToken(first, token) { atRuleToken(first, token) {
this._reader.mark(); this._reader.mark();
let rule = first + this.readName(); let rule = first + this.readName();
let tt = Tokens.type(lower(rule)); let tt = Tokens.type(rule.toLowerCase());
// if it's not valid, use the first character only and reset the reader // if it's not valid, use the first character only and reset the reader
if (tt === Tokens.CHAR || tt === Tokens.UNKNOWN) { if (tt === Tokens.CHAR || tt === Tokens.UNKNOWN) {
if (rule.length > 1) { if (rule.length > 1) {
@ -2950,7 +2946,7 @@ self.parserlib = (() => {
const c = reader.peek(); const c = reader.peek();
if (rxIdentStart.test(c)) { if (rxIdentStart.test(c)) {
units = this.readName(reader.read()); units = this.readName(reader.read());
type = UNITS[units] || UNITS[lower(units)]; type = UNITS[units] || UNITS[units.toLowerCase()];
tt = type && Tokens[type.toUpperCase()] || tt = type && Tokens[type.toUpperCase()] ||
type === 'frequency' && Tokens.FREQ || type === 'frequency' && Tokens.FREQ ||
Tokens.DIMENSION; Tokens.DIMENSION;
@ -3675,7 +3671,7 @@ self.parserlib = (() => {
this._ws(); this._ws();
const {type, value} = stream.LT(1); const {type, value} = stream.LT(1);
if (type === Tokens.IDENT) { if (type === Tokens.IDENT) {
if (lowerCmp(value, 'not')) { if (/^not$/i.test(value)) {
this._supportsCondition(); this._supportsCondition();
stream.mustMatch(Tokens.RPAREN); stream.mustMatch(Tokens.RPAREN);
} else { } else {
@ -3754,7 +3750,7 @@ self.parserlib = (() => {
this._ws(); this._ws();
const c = stream.match(Tokens.IDENT).value; const c = stream.match(Tokens.IDENT).value;
if (c) { if (c) {
if (lowerCmp(c, 'and') || !type && lowerCmp(c, 'or')) { if (/^and$/i.test(c) || !type && /^or$/i.test(c)) {
this._ws(); this._ws();
expressions.push(this._mediaExpression()); expressions.push(this._mediaExpression());
} else { } else {
@ -3797,7 +3793,7 @@ self.parserlib = (() => {
const stream = this._tokenStream; const stream = this._tokenStream;
this._ws(); this._ws();
const id = stream.match(Tokens.IDENT).value || null; const id = stream.match(Tokens.IDENT).value || null;
if (id && lowerCmp(id, 'auto')) { if (id && /^auto$/i.test(id)) {
stream.throwUnexpected(); stream.throwUnexpected();
} }
const pseudo = stream.match(Tokens.COLON) const pseudo = stream.match(Tokens.COLON)
@ -4035,8 +4031,11 @@ self.parserlib = (() => {
const start = stream.LT(1); const start = stream.LT(1);
const modifiers = []; const modifiers = [];
const seq = []; const seq = [];
const ns = this._namespacePrefix(start.type); const ns = this._namespacePrefix(start) || '';
const elementName = this._typeSelector(ns) || this._universal(ns); const next = ns ? stream.LT(1) : start;
const elementName = (next.value === '*' || next.type === Tokens.IDENT)
? this._typeSelector(ns, stream.get())
: '';
if (elementName) { if (elementName) {
seq.push(elementName); seq.push(elementName);
} else if (ns) { } else if (ns) {
@ -4054,21 +4053,9 @@ self.parserlib = (() => {
return text && new SelectorPart(elementName, modifiers, text, start); return text && new SelectorPart(elementName, modifiers, text, start);
} }
_typeSelector(ns) { _typeSelector(ns, token) {
const stream = this._tokenStream; const name = new SelectorSubPart(ns + token.value, 'elementName', token);
const nsSupplied = ns !== undefined; name.col -= ns.length;
if (!nsSupplied) ns = this._namespacePrefix();
const name = stream.match(Tokens.IDENT) &&
new SelectorSubPart(stream._token.value, 'elementName', stream._token);
if (!name) {
if (!nsSupplied && ns && ns.length > 0) stream.unget();
if (!nsSupplied && ns && ns.length > 1) stream.unget();
return null;
}
if (ns) {
name.text = ns + name.text;
name.col -= ns.length;
}
return name; return name;
} }
@ -4083,17 +4070,12 @@ self.parserlib = (() => {
_namespacePrefix(next) { _namespacePrefix(next) {
const stream = this._tokenStream; const stream = this._tokenStream;
if (!next) next = stream.LA(1); const v = (next || (next = stream.LT(1))).value;
return next === Tokens.PIPE ? '|' : return v === '|' ? v :
(next === Tokens.IDENT || next === Tokens.STAR) && stream.LA(2) === Tokens.PIPE (v === '*' || next.type === Tokens.IDENT) && stream.LT(2).value === '|'
? stream.get().value + stream.get().value ? stream.get().value + stream.get().value
: null; : null;
} }
_universal(ns = this._namespacePrefix()) {
return `${ns || ''}${this._tokenStream.match(Tokens.STAR).value || ''}` || null;
}
_attrib(start) { _attrib(start) {
const stream = this._tokenStream; const stream = this._tokenStream;
const value = [ const value = [
@ -4165,7 +4147,7 @@ self.parserlib = (() => {
(args = this._selectorsGroup(start.type === Tokens.HAS)) + (args = this._selectorsGroup(start.type === Tokens.HAS)) +
this._ws() + this._ws() +
this._tokenStream.mustMatch(Tokens.RPAREN).value; this._tokenStream.mustMatch(Tokens.RPAREN).value;
const type = lower(Tokens.name(start.type)); const type = Tokens.name(start.type).toLowerCase();
return Object.assign(new SelectorSubPart(value, type, start), {args}); return Object.assign(new SelectorSubPart(value, type, start), {args});
} }
@ -4311,7 +4293,7 @@ self.parserlib = (() => {
const start = stream._token; const start = stream._token;
const name = start.value.slice(0, -1); const name = start.value.slice(0, -1);
this._ws(); this._ws();
const expr = this._expr(lower(name)); const expr = this._expr(name.toLowerCase());
const ieFilter = this.options.ieFilters && stream.peek() === Tokens.EQUALS ? const ieFilter = this.options.ieFilters && stream.peek() === Tokens.EQUALS ?
this._functionIeFilter() : ''; this._functionIeFilter() : '';
const text = name + '(' + (expr || '') + ieFilter + ')'; const text = name + '(' + (expr || '') + ieFilter + ')';
@ -4320,11 +4302,11 @@ self.parserlib = (() => {
if (asText) { if (asText) {
return text; return text;
} }
const m = rxVendorPrefix.exec(name) || []; const m = rxVendorPrefix.exec(name);
return SyntaxUnit.addFuncInfo( return SyntaxUnit.addFuncInfo(
new SyntaxUnit(text, start, 'function', { new SyntaxUnit(text, start, 'function', {
expr, expr,
name: m[2] || name, name: m[2],
prefix: m[1] || '', prefix: m[1] || '',
tokenType: Tokens.FUNCTION, tokenType: Tokens.FUNCTION,
})); }));
@ -4397,7 +4379,7 @@ self.parserlib = (() => {
_keyframes(start) { _keyframes(start) {
const stream = this._tokenStream; const stream = this._tokenStream;
const prefix = rxVendorPrefix.test(start.value) ? RegExp.$1 : ''; const prefix = start.value.match(rxVendorPrefix)[1] || '';
const name = SyntaxUnit.fromToken(stream.mustMatch(TT.identString)); const name = SyntaxUnit.fromToken(stream.mustMatch(TT.identString));
stream.mustMatch(Tokens.LBRACE); stream.mustMatch(Tokens.LBRACE);
this.fire({type: 'startkeyframes', name, prefix}, start); this.fire({type: 'startkeyframes', name, prefix}, start);
@ -4677,22 +4659,13 @@ self.parserlib = (() => {
/^:(first-(letter|line)|before|after)$/i.test(pseudo); /^:(first-(letter|line)|before|after)$/i.test(pseudo);
} }
function lower(text) {
if (typeof text !== 'string') text = `${text}`;
let result = lowercaseCache.get(text);
if (result) return result;
result = text.toLowerCase();
lowercaseCache.set(text, result);
return result;
}
function lowerCmp(a, b) { function lowerCmp(a, b) {
return a.length === b.length && (a === b || lower(a) === lower(b)); return a.length === b.length && (a === b || a.toLowerCase() === b.toLowerCase());
} }
/** @this {String} */ /** @this {String} */
function lowerCmpThis(a) { function lowerCmpThis(a) {
return a.length === this.length && (a === this || lower(a) === lower(this)); return a.length === this.length && (a === this || a.toLowerCase() === this.toLowerCase());
} }
function parseString(str) { function parseString(str) {
@ -4746,7 +4719,6 @@ self.parserlib = (() => {
TokenStreamBase, TokenStreamBase,
fastJoin, fastJoin,
isPseudoElement, isPseudoElement,
lower,
rxVendorPrefix, rxVendorPrefix,
describeProp: vtExplode, describeProp: vtExplode,
}, },