parserlib: reuse global keywords
This commit is contained in:
parent
9d6542a39d
commit
8e36e0277f
|
@ -16,17 +16,11 @@
|
||||||
const rxVAR = /(^|[^-.\w\u0080-\uFFFF])var\(/iyu;
|
const rxVAR = /(^|[^-.\w\u0080-\uFFFF])var\(/iyu;
|
||||||
const rxCONSUME = /([-\w]*\s*:\s?)?/yu;
|
const rxCONSUME = /([-\w]*\s*:\s?)?/yu;
|
||||||
const cssMime = CodeMirror.mimeModes['text/css'];
|
const cssMime = CodeMirror.mimeModes['text/css'];
|
||||||
const cssGlobalValues = [
|
|
||||||
'inherit',
|
|
||||||
'initial',
|
|
||||||
'revert',
|
|
||||||
'unset',
|
|
||||||
];
|
|
||||||
const docFuncs = addSuffix(cssMime.documentTypes, '(');
|
const docFuncs = addSuffix(cssMime.documentTypes, '(');
|
||||||
const {tokenHooks} = cssMime;
|
const {tokenHooks} = cssMime;
|
||||||
const originalCommentHook = tokenHooks['/'];
|
const originalCommentHook = tokenHooks['/'];
|
||||||
const originalHelper = CodeMirror.hint.css || (() => {});
|
const originalHelper = CodeMirror.hint.css || (() => {});
|
||||||
let cssMedia, cssProps, cssPropsValues;
|
let cssMedia, cssProps, cssValues;
|
||||||
|
|
||||||
const AOT_ID = 'autocompleteOnTyping';
|
const AOT_ID = 'autocompleteOnTyping';
|
||||||
const AOT_PREF_ID = 'editor.' + AOT_ID;
|
const AOT_PREF_ID = 'editor.' + AOT_ID;
|
||||||
|
@ -148,8 +142,8 @@
|
||||||
leftLC = leftLC.replace(/^[^\w\s]\s*/, '');
|
leftLC = leftLC.replace(/^[^\w\s]\s*/, '');
|
||||||
}
|
}
|
||||||
if (prop.startsWith('--')) prop = 'color'; // assuming 90% of variables are colors
|
if (prop.startsWith('--')) prop = 'color'; // assuming 90% of variables are colors
|
||||||
if (!cssPropsValues) cssPropsValues = await linterMan.worker.getCssPropsValues();
|
if (!cssValues) cssValues = await linterMan.worker.getCssPropsValues();
|
||||||
list = [...new Set([...cssPropsValues[prop] || [], ...cssGlobalValues])];
|
list = [...new Set([...cssValues.own[prop] || [], ...cssValues.global])];
|
||||||
end = prev + execAt(/(\s*[-a-z(]+)?/y, prev, text)[0].length;
|
end = prev + execAt(/(\s*[-a-z(]+)?/y, prev, text)[0].length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,10 @@
|
||||||
|
|
||||||
getCssPropsValues() {
|
getCssPropsValues() {
|
||||||
require(['/js/csslint/parserlib']); /* global parserlib */
|
require(['/js/csslint/parserlib']); /* global parserlib */
|
||||||
const {css: {Colors, Properties}, util: {describeProp}} = parserlib;
|
const {
|
||||||
|
css: {Colors, GlobalKeywords, Properties},
|
||||||
|
util: {describeProp},
|
||||||
|
} = parserlib;
|
||||||
const namedColors = Object.keys(Colors);
|
const namedColors = Object.keys(Colors);
|
||||||
const rxNonWord = /(?:<.+?>|[^-\w<(]+\d*)+/g;
|
const rxNonWord = /(?:<.+?>|[^-\w<(]+\d*)+/g;
|
||||||
const res = {};
|
const res = {};
|
||||||
|
@ -41,7 +44,7 @@
|
||||||
if (uniq.length) res[k] = uniq;
|
if (uniq.length) res[k] = uniq;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res;
|
return {own: res, global: GlobalKeywords};
|
||||||
},
|
},
|
||||||
|
|
||||||
getRules(linter) {
|
getRules(linter) {
|
||||||
|
|
|
@ -30,12 +30,18 @@ self.parserlib = (() => {
|
||||||
|
|
||||||
//#region Properties
|
//#region Properties
|
||||||
|
|
||||||
|
// Global keywords that can be set for any property are conveniently listed in `all` prop:
|
||||||
|
// https://drafts.csswg.org/css-cascade/#all-shorthand
|
||||||
|
const GlobalKeywords = ['initial', 'inherit', 'revert', 'unset'];
|
||||||
|
const isGlobalKeyword = RegExp.prototype.test.bind(
|
||||||
|
new RegExp(`^(${GlobalKeywords.join('|')})$`, 'i'));
|
||||||
|
|
||||||
const Properties = {
|
const Properties = {
|
||||||
'accent-color': 'auto | <color>',
|
'accent-color': 'auto | <color>',
|
||||||
'align-items': 'normal | stretch | <baseline-position> | [ <overflow-position>? <self-position> ]',
|
'align-items': 'normal | stretch | <baseline-position> | [ <overflow-position>? <self-position> ]',
|
||||||
'align-content': '<align-content>',
|
'align-content': '<align-content>',
|
||||||
'align-self': '<align-self>',
|
'align-self': '<align-self>',
|
||||||
'all': 'initial | inherit | revert | unset',
|
'all': GlobalKeywords.join(' | '),
|
||||||
'alignment-adjust': 'auto | baseline | before-edge | text-before-edge | middle | central | ' +
|
'alignment-adjust': 'auto | baseline | before-edge | text-before-edge | middle | central | ' +
|
||||||
'after-edge | text-after-edge | ideographic | alphabetic | hanging | ' +
|
'after-edge | text-after-edge | ideographic | alphabetic | hanging | ' +
|
||||||
'mathematical | <length-pct>',
|
'mathematical | <length-pct>',
|
||||||
|
@ -702,8 +708,8 @@ self.parserlib = (() => {
|
||||||
const VTSimple = {
|
const VTSimple = {
|
||||||
'<absolute-size>': 'xx-small | x-small | small | medium | large | x-large | xx-large',
|
'<absolute-size>': 'xx-small | x-small | small | medium | large | x-large | xx-large',
|
||||||
'<animateable-feature>': 'scroll-position | contents | <animateable-feature-name>',
|
'<animateable-feature>': 'scroll-position | contents | <animateable-feature-name>',
|
||||||
'<animateable-feature-name>': p => vtIsIdent(p) &&
|
'<animateable-feature-name>': p => vtIsIdent(p) && !isGlobalKeyword(p) &&
|
||||||
!/^(unset|initial|inherit|will-change|auto|scroll-position|contents)$/i.test(p),
|
!/^(will-change|auto|scroll-position|contents)$/i.test(p),
|
||||||
'<angle>': p => p.type === 'angle' || p.isCalc,
|
'<angle>': p => p.type === 'angle' || p.isCalc,
|
||||||
'<angle-or-0>': p => p.text === '0' || p.type === 'angle' || p.isCalc,
|
'<angle-or-0>': p => p.text === '0' || p.type === 'angle' || p.isCalc,
|
||||||
'<attr>': vtIsAttr,
|
'<attr>': vtIsAttr,
|
||||||
|
@ -752,8 +758,8 @@ self.parserlib = (() => {
|
||||||
'<hex-color>': p => p.tokenType === Tokens.HASH, //eslint-disable-line no-use-before-define
|
'<hex-color>': p => p.tokenType === Tokens.HASH, //eslint-disable-line no-use-before-define
|
||||||
'<icccolor>': 'cielab() | cielch() | cielchab() | icc-color() | icc-named-color()',
|
'<icccolor>': 'cielab() | cielch() | cielchab() | icc-color() | icc-named-color()',
|
||||||
'<ident>': vtIsIdent,
|
'<ident>': vtIsIdent,
|
||||||
'<ident-for-grid>': p => vtIsIdent(p) &&
|
'<ident-for-grid>': p => vtIsIdent(p) && !isGlobalKeyword(p.value) &&
|
||||||
!/^(span|auto|initial|inherit|unset|default)$/i.test(p.value),
|
!/^(span|auto|default)$/i.test(p.value),
|
||||||
'<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) && !lowerCmp(p.value, 'none'),
|
||||||
'<image>': '<uri> | <gradient> | cross-fade()',
|
'<image>': '<uri> | <gradient> | cross-fade()',
|
||||||
|
@ -793,8 +799,8 @@ self.parserlib = (() => {
|
||||||
'<shape-box>': '<box> | margin-box',
|
'<shape-box>': '<box> | margin-box',
|
||||||
'<single-animation-direction>': 'normal | reverse | alternate | alternate-reverse',
|
'<single-animation-direction>': 'normal | reverse | alternate | alternate-reverse',
|
||||||
'<single-animation-fill-mode>': 'none | forwards | backwards | both',
|
'<single-animation-fill-mode>': 'none | forwards | backwards | both',
|
||||||
'<single-animation-name>': p => vtIsIdent(p) &&
|
'<single-animation-name>': p => vtIsIdent(p) && !isGlobalKeyword(p) &&
|
||||||
/^(?!(none|unset|initial|inherit)$)-?[a-z_][-a-z0-9_]+$/i.test(p),
|
/^-?[a-z_][-a-z0-9_]+$/i.test(p),
|
||||||
'<string>': p => p.type === 'string',
|
'<string>': p => p.type === 'string',
|
||||||
'<text-align>': 'start | end | left | right | center | justify | match-parent',
|
'<text-align>': 'start | end | left | right | center | justify | match-parent',
|
||||||
'<text-decoration-style>': 'solid | double | dotted | dashed | wavy',
|
'<text-decoration-style>': 'solid | double | dotted | dashed | wavy',
|
||||||
|
@ -2395,10 +2401,8 @@ self.parserlib = (() => {
|
||||||
|
|
||||||
const validationCache = new Map();
|
const validationCache = new Map();
|
||||||
|
|
||||||
function validateProperty(property, value) {
|
function validateProperty(name, property, value) {
|
||||||
// Global keywords that can be set for any property are conveniently listed in `all` prop:
|
if (isGlobalKeyword(value.parts[0])) {
|
||||||
// https://drafts.csswg.org/css-cascade/#all-shorthand
|
|
||||||
if (/^(inherit|initial|unset|revert)$/i.test(value.parts[0])) {
|
|
||||||
if (value.parts.length > 1) {
|
if (value.parts.length > 1) {
|
||||||
throwEndExpected(value.parts[1], true);
|
throwEndExpected(value.parts[1], true);
|
||||||
}
|
}
|
||||||
|
@ -2407,7 +2411,7 @@ self.parserlib = (() => {
|
||||||
if (hasVarParts(value)) {
|
if (hasVarParts(value)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const prop = lower(property);
|
const prop = lower(name);
|
||||||
let known = validationCache.get(prop);
|
let known = validationCache.get(prop);
|
||||||
if (known && known.has(value.text)) {
|
if (known && known.has(value.text)) {
|
||||||
return;
|
return;
|
||||||
|
@ -2417,7 +2421,7 @@ self.parserlib = (() => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!spec) {
|
if (!spec) {
|
||||||
throw new ValidationError(`Unknown property '${property}'.`, value);
|
throw new ValidationError(`Unknown property '${name}'.`, value);
|
||||||
}
|
}
|
||||||
// Property-specific validation.
|
// Property-specific validation.
|
||||||
const expr = new PropertyValueIterator(value);
|
const expr = new PropertyValueIterator(value);
|
||||||
|
@ -4066,7 +4070,7 @@ self.parserlib = (() => {
|
||||||
this.options.underscoreHack && property.hack === '_'
|
this.options.underscoreHack && property.hack === '_'
|
||||||
? property.text
|
? property.text
|
||||||
: property.toString();
|
: property.toString();
|
||||||
validateProperty(name, value);
|
validateProperty(name, property, value);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
if (!(ex instanceof ValidationError)) {
|
if (!(ex instanceof ValidationError)) {
|
||||||
ex.message = ex.stack;
|
ex.message = ex.stack;
|
||||||
|
@ -4650,14 +4654,15 @@ self.parserlib = (() => {
|
||||||
css: {
|
css: {
|
||||||
Colors,
|
Colors,
|
||||||
Combinator,
|
Combinator,
|
||||||
|
GlobalKeywords,
|
||||||
|
Matcher,
|
||||||
|
MediaFeature,
|
||||||
|
MediaQuery,
|
||||||
Parser,
|
Parser,
|
||||||
Properties,
|
Properties,
|
||||||
PropertyName,
|
PropertyName,
|
||||||
PropertyValue,
|
PropertyValue,
|
||||||
PropertyValuePart,
|
PropertyValuePart,
|
||||||
Matcher,
|
|
||||||
MediaFeature,
|
|
||||||
MediaQuery,
|
|
||||||
Selector,
|
Selector,
|
||||||
SelectorPart,
|
SelectorPart,
|
||||||
SelectorSubPart,
|
SelectorSubPart,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user