diff --git a/lib/reference/atKeywords.js b/lib/reference/atKeywords.js new file mode 100644 index 0000000000..70b7364cd7 --- /dev/null +++ b/lib/reference/atKeywords.js @@ -0,0 +1,55 @@ +'use strict'; + +const uniteSets = require('../utils/uniteSets.js'); + +// https://www.w3.org/TR/css-page-3/#syntax-page-selector +const pageMarginAtKeywords = new Set([ + 'top-left-corner', + 'top-left', + 'top-center', + 'top-right', + 'top-right-corner', + 'bottom-left-corner', + 'bottom-left', + 'bottom-center', + 'bottom-right', + 'bottom-right-corner', + 'left-top', + 'left-middle', + 'left-bottom', + 'right-top', + 'right-middle', + 'right-bottom', +]); + +// https://developer.mozilla.org/en/docs/Web/CSS/At-rule +const atKeywords = uniteSets(pageMarginAtKeywords, [ + 'annotation', + 'apply', + 'character-variant', + 'charset', + 'counter-style', + 'custom-media', + 'custom-selector', + 'document', + 'font-face', + 'font-feature-values', + 'import', + 'keyframes', + 'layer', + 'media', + 'namespace', + 'nest', + 'ornaments', + 'page', + 'property', + 'styleset', + 'stylistic', + 'supports', + 'swash', + 'viewport', +]); + +module.exports = { + atKeywords, +}; diff --git a/lib/reference/functions.js b/lib/reference/functions.js new file mode 100644 index 0000000000..be84110721 --- /dev/null +++ b/lib/reference/functions.js @@ -0,0 +1,22 @@ +'use strict'; + +const camelCaseFunctions = new Set([ + 'translateX', + 'translateY', + 'translateZ', + 'scaleX', + 'scaleY', + 'scaleZ', + 'rotateX', + 'rotateY', + 'rotateZ', + 'skewX', + 'skewY', +]); + +const mathFunctions = new Set(['calc', 'clamp', 'max', 'min']); + +module.exports = { + camelCaseFunctions, + mathFunctions, +}; diff --git a/lib/reference/keywordSets.js b/lib/reference/keywordSets.js deleted file mode 100644 index b8f0d9619e..0000000000 --- a/lib/reference/keywordSets.js +++ /dev/null @@ -1,829 +0,0 @@ -'use strict'; - -const htmlTags = require('html-tags'); - -const keywordSets = {}; - -keywordSets.nonLengthUnits = new Set([ - // Relative length units - '%', - // Time length units - 's', - 'ms', - // Angle - 'deg', - 'grad', - 'turn', - 'rad', - // Frequency - 'Hz', - 'kHz', - // Resolution - 'dpi', - 'dpcm', - 'dppx', -]); - -keywordSets.lengthUnits = new Set([ - // Relative length units - 'em', - 'ex', - 'ch', - 'rem', - 'rlh', - 'lh', - // Viewport-percentage lengths - 'dvh', - 'dvmax', - 'dvmin', - 'dvw', - 'lvh', - 'lvmax', - 'lvmin', - 'lvw', - 'svh', - 'svmax', - 'svmin', - 'svw', - 'vh', - 'vw', - 'vmin', - 'vmax', - 'vm', - // Absolute length units - 'px', - 'mm', - 'cm', - 'in', - 'pt', - 'pc', - 'q', - 'mozmm', - // Flexible length units - 'fr', -]); - -keywordSets.units = uniteSets(keywordSets.nonLengthUnits, keywordSets.lengthUnits); - -keywordSets.camelCaseFunctionNames = new Set([ - 'translateX', - 'translateY', - 'translateZ', - 'scaleX', - 'scaleY', - 'scaleZ', - 'rotateX', - 'rotateY', - 'rotateZ', - 'skewX', - 'skewY', -]); - -keywordSets.basicKeywords = new Set(['initial', 'inherit', 'revert', 'revert-layer', 'unset']); - -keywordSets.systemFontValues = uniteSets(keywordSets.basicKeywords, [ - 'caption', - 'icon', - 'menu', - 'message-box', - 'small-caption', - 'status-bar', -]); - -keywordSets.fontFamilyKeywords = uniteSets(keywordSets.basicKeywords, [ - 'serif', - 'sans-serif', - 'cursive', - 'fantasy', - 'monospace', - 'system-ui', - 'ui-serif', - 'ui-sans-serif', - 'ui-monospace', - 'ui-rounded', -]); - -keywordSets.fontWeightRelativeKeywords = new Set(['bolder', 'lighter']); - -keywordSets.fontWeightAbsoluteKeywords = new Set(['bold']); - -keywordSets.fontWeightNumericKeywords = new Set([ - '100', - '200', - '300', - '400', - '500', - '600', - '700', - '800', - '900', -]); - -keywordSets.fontWeightKeywords = uniteSets( - keywordSets.basicKeywords, - keywordSets.fontWeightRelativeKeywords, - keywordSets.fontWeightAbsoluteKeywords, - keywordSets.fontWeightNumericKeywords, -); - -keywordSets.animationNameKeywords = uniteSets(keywordSets.basicKeywords, ['none']); - -keywordSets.animationTimingFunctionKeywords = uniteSets(keywordSets.basicKeywords, [ - 'linear', - 'ease', - 'ease-in', - 'ease-in-out', - 'ease-out', - 'step-start', - 'step-end', - 'steps', - 'cubic-bezier', -]); - -keywordSets.animationIterationCountKeywords = new Set(['infinite']); - -keywordSets.animationDirectionKeywords = uniteSets(keywordSets.basicKeywords, [ - 'normal', - 'reverse', - 'alternate', - 'alternate-reverse', -]); - -keywordSets.animationFillModeKeywords = new Set(['none', 'forwards', 'backwards', 'both']); - -keywordSets.animationPlayStateKeywords = uniteSets(keywordSets.basicKeywords, [ - 'running', - 'paused', -]); - -// cf. https://developer.mozilla.org/en-US/docs/Web/CSS/animation -keywordSets.animationShorthandKeywords = uniteSets( - keywordSets.basicKeywords, - keywordSets.animationNameKeywords, - keywordSets.animationTimingFunctionKeywords, - keywordSets.animationIterationCountKeywords, - keywordSets.animationDirectionKeywords, - keywordSets.animationFillModeKeywords, - keywordSets.animationPlayStateKeywords, -); - -// These are the ones that can have single-colon notation -keywordSets.levelOneAndTwoPseudoElements = new Set([ - 'before', - 'after', - 'first-line', - 'first-letter', -]); - -keywordSets.levelThreeAndUpPseudoElements = new Set([ - 'before', - 'after', - 'first-line', - 'first-letter', - // These are the ones that require double-colon notation - 'backdrop', - 'content', - 'cue', - 'file-selector-button', - 'grammar-error', - 'marker', - 'placeholder', - 'selection', - 'shadow', - 'slotted', - 'spelling-error', - 'target-text', -]); - -keywordSets.shadowTreePseudoElements = new Set(['part']); - -keywordSets.webkitScrollbarPseudoElements = new Set([ - '-webkit-resizer', - '-webkit-scrollbar', - '-webkit-scrollbar-button', - '-webkit-scrollbar-corner', - '-webkit-scrollbar-thumb', - '-webkit-scrollbar-track', - '-webkit-scrollbar-track-piece', -]); - -keywordSets.vendorSpecificPseudoElements = new Set([ - '-moz-focus-inner', - '-moz-focus-outer', - '-moz-list-bullet', - '-moz-meter-bar', - '-moz-placeholder', - '-moz-progress-bar', - '-moz-range-progress', - '-moz-range-thumb', - '-moz-range-track', - '-ms-browse', - '-ms-check', - '-ms-clear', - '-ms-expand', - '-ms-fill', - '-ms-fill-lower', - '-ms-fill-upper', - '-ms-reveal', - '-ms-thumb', - '-ms-ticks-after', - '-ms-ticks-before', - '-ms-tooltip', - '-ms-track', - '-ms-value', - '-webkit-color-swatch', - '-webkit-color-swatch-wrapper', - '-webkit-calendar-picker-indicator', - '-webkit-clear-button', - '-webkit-date-and-time-value', - '-webkit-datetime-edit', - '-webkit-datetime-edit-ampm-field', - '-webkit-datetime-edit-day-field', - '-webkit-datetime-edit-fields-wrapper', - '-webkit-datetime-edit-hour-field', - '-webkit-datetime-edit-millisecond-field', - '-webkit-datetime-edit-minute-field', - '-webkit-datetime-edit-month-field', - '-webkit-datetime-edit-second-field', - '-webkit-datetime-edit-text', - '-webkit-datetime-edit-week-field', - '-webkit-datetime-edit-year-field', - '-webkit-details-marker', - '-webkit-distributed', - '-webkit-file-upload-button', - '-webkit-input-placeholder', - '-webkit-keygen-select', - '-webkit-meter-bar', - '-webkit-meter-even-less-good-value', - '-webkit-meter-inner-element', - '-webkit-meter-optimum-value', - '-webkit-meter-suboptimum-value', - '-webkit-progress-bar', - '-webkit-progress-inner-element', - '-webkit-progress-value', - '-webkit-search-cancel-button', - '-webkit-search-decoration', - '-webkit-search-results-button', - '-webkit-search-results-decoration', - '-webkit-slider-runnable-track', - '-webkit-slider-thumb', - '-webkit-textfield-decoration-container', - '-webkit-validation-bubble', - '-webkit-validation-bubble-arrow', - '-webkit-validation-bubble-arrow-clipper', - '-webkit-validation-bubble-heading', - '-webkit-validation-bubble-message', - '-webkit-validation-bubble-text-block', - ...keywordSets.webkitScrollbarPseudoElements, -]); - -keywordSets.pseudoElements = uniteSets( - keywordSets.levelOneAndTwoPseudoElements, - keywordSets.levelThreeAndUpPseudoElements, - keywordSets.vendorSpecificPseudoElements, - keywordSets.shadowTreePseudoElements, -); - -keywordSets.aNPlusBNotationPseudoClasses = new Set([ - 'nth-column', - 'nth-last-column', - 'nth-last-of-type', - 'nth-of-type', -]); - -keywordSets.linguisticPseudoClasses = new Set(['dir', 'lang']); - -keywordSets.atRulePagePseudoClasses = new Set(['first', 'right', 'left', 'blank']); - -keywordSets.logicalCombinationsPseudoClasses = new Set(['has', 'is', 'matches', 'not', 'where']); - -keywordSets.aNPlusBOfSNotationPseudoClasses = new Set(['nth-child', 'nth-last-child']); - -keywordSets.otherPseudoClasses = new Set([ - 'active', - 'any-link', - 'autofill', - 'blank', - 'checked', - 'current', - 'default', - 'defined', - 'disabled', - 'empty', - 'enabled', - 'first-child', - 'first-of-type', - 'focus', - 'focus-within', - 'focus-visible', - 'fullscreen', - 'fullscreen-ancestor', - 'future', - 'host', - 'host-context', - 'hover', - 'indeterminate', - 'in-range', - 'invalid', - 'last-child', - 'last-of-type', - 'link', - 'only-child', - 'only-of-type', - 'optional', - 'out-of-range', - 'past', - 'placeholder-shown', - 'playing', - 'picture-in-picture', - 'paused', - 'read-only', - 'read-write', - 'required', - 'root', - 'scope', - 'state', - 'target', - 'unresolved', - 'user-invalid', - 'user-valid', - 'valid', - 'visited', - 'window-inactive', // for ::selection (chrome) -]); - -keywordSets.vendorSpecificPseudoClasses = new Set([ - '-khtml-drag', - '-moz-any', - '-moz-any-link', - '-moz-broken', - '-moz-drag-over', - '-moz-first-node', - '-moz-focusring', - '-moz-full-screen', - '-moz-full-screen-ancestor', - '-moz-last-node', - '-moz-loading', - '-moz-meter-optimum', - '-moz-meter-sub-optimum', - '-moz-meter-sub-sub-optimum', - '-moz-placeholder', - '-moz-submit-invalid', - '-moz-suppressed', - '-moz-ui-invalid', - '-moz-ui-valid', - '-moz-user-disabled', - '-moz-window-inactive', - '-ms-fullscreen', - '-ms-input-placeholder', - '-webkit-drag', - '-webkit-any', - '-webkit-any-link', - '-webkit-autofill', - '-webkit-full-screen', - '-webkit-full-screen-ancestor', -]); - -// https://webkit.org/blog/363/styling-scrollbars/ -keywordSets.webkitScrollbarPseudoClasses = new Set([ - 'horizontal', - 'vertical', - 'decrement', - 'increment', - 'start', - 'end', - 'double-button', - 'single-button', - 'no-button', - 'corner-present', - 'window-inactive', -]); - -keywordSets.pseudoClasses = uniteSets( - keywordSets.aNPlusBNotationPseudoClasses, - keywordSets.linguisticPseudoClasses, - keywordSets.logicalCombinationsPseudoClasses, - keywordSets.aNPlusBOfSNotationPseudoClasses, - keywordSets.otherPseudoClasses, - keywordSets.vendorSpecificPseudoClasses, -); - -keywordSets.shorthandTimeProperties = new Set(['transition', 'animation']); - -keywordSets.longhandTimeProperties = new Set([ - 'transition-duration', - 'transition-delay', - 'animation-duration', - 'animation-delay', -]); - -keywordSets.timeProperties = uniteSets( - keywordSets.shorthandTimeProperties, - keywordSets.longhandTimeProperties, -); - -keywordSets.camelCaseKeywords = new Set([ - 'optimizeSpeed', - 'optimizeQuality', - 'optimizeLegibility', - 'geometricPrecision', - 'currentColor', - 'crispEdges', - 'visiblePainted', - 'visibleFill', - 'visibleStroke', - 'sRGB', - 'linearRGB', -]); - -// https://developer.mozilla.org/docs/Web/CSS/counter-increment -keywordSets.counterIncrementKeywords = uniteSets(keywordSets.basicKeywords, ['none']); - -keywordSets.counterResetKeywords = uniteSets(keywordSets.basicKeywords, ['none']); - -keywordSets.gridRowKeywords = uniteSets(keywordSets.basicKeywords, ['auto', 'span']); - -keywordSets.gridColumnKeywords = uniteSets(keywordSets.basicKeywords, ['auto', 'span']); - -keywordSets.gridAreaKeywords = uniteSets(keywordSets.basicKeywords, ['auto', 'span']); - -// https://developer.mozilla.org/ru/docs/Web/CSS/list-style-type -keywordSets.listStyleTypeKeywords = uniteSets(keywordSets.basicKeywords, [ - 'none', - 'disc', - 'circle', - 'square', - 'decimal', - 'cjk-decimal', - 'decimal-leading-zero', - 'lower-roman', - 'upper-roman', - 'lower-greek', - 'lower-alpha', - 'lower-latin', - 'upper-alpha', - 'upper-latin', - 'arabic-indic', - 'armenian', - 'bengali', - 'cambodian', - 'cjk-earthly-branch', - 'cjk-ideographic', - 'devanagari', - 'ethiopic-numeric', - 'georgian', - 'gujarati', - 'gurmukhi', - 'hebrew', - 'hiragana', - 'hiragana-iroha', - 'japanese-formal', - 'japanese-informal', - 'kannada', - 'katakana', - 'katakana-iroha', - 'khmer', - 'korean-hangul-formal', - 'korean-hanja-formal', - 'korean-hanja-informal', - 'lao', - 'lower-armenian', - 'malayalam', - 'mongolian', - 'myanmar', - 'oriya', - 'persian', - 'simp-chinese-formal', - 'simp-chinese-informal', - 'tamil', - 'telugu', - 'thai', - 'tibetan', - 'trad-chinese-formal', - 'trad-chinese-informal', - 'upper-armenian', - 'disclosure-open', - 'disclosure-closed', - // Non-standard extensions (without prefixe) - 'ethiopic-halehame', - 'ethiopic-halehame-am', - 'ethiopic-halehame-ti-er', - 'ethiopic-halehame-ti-et', - 'hangul', - 'hangul-consonant', - 'urdu', -]); - -keywordSets.listStylePositionKeywords = uniteSets(keywordSets.basicKeywords, ['inside', 'outside']); - -keywordSets.listStyleImageKeywords = uniteSets(keywordSets.basicKeywords, ['none']); - -keywordSets.listStyleShorthandKeywords = uniteSets( - keywordSets.basicKeywords, - keywordSets.listStyleTypeKeywords, - keywordSets.listStylePositionKeywords, - keywordSets.listStyleImageKeywords, -); - -keywordSets.fontStyleKeywords = uniteSets(keywordSets.basicKeywords, [ - 'normal', - 'italic', - 'oblique', -]); - -keywordSets.fontVariantKeywords = uniteSets(keywordSets.basicKeywords, [ - 'normal', - 'none', - 'historical-forms', - 'none', - 'common-ligatures', - 'no-common-ligatures', - 'discretionary-ligatures', - 'no-discretionary-ligatures', - 'historical-ligatures', - 'no-historical-ligatures', - 'contextual', - 'no-contextual', - 'small-caps', - 'small-caps', - 'all-small-caps', - 'petite-caps', - 'all-petite-caps', - 'unicase', - 'titling-caps', - 'lining-nums', - 'oldstyle-nums', - 'proportional-nums', - 'tabular-nums', - 'diagonal-fractions', - 'stacked-fractions', - 'ordinal', - 'slashed-zero', - 'jis78', - 'jis83', - 'jis90', - 'jis04', - 'simplified', - 'traditional', - 'full-width', - 'proportional-width', - 'ruby', -]); - -keywordSets.fontStretchKeywords = uniteSets(keywordSets.basicKeywords, [ - 'semi-condensed', - 'condensed', - 'extra-condensed', - 'ultra-condensed', - 'semi-expanded', - 'expanded', - 'extra-expanded', - 'ultra-expanded', -]); - -keywordSets.fontSizeKeywords = uniteSets(keywordSets.basicKeywords, [ - 'xx-small', - 'x-small', - 'small', - 'medium', - 'large', - 'x-large', - 'xx-large', - 'larger', - 'smaller', -]); - -keywordSets.lineHeightKeywords = uniteSets(keywordSets.basicKeywords, ['normal']); - -keywordSets.fontShorthandKeywords = uniteSets( - keywordSets.basicKeywords, - keywordSets.fontStyleKeywords, - keywordSets.fontVariantKeywords, - keywordSets.fontWeightKeywords, - keywordSets.fontStretchKeywords, - keywordSets.fontSizeKeywords, - keywordSets.lineHeightKeywords, - keywordSets.fontFamilyKeywords, -); - -keywordSets.keyframeSelectorKeywords = new Set(['from', 'to']); - -// https://www.w3.org/TR/css-page-3/#syntax-page-selector -keywordSets.pageMarginAtRules = new Set([ - 'top-left-corner', - 'top-left', - 'top-center', - 'top-right', - 'top-right-corner', - 'bottom-left-corner', - 'bottom-left', - 'bottom-center', - 'bottom-right', - 'bottom-right-corner', - 'left-top', - 'left-middle', - 'left-bottom', - 'right-top', - 'right-middle', - 'right-bottom', -]); - -// https://developer.mozilla.org/en/docs/Web/CSS/At-rule -keywordSets.atRules = uniteSets(keywordSets.pageMarginAtRules, [ - 'annotation', - 'apply', - 'character-variant', - 'charset', - 'counter-style', - 'custom-media', - 'custom-selector', - 'document', - 'font-face', - 'font-feature-values', - 'import', - 'keyframes', - 'layer', - 'media', - 'namespace', - 'nest', - 'ornaments', - 'page', - 'property', - 'styleset', - 'stylistic', - 'supports', - 'swash', - 'viewport', -]); - -// https://drafts.csswg.org/mediaqueries/#descdef-media-update -keywordSets.deprecatedMediaFeatureNames = new Set([ - 'device-aspect-ratio', - 'device-height', - 'device-width', - 'max-device-aspect-ratio', - 'max-device-height', - 'max-device-width', - 'min-device-aspect-ratio', - 'min-device-height', - 'min-device-width', -]); - -// https://drafts.csswg.org/mediaqueries/#descdef-media-update -keywordSets.mediaFeatureNames = uniteSets(keywordSets.deprecatedMediaFeatureNames, [ - 'any-hover', - 'any-pointer', - 'aspect-ratio', - 'color', - 'color-gamut', - 'color-index', - 'display-mode', - 'dynamic-range', - 'forced-colors', - 'grid', - 'height', - 'hover', - 'inverted-colors', - 'light-level', - 'max-aspect-ratio', - 'max-color', - 'max-color-index', - 'max-height', - 'max-monochrome', - 'max-resolution', - 'max-width', - 'min-aspect-ratio', - 'min-color', - 'min-color-index', - 'min-height', - 'min-monochrome', - 'min-resolution', - 'min-width', - 'monochrome', - 'orientation', - 'overflow-block', - 'overflow-inline', - 'pointer', - 'prefers-color-scheme', - 'prefers-contrast', - 'prefers-reduced-motion', - 'prefers-reduced-transparency', - 'resolution', - 'scan', - 'scripting', - 'update', - 'video-dynamic-range', - 'width', -]); - -// https://www.w3.org/TR/CSS22/ui.html#system-colors -keywordSets.systemColors = new Set([ - 'activeborder', - 'activecaption', - 'appworkspace', - 'background', - 'buttonface', - 'buttonhighlight', - 'buttonshadow', - 'buttontext', - 'captiontext', - 'graytext', - 'highlight', - 'highlighttext', - 'inactiveborder', - 'inactivecaption', - 'inactivecaptiontext', - 'infobackground', - 'infotext', - 'menu', - 'menutext', - 'scrollbar', - 'threeddarkshadow', - 'threedface', - 'threedhighlight', - 'threedlightshadow', - 'threedshadow', - 'window', - 'windowframe', - 'windowtext', -]); - -// typecasting htmlTags to be more generic; see https://github.com/stylelint/stylelint/pull/6013 for discussion -/** @type {Set} */ -keywordSets.standardHtmlTags = new Set(htmlTags); - -// htmlTags includes only "standard" tags. So we augment it with older tags etc. -keywordSets.nonStandardHtmlTags = new Set([ - 'acronym', - 'applet', - 'basefont', - 'big', - 'blink', - 'center', - 'content', - 'dir', - 'font', - 'frame', - 'frameset', - 'hgroup', - 'isindex', - 'keygen', - 'listing', - 'marquee', - 'nobr', - 'noembed', - 'plaintext', - 'spacer', - 'strike', - 'tt', - 'xmp', -]); - -keywordSets.validMixedCaseSvgElements = new Set([ - 'altGlyph', - 'altGlyphDef', - 'altGlyphItem', - 'animateColor', - 'animateMotion', - 'animateTransform', - 'clipPath', - 'feBlend', - 'feColorMatrix', - 'feComponentTransfer', - 'feComposite', - 'feConvolveMatrix', - 'feDiffuseLighting', - 'feDisplacementMap', - 'feDistantLight', - 'feDropShadow', - 'feFlood', - 'feFuncA', - 'feFuncB', - 'feFuncG', - 'feFuncR', - 'feGaussianBlur', - 'feImage', - 'feMerge', - 'feMergeNode', - 'feMorphology', - 'feOffset', - 'fePointLight', - 'feSpecularLighting', - 'feSpotLight', - 'feTile', - 'feTurbulence', - 'foreignObject', - 'glyphRef', - 'linearGradient', - 'radialGradient', - 'textPath', -]); - -/** - * @param {(string[] | Set)[]} args - */ -function uniteSets(...args) { - return new Set([...args].reduce((result, set) => [...result, ...set], [])); -} - -module.exports = keywordSets; diff --git a/lib/reference/keywords.js b/lib/reference/keywords.js new file mode 100644 index 0000000000..ed68e9efa9 --- /dev/null +++ b/lib/reference/keywords.js @@ -0,0 +1,326 @@ +'use strict'; + +const uniteSets = require('../utils/uniteSets.js'); + +const basicKeywords = new Set(['initial', 'inherit', 'revert', 'revert-layer', 'unset']); + +const systemFontKeywords = uniteSets(basicKeywords, [ + 'caption', + 'icon', + 'menu', + 'message-box', + 'small-caption', + 'status-bar', +]); + +const fontFamilyKeywords = uniteSets(basicKeywords, [ + 'serif', + 'sans-serif', + 'cursive', + 'fantasy', + 'monospace', + 'system-ui', + 'ui-serif', + 'ui-sans-serif', + 'ui-monospace', + 'ui-rounded', +]); + +const fontWeightRelativeKeywords = new Set(['bolder', 'lighter']); + +const fontWeightAbsoluteKeywords = new Set(['bold']); + +const fontWeightNumericKeywords = new Set([ + '100', + '200', + '300', + '400', + '500', + '600', + '700', + '800', + '900', +]); + +const fontWeightKeywords = uniteSets( + basicKeywords, + fontWeightRelativeKeywords, + fontWeightAbsoluteKeywords, + fontWeightNumericKeywords, +); + +const fontStyleKeywords = uniteSets(basicKeywords, ['normal', 'italic', 'oblique']); + +const fontVariantKeywords = uniteSets(basicKeywords, [ + 'normal', + 'none', + 'historical-forms', + 'none', + 'common-ligatures', + 'no-common-ligatures', + 'discretionary-ligatures', + 'no-discretionary-ligatures', + 'historical-ligatures', + 'no-historical-ligatures', + 'contextual', + 'no-contextual', + 'small-caps', + 'small-caps', + 'all-small-caps', + 'petite-caps', + 'all-petite-caps', + 'unicase', + 'titling-caps', + 'lining-nums', + 'oldstyle-nums', + 'proportional-nums', + 'tabular-nums', + 'diagonal-fractions', + 'stacked-fractions', + 'ordinal', + 'slashed-zero', + 'jis78', + 'jis83', + 'jis90', + 'jis04', + 'simplified', + 'traditional', + 'full-width', + 'proportional-width', + 'ruby', +]); + +const fontStretchKeywords = uniteSets(basicKeywords, [ + 'semi-condensed', + 'condensed', + 'extra-condensed', + 'ultra-condensed', + 'semi-expanded', + 'expanded', + 'extra-expanded', + 'ultra-expanded', +]); + +const fontSizeKeywords = uniteSets(basicKeywords, [ + 'xx-small', + 'x-small', + 'small', + 'medium', + 'large', + 'x-large', + 'xx-large', + 'larger', + 'smaller', +]); + +const lineHeightKeywords = uniteSets(basicKeywords, ['normal']); + +const fontShorthandKeywords = uniteSets( + basicKeywords, + fontStyleKeywords, + fontVariantKeywords, + fontWeightKeywords, + fontStretchKeywords, + fontSizeKeywords, + lineHeightKeywords, + fontFamilyKeywords, +); + +const animationNameKeywords = uniteSets(basicKeywords, ['none']); + +const animationTimingFunctionKeywords = uniteSets(basicKeywords, [ + 'linear', + 'ease', + 'ease-in', + 'ease-in-out', + 'ease-out', + 'step-start', + 'step-end', + 'steps', + 'cubic-bezier', +]); + +const animationIterationCountKeywords = new Set(['infinite']); + +const animationDirectionKeywords = uniteSets(basicKeywords, [ + 'normal', + 'reverse', + 'alternate', + 'alternate-reverse', +]); + +const animationFillModeKeywords = new Set(['none', 'forwards', 'backwards', 'both']); + +const animationPlayStateKeywords = uniteSets(basicKeywords, ['running', 'paused']); + +// cf. https://developer.mozilla.org/en-US/docs/Web/CSS/animation +const animationShorthandKeywords = uniteSets( + basicKeywords, + animationNameKeywords, + animationTimingFunctionKeywords, + animationIterationCountKeywords, + animationDirectionKeywords, + animationFillModeKeywords, + animationPlayStateKeywords, +); + +const gridRowKeywords = uniteSets(basicKeywords, ['auto', 'span']); + +const gridColumnKeywords = uniteSets(basicKeywords, ['auto', 'span']); + +const gridAreaKeywords = uniteSets(basicKeywords, ['auto', 'span']); + +// https://developer.mozilla.org/docs/Web/CSS/counter-increment +const counterIncrementKeywords = uniteSets(basicKeywords, ['none']); + +const counterResetKeywords = uniteSets(basicKeywords, ['none']); + +// https://developer.mozilla.org/ru/docs/Web/CSS/list-style-type +const listStyleTypeKeywords = uniteSets(basicKeywords, [ + 'none', + 'disc', + 'circle', + 'square', + 'decimal', + 'cjk-decimal', + 'decimal-leading-zero', + 'lower-roman', + 'upper-roman', + 'lower-greek', + 'lower-alpha', + 'lower-latin', + 'upper-alpha', + 'upper-latin', + 'arabic-indic', + 'armenian', + 'bengali', + 'cambodian', + 'cjk-earthly-branch', + 'cjk-ideographic', + 'devanagari', + 'ethiopic-numeric', + 'georgian', + 'gujarati', + 'gurmukhi', + 'hebrew', + 'hiragana', + 'hiragana-iroha', + 'japanese-formal', + 'japanese-informal', + 'kannada', + 'katakana', + 'katakana-iroha', + 'khmer', + 'korean-hangul-formal', + 'korean-hanja-formal', + 'korean-hanja-informal', + 'lao', + 'lower-armenian', + 'malayalam', + 'mongolian', + 'myanmar', + 'oriya', + 'persian', + 'simp-chinese-formal', + 'simp-chinese-informal', + 'tamil', + 'telugu', + 'thai', + 'tibetan', + 'trad-chinese-formal', + 'trad-chinese-informal', + 'upper-armenian', + 'disclosure-open', + 'disclosure-closed', + // Non-standard extensions (without prefixe) + 'ethiopic-halehame', + 'ethiopic-halehame-am', + 'ethiopic-halehame-ti-er', + 'ethiopic-halehame-ti-et', + 'hangul', + 'hangul-consonant', + 'urdu', +]); + +const listStylePositionKeywords = uniteSets(basicKeywords, ['inside', 'outside']); + +const listStyleImageKeywords = uniteSets(basicKeywords, ['none']); + +const listStyleShorthandKeywords = uniteSets( + basicKeywords, + listStyleTypeKeywords, + listStylePositionKeywords, + listStyleImageKeywords, +); + +const camelCaseKeywords = new Set([ + 'optimizeSpeed', + 'optimizeQuality', + 'optimizeLegibility', + 'geometricPrecision', + 'currentColor', + 'crispEdges', + 'visiblePainted', + 'visibleFill', + 'visibleStroke', + 'sRGB', + 'linearRGB', +]); + +const keyframeSelectorKeywords = new Set(['from', 'to']); + +// https://www.w3.org/TR/CSS22/ui.html#system-colors +const systemColorsKeywords = new Set([ + 'activeborder', + 'activecaption', + 'appworkspace', + 'background', + 'buttonface', + 'buttonhighlight', + 'buttonshadow', + 'buttontext', + 'captiontext', + 'graytext', + 'highlight', + 'highlighttext', + 'inactiveborder', + 'inactivecaption', + 'inactivecaptiontext', + 'infobackground', + 'infotext', + 'menu', + 'menutext', + 'scrollbar', + 'threeddarkshadow', + 'threedface', + 'threedhighlight', + 'threedlightshadow', + 'threedshadow', + 'window', + 'windowframe', + 'windowtext', +]); + +module.exports = { + animationNameKeywords, + animationShorthandKeywords, + basicKeywords, + camelCaseKeywords, + counterIncrementKeywords, + counterResetKeywords, + fontFamilyKeywords, + fontShorthandKeywords, + fontSizeKeywords, + fontWeightKeywords, + fontWeightRelativeKeywords, + gridAreaKeywords, + gridColumnKeywords, + gridRowKeywords, + keyframeSelectorKeywords, + listStyleImageKeywords, + listStylePositionKeywords, + listStyleShorthandKeywords, + listStyleTypeKeywords, + systemColorsKeywords, + systemFontKeywords, +}; diff --git a/lib/reference/mathFunctions.js b/lib/reference/mathFunctions.js deleted file mode 100644 index d9e2b1554e..0000000000 --- a/lib/reference/mathFunctions.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict'; - -module.exports = new Set(['calc', 'clamp', 'max', 'min']); diff --git a/lib/reference/mediaFeatures.js b/lib/reference/mediaFeatures.js new file mode 100644 index 0000000000..5362da3f97 --- /dev/null +++ b/lib/reference/mediaFeatures.js @@ -0,0 +1,65 @@ +'use strict'; + +const uniteSets = require('../utils/uniteSets.js'); + +const deprecatedMediaFeatureNames = new Set([ + 'device-aspect-ratio', + 'device-height', + 'device-width', + 'max-device-aspect-ratio', + 'max-device-height', + 'max-device-width', + 'min-device-aspect-ratio', + 'min-device-height', + 'min-device-width', +]); + +const mediaFeatureNames = uniteSets(deprecatedMediaFeatureNames, [ + 'any-hover', + 'any-pointer', + 'aspect-ratio', + 'color', + 'color-gamut', + 'color-index', + 'display-mode', + 'dynamic-range', + 'forced-colors', + 'grid', + 'height', + 'hover', + 'inverted-colors', + 'light-level', + 'max-aspect-ratio', + 'max-color', + 'max-color-index', + 'max-height', + 'max-monochrome', + 'max-resolution', + 'max-width', + 'min-aspect-ratio', + 'min-color', + 'min-color-index', + 'min-height', + 'min-monochrome', + 'min-resolution', + 'min-width', + 'monochrome', + 'orientation', + 'overflow-block', + 'overflow-inline', + 'pointer', + 'prefers-color-scheme', + 'prefers-contrast', + 'prefers-reduced-motion', + 'prefers-reduced-transparency', + 'resolution', + 'scan', + 'scripting', + 'update', + 'video-dynamic-range', + 'width', +]); + +module.exports = { + mediaFeatureNames, +}; diff --git a/lib/reference/properties.js b/lib/reference/properties.js index eea7176182..76895ecbaf 100644 --- a/lib/reference/properties.js +++ b/lib/reference/properties.js @@ -1,5 +1,18 @@ 'use strict'; +const acceptCustomIdentsProperties = new Set([ + 'animation', + 'animation-name', + 'font', + 'font-family', + 'counter-increment', + 'grid-row', + 'grid-column', + 'grid-area', + 'list-style', + 'list-style-type', +]); + /** @type {import('stylelint').LonghandSubPropertiesOfShorthandProperties} */ const longhandSubPropertiesOfShorthandProperties = new Map([ // Sort alphabetically @@ -347,6 +360,18 @@ const longhandSubPropertiesOfShorthandProperties = new Map([ ], ]); +const longhandTimeProperties = new Set([ + 'transition-duration', + 'transition-delay', + 'animation-duration', + 'animation-delay', +]); + +const shorthandTimeProperties = new Set(['transition', 'animation']); + module.exports = { + acceptCustomIdentsProperties, longhandSubPropertiesOfShorthandProperties, + longhandTimeProperties, + shorthandTimeProperties, }; diff --git a/lib/reference/propertySets.js b/lib/reference/propertySets.js deleted file mode 100644 index 3bfe3af8a6..0000000000 --- a/lib/reference/propertySets.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict'; - -const propertySets = {}; - -propertySets.acceptCustomIdents = new Set([ - 'animation', - 'animation-name', - 'font', - 'font-family', - 'counter-increment', - 'grid-row', - 'grid-column', - 'grid-area', - 'list-style', - 'list-style-type', -]); - -module.exports = propertySets; diff --git a/lib/reference/punctuationSets.js b/lib/reference/punctuationSets.js deleted file mode 100644 index a9a525282a..0000000000 --- a/lib/reference/punctuationSets.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; - -const punctuationSets = {}; - -punctuationSets.mediaFeaturePunctuation = new Set([':', '=', '>', '>=', '<', '<=']); - -punctuationSets.nonSpaceCombinators = new Set(['>', '+', '~', '>>>', '/deep/']); - -module.exports = punctuationSets; diff --git a/lib/reference/selectors.js b/lib/reference/selectors.js new file mode 100644 index 0000000000..bd3bdc742f --- /dev/null +++ b/lib/reference/selectors.js @@ -0,0 +1,318 @@ +'use strict'; + +const htmlTags = require('html-tags'); +const uniteSets = require('../utils/uniteSets.js'); + +const deprecatedHtmlTypeSelectors = new Set([ + 'acronym', + 'applet', + 'basefont', + 'big', + 'blink', + 'center', + 'content', + 'dir', + 'font', + 'frame', + 'frameset', + 'hgroup', + 'isindex', + 'keygen', + 'listing', + 'marquee', + 'nobr', + 'noembed', + 'plaintext', + 'spacer', + 'strike', + 'tt', + 'xmp', +]); + +// typecasting htmlTags to be more generic; see https://github.com/stylelint/stylelint/pull/6013 for discussion +/** @type {Set} */ +const standardHtmlTypeSelectors = new Set(htmlTags); + +const htmlTypeSelectors = uniteSets(deprecatedHtmlTypeSelectors, standardHtmlTypeSelectors); + +const mixedCaseSvgTypeSelectors = new Set([ + 'altGlyph', + 'altGlyphDef', + 'altGlyphItem', + 'animateColor', + 'animateMotion', + 'animateTransform', + 'clipPath', + 'feBlend', + 'feColorMatrix', + 'feComponentTransfer', + 'feComposite', + 'feConvolveMatrix', + 'feDiffuseLighting', + 'feDisplacementMap', + 'feDistantLight', + 'feDropShadow', + 'feFlood', + 'feFuncA', + 'feFuncB', + 'feFuncG', + 'feFuncR', + 'feGaussianBlur', + 'feImage', + 'feMerge', + 'feMergeNode', + 'feMorphology', + 'feOffset', + 'fePointLight', + 'feSpecularLighting', + 'feSpotLight', + 'feTile', + 'feTurbulence', + 'foreignObject', + 'glyphRef', + 'linearGradient', + 'radialGradient', + 'textPath', +]); + +// These are the ones that can have single-colon notation +const levelOneAndTwoPseudoElements = new Set(['before', 'after', 'first-line', 'first-letter']); + +const shadowTreePseudoElements = new Set(['part']); + +const webkitScrollbarPseudoElements = new Set([ + '-webkit-resizer', + '-webkit-scrollbar', + '-webkit-scrollbar-button', + '-webkit-scrollbar-corner', + '-webkit-scrollbar-thumb', + '-webkit-scrollbar-track', + '-webkit-scrollbar-track-piece', +]); + +const vendorSpecificPseudoElements = uniteSets(webkitScrollbarPseudoElements, [ + '-moz-focus-inner', + '-moz-focus-outer', + '-moz-list-bullet', + '-moz-meter-bar', + '-moz-placeholder', + '-moz-progress-bar', + '-moz-range-progress', + '-moz-range-thumb', + '-moz-range-track', + '-ms-browse', + '-ms-check', + '-ms-clear', + '-ms-expand', + '-ms-fill', + '-ms-fill-lower', + '-ms-fill-upper', + '-ms-reveal', + '-ms-thumb', + '-ms-ticks-after', + '-ms-ticks-before', + '-ms-tooltip', + '-ms-track', + '-ms-value', + '-webkit-color-swatch', + '-webkit-color-swatch-wrapper', + '-webkit-calendar-picker-indicator', + '-webkit-clear-button', + '-webkit-date-and-time-value', + '-webkit-datetime-edit', + '-webkit-datetime-edit-ampm-field', + '-webkit-datetime-edit-day-field', + '-webkit-datetime-edit-fields-wrapper', + '-webkit-datetime-edit-hour-field', + '-webkit-datetime-edit-millisecond-field', + '-webkit-datetime-edit-minute-field', + '-webkit-datetime-edit-month-field', + '-webkit-datetime-edit-second-field', + '-webkit-datetime-edit-text', + '-webkit-datetime-edit-week-field', + '-webkit-datetime-edit-year-field', + '-webkit-details-marker', + '-webkit-distributed', + '-webkit-file-upload-button', + '-webkit-input-placeholder', + '-webkit-keygen-select', + '-webkit-meter-bar', + '-webkit-meter-even-less-good-value', + '-webkit-meter-inner-element', + '-webkit-meter-optimum-value', + '-webkit-meter-suboptimum-value', + '-webkit-progress-bar', + '-webkit-progress-inner-element', + '-webkit-progress-value', + '-webkit-search-cancel-button', + '-webkit-search-decoration', + '-webkit-search-results-button', + '-webkit-search-results-decoration', + '-webkit-slider-runnable-track', + '-webkit-slider-thumb', + '-webkit-textfield-decoration-container', + '-webkit-validation-bubble', + '-webkit-validation-bubble-arrow', + '-webkit-validation-bubble-arrow-clipper', + '-webkit-validation-bubble-heading', + '-webkit-validation-bubble-message', + '-webkit-validation-bubble-text-block', +]); + +const pseudoElements = uniteSets( + levelOneAndTwoPseudoElements, + vendorSpecificPseudoElements, + shadowTreePseudoElements, + [ + 'backdrop', + 'content', + 'cue', + 'file-selector-button', + 'grammar-error', + 'marker', + 'placeholder', + 'selection', + 'shadow', + 'slotted', + 'spelling-error', + 'target-text', + ], +); + +const aNPlusBNotationPseudoClasses = new Set([ + 'nth-column', + 'nth-last-column', + 'nth-last-of-type', + 'nth-of-type', +]); + +const aNPlusBOfSNotationPseudoClasses = new Set(['nth-child', 'nth-last-child']); + +const atRulePagePseudoClasses = new Set(['first', 'right', 'left', 'blank']); + +const linguisticPseudoClasses = new Set(['dir', 'lang']); + +const logicalCombinationsPseudoClasses = new Set(['has', 'is', 'matches', 'not', 'where']); + +const vendorSpecificPseudoClasses = new Set([ + '-khtml-drag', + '-moz-any', + '-moz-any-link', + '-moz-broken', + '-moz-drag-over', + '-moz-first-node', + '-moz-focusring', + '-moz-full-screen', + '-moz-full-screen-ancestor', + '-moz-last-node', + '-moz-loading', + '-moz-meter-optimum', + '-moz-meter-sub-optimum', + '-moz-meter-sub-sub-optimum', + '-moz-placeholder', + '-moz-submit-invalid', + '-moz-suppressed', + '-moz-ui-invalid', + '-moz-ui-valid', + '-moz-user-disabled', + '-moz-window-inactive', + '-ms-fullscreen', + '-ms-input-placeholder', + '-webkit-drag', + '-webkit-any', + '-webkit-any-link', + '-webkit-autofill', + '-webkit-full-screen', + '-webkit-full-screen-ancestor', +]); + +// https://webkit.org/blog/363/styling-scrollbars/ +const webkitScrollbarPseudoClasses = new Set([ + 'horizontal', + 'vertical', + 'decrement', + 'increment', + 'start', + 'end', + 'double-button', + 'single-button', + 'no-button', + 'corner-present', + 'window-inactive', +]); + +const pseudoClasses = uniteSets( + aNPlusBNotationPseudoClasses, + linguisticPseudoClasses, + logicalCombinationsPseudoClasses, + aNPlusBOfSNotationPseudoClasses, + vendorSpecificPseudoClasses, + [ + 'active', + 'any-link', + 'autofill', + 'blank', + 'checked', + 'current', + 'default', + 'defined', + 'disabled', + 'empty', + 'enabled', + 'first-child', + 'first-of-type', + 'focus', + 'focus-within', + 'focus-visible', + 'fullscreen', + 'fullscreen-ancestor', + 'future', + 'host', + 'host-context', + 'hover', + 'indeterminate', + 'in-range', + 'invalid', + 'last-child', + 'last-of-type', + 'link', + 'only-child', + 'only-of-type', + 'optional', + 'out-of-range', + 'past', + 'placeholder-shown', + 'playing', + 'picture-in-picture', + 'paused', + 'read-only', + 'read-write', + 'required', + 'root', + 'scope', + 'state', + 'target', + 'unresolved', + 'user-invalid', + 'user-valid', + 'valid', + 'visited', + 'window-inactive', // for ::selection (chrome) + ], +); + +module.exports = { + aNPlusBNotationPseudoClasses, + aNPlusBOfSNotationPseudoClasses, + atRulePagePseudoClasses, + levelOneAndTwoPseudoElements, + linguisticPseudoClasses, + logicalCombinationsPseudoClasses, + mixedCaseSvgTypeSelectors, + pseudoClasses, + pseudoElements, + shadowTreePseudoElements, + htmlTypeSelectors, + webkitScrollbarPseudoClasses, + webkitScrollbarPseudoElements, +}; diff --git a/lib/reference/units.js b/lib/reference/units.js new file mode 100644 index 0000000000..a4de9e3bbd --- /dev/null +++ b/lib/reference/units.js @@ -0,0 +1,67 @@ +'use strict'; + +const uniteSets = require('../utils/uniteSets.js'); + +const lengthUnits = new Set([ + // Relative length units + 'em', + 'ex', + 'ch', + 'rem', + 'rlh', + 'lh', + // Viewport-percentage lengths + 'dvh', + 'dvmax', + 'dvmin', + 'dvw', + 'lvh', + 'lvmax', + 'lvmin', + 'lvw', + 'svh', + 'svmax', + 'svmin', + 'svw', + 'vh', + 'vw', + 'vmin', + 'vmax', + 'vm', + // Absolute length units + 'px', + 'mm', + 'cm', + 'in', + 'pt', + 'pc', + 'q', + 'mozmm', + // Flexible length units + 'fr', +]); + +const units = uniteSets(lengthUnits, [ + // Relative length units + '%', + // Time length units + 's', + 'ms', + // Angle + 'deg', + 'grad', + 'turn', + 'rad', + // Frequency + 'Hz', + 'kHz', + // Resolution + 'dpi', + 'dpcm', + 'dppx', +]); + +module.exports = { + lengthUnits, + units, +}; diff --git a/lib/rules/at-rule-no-unknown/index.js b/lib/rules/at-rule-no-unknown/index.js index 7776b513ad..940e483547 100644 --- a/lib/rules/at-rule-no-unknown/index.js +++ b/lib/rules/at-rule-no-unknown/index.js @@ -1,7 +1,7 @@ 'use strict'; const isStandardSyntaxAtRule = require('../../utils/isStandardSyntaxAtRule'); -const keywordSets = require('../../reference/keywordSets'); +const { atKeywords } = require('../../reference/atKeywords'); const optionsMatches = require('../../utils/optionsMatches'); const report = require('../../utils/report'); const ruleMessages = require('../../utils/ruleMessages'); @@ -51,7 +51,7 @@ const rule = (primary, secondaryOptions) => { return; } - if (vendor.prefix(name) || keywordSets.atRules.has(name.toLowerCase())) { + if (vendor.prefix(name) || atKeywords.has(name.toLowerCase())) { return; } diff --git a/lib/rules/color-named/index.js b/lib/rules/color-named/index.js index 7e2b76afd7..9a982a95e2 100644 --- a/lib/rules/color-named/index.js +++ b/lib/rules/color-named/index.js @@ -4,7 +4,7 @@ const declarationValueIndex = require('../../utils/declarationValueIndex'); const isStandardSyntaxFunction = require('../../utils/isStandardSyntaxFunction'); const isStandardSyntaxValue = require('../../utils/isStandardSyntaxValue'); const optionsMatches = require('../../utils/optionsMatches'); -const propertySets = require('../../reference/propertySets'); +const { acceptCustomIdentsProperties } = require('../../reference/properties'); const report = require('../../utils/report'); const ruleMessages = require('../../utils/ruleMessages'); const validateOptions = require('../../utils/validateOptions'); @@ -51,7 +51,7 @@ const rule = (primary, secondaryOptions) => { } root.walkDecls((decl) => { - if (propertySets.acceptCustomIdents.has(decl.prop)) { + if (acceptCustomIdentsProperties.has(decl.prop)) { return; } diff --git a/lib/rules/font-family-name-quotes/index.js b/lib/rules/font-family-name-quotes/index.js index 32f8542655..c7ae41ed1c 100644 --- a/lib/rules/font-family-name-quotes/index.js +++ b/lib/rules/font-family-name-quotes/index.js @@ -3,7 +3,7 @@ const findFontFamily = require('../../utils/findFontFamily'); const isStandardSyntaxValue = require('../../utils/isStandardSyntaxValue'); const isVariable = require('../../utils/isVariable'); -const keywordSets = require('../../reference/keywordSets'); +const { fontFamilyKeywords } = require('../../reference/keywords'); const report = require('../../utils/report'); const ruleMessages = require('../../utils/ruleMessages'); const validateOptions = require('../../utils/validateOptions'); @@ -168,7 +168,7 @@ const rule = (primary, _secondary, context) => { // Disallow quotes around (case-insensitive) keywords // and system font keywords in all cases - if (keywordSets.fontFamilyKeywords.has(family.toLowerCase()) || isSystemFontKeyword(family)) { + if (fontFamilyKeywords.has(family.toLowerCase()) || isSystemFontKeyword(family)) { if (hasQuotes) { if (context.fix) { fontFamilyNode.removeQuotes(); diff --git a/lib/rules/font-family-no-duplicate-names/index.js b/lib/rules/font-family-no-duplicate-names/index.js index c187eac91e..594ccd7b64 100644 --- a/lib/rules/font-family-no-duplicate-names/index.js +++ b/lib/rules/font-family-no-duplicate-names/index.js @@ -2,7 +2,7 @@ const declarationValueIndex = require('../../utils/declarationValueIndex'); const findFontFamily = require('../../utils/findFontFamily'); -const keywordSets = require('../../reference/keywordSets'); +const { fontFamilyKeywords } = require('../../reference/keywords'); const optionsMatches = require('../../utils/optionsMatches'); const report = require('../../utils/report'); const ruleMessages = require('../../utils/ruleMessages'); @@ -23,7 +23,7 @@ const meta = { * @param {import('postcss-value-parser').Node} node */ const isFamilyNameKeyword = (node) => - !('quote' in node) && keywordSets.fontFamilyKeywords.has(node.value.toLowerCase()); + !('quote' in node) && fontFamilyKeywords.has(node.value.toLowerCase()); /** @type {import('stylelint').Rule} */ const rule = (primary, secondaryOptions) => { diff --git a/lib/rules/font-family-no-missing-generic-family-keyword/index.js b/lib/rules/font-family-no-missing-generic-family-keyword/index.js index df23aeeadd..db972487b6 100644 --- a/lib/rules/font-family-no-missing-generic-family-keyword/index.js +++ b/lib/rules/font-family-no-missing-generic-family-keyword/index.js @@ -4,7 +4,7 @@ const declarationValueIndex = require('../../utils/declarationValueIndex'); const findFontFamily = require('../../utils/findFontFamily'); const isStandardSyntaxValue = require('../../utils/isStandardSyntaxValue'); const isVariable = require('../../utils/isVariable'); -const keywordSets = require('../../reference/keywordSets'); +const { systemFontKeywords, fontFamilyKeywords } = require('../../reference/keywords'); const optionsMatches = require('../../utils/optionsMatches'); const postcss = require('postcss'); const report = require('../../utils/report'); @@ -28,7 +28,7 @@ const meta = { * @returns {boolean} */ const isFamilyNameKeyword = (node) => - !('quote' in node) && keywordSets.fontFamilyKeywords.has(node.value.toLowerCase()); + !('quote' in node) && fontFamilyKeywords.has(node.value.toLowerCase()); /** * @param {string} value @@ -68,7 +68,7 @@ const rule = (primary, secondaryOptions) => { return; } - if (decl.prop === 'font' && keywordSets.systemFontValues.has(decl.value.toLowerCase())) { + if (decl.prop === 'font' && systemFontKeywords.has(decl.value.toLowerCase())) { return; } diff --git a/lib/rules/font-weight-notation/index.js b/lib/rules/font-weight-notation/index.js index b1c60dd923..49d9c7210e 100644 --- a/lib/rules/font-weight-notation/index.js +++ b/lib/rules/font-weight-notation/index.js @@ -6,7 +6,7 @@ const declarationValueIndex = require('../../utils/declarationValueIndex'); const isNumbery = require('../../utils/isNumbery'); const isStandardSyntaxValue = require('../../utils/isStandardSyntaxValue'); const isVariable = require('../../utils/isVariable'); -const keywordSets = require('../../reference/keywordSets'); +const { fontWeightKeywords, fontWeightRelativeKeywords } = require('../../reference/keywords'); const optionsMatches = require('../../utils/optionsMatches'); const report = require('../../utils/report'); const ruleMessages = require('../../utils/ruleMessages'); @@ -80,7 +80,7 @@ const rule = (primary, secondaryOptions) => { if ( (lowerValue === NORMAL_KEYWORD && !hasNumericFontWeight) || isNumbery(value) || - (lowerValue !== NORMAL_KEYWORD && keywordSets.fontWeightKeywords.has(lowerValue)) + (lowerValue !== NORMAL_KEYWORD && fontWeightKeywords.has(lowerValue)) ) { checkWeight(decl, value, valueNode); @@ -115,7 +115,7 @@ const rule = (primary, secondaryOptions) => { if ( optionsMatches(secondaryOptions, 'ignore', 'relative') && - keywordSets.fontWeightRelativeKeywords.has(lowerWeightValue) + fontWeightRelativeKeywords.has(lowerWeightValue) ) { return; } @@ -148,10 +148,7 @@ const rule = (primary, secondaryOptions) => { return; } - if ( - !keywordSets.fontWeightKeywords.has(lowerWeightValue) && - lowerWeightValue !== NORMAL_KEYWORD - ) { + if (!fontWeightKeywords.has(lowerWeightValue) && lowerWeightValue !== NORMAL_KEYWORD) { return complain(messages.invalidNamed(weightValue), weightValue, weightValueNode); } } diff --git a/lib/rules/function-name-case/index.js b/lib/rules/function-name-case/index.js index 4f286ca64f..979b7c79e3 100644 --- a/lib/rules/function-name-case/index.js +++ b/lib/rules/function-name-case/index.js @@ -3,7 +3,7 @@ const declarationValueIndex = require('../../utils/declarationValueIndex'); const getDeclarationValue = require('../../utils/getDeclarationValue'); const isStandardSyntaxFunction = require('../../utils/isStandardSyntaxFunction'); -const keywordSets = require('../../reference/keywordSets'); +const { camelCaseFunctions } = require('../../reference/functions'); const optionsMatches = require('../../utils/optionsMatches'); const report = require('../../utils/report'); const ruleMessages = require('../../utils/ruleMessages'); @@ -24,7 +24,7 @@ const meta = { const mapLowercaseFunctionNamesToCamelCase = new Map(); -for (const func of keywordSets.camelCaseFunctionNames) { +for (const func of camelCaseFunctions) { mapLowercaseFunctionNamesToCamelCase.set(func.toLowerCase(), func); } diff --git a/lib/rules/length-zero-no-unit/index.js b/lib/rules/length-zero-no-unit/index.js index 04766d4f1a..b4fe9fe30a 100644 --- a/lib/rules/length-zero-no-unit/index.js +++ b/lib/rules/length-zero-no-unit/index.js @@ -9,7 +9,7 @@ const getDeclarationValue = require('../../utils/getDeclarationValue'); const isCustomProperty = require('../../utils/isCustomProperty'); const isMathFunction = require('../../utils/isMathFunction'); const isStandardSyntaxAtRule = require('../../utils/isStandardSyntaxAtRule'); -const keywordSets = require('../../reference/keywordSets'); +const { lengthUnits } = require('../../reference/units'); const optionsMatches = require('../../utils/optionsMatches'); const report = require('../../utils/report'); const ruleMessages = require('../../utils/ruleMessages'); @@ -196,7 +196,7 @@ function isWord({ type }) { * @param {string} unit */ function isLength(unit) { - return keywordSets.lengthUnits.has(unit.toLowerCase()); + return lengthUnits.has(unit.toLowerCase()); } /** diff --git a/lib/rules/media-feature-name-no-unknown/index.js b/lib/rules/media-feature-name-no-unknown/index.js index 4b9e9393bd..82b0684b1e 100644 --- a/lib/rules/media-feature-name-no-unknown/index.js +++ b/lib/rules/media-feature-name-no-unknown/index.js @@ -4,7 +4,7 @@ const atRuleParamIndex = require('../../utils/atRuleParamIndex'); const isCustomMediaQuery = require('../../utils/isCustomMediaQuery'); const isRangeContextMediaFeature = require('../../utils/isRangeContextMediaFeature'); const isStandardSyntaxMediaFeatureName = require('../../utils/isStandardSyntaxMediaFeatureName'); -const keywordSets = require('../../reference/keywordSets'); +const { mediaFeatureNames } = require('../../reference/mediaFeatures'); const mediaParser = require('postcss-media-query-parser').default; const optionsMatches = require('../../utils/optionsMatches'); const rangeContextNodeParser = require('../rangeContextNodeParser'); @@ -70,7 +70,7 @@ const rule = (primary, secondaryOptions) => { return; } - if (vendor.prefix(value) || keywordSets.mediaFeatureNames.has(value.toLowerCase())) { + if (vendor.prefix(value) || mediaFeatureNames.has(value.toLowerCase())) { return; } diff --git a/lib/rules/no-descending-specificity/index.js b/lib/rules/no-descending-specificity/index.js index bd4654c57c..39734f8d3a 100644 --- a/lib/rules/no-descending-specificity/index.js +++ b/lib/rules/no-descending-specificity/index.js @@ -6,7 +6,7 @@ const { selectorSpecificity: calculate, compare } = require('@csstools/selector- const findAtRuleContext = require('../../utils/findAtRuleContext'); const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); const isStandardSyntaxSelector = require('../../utils/isStandardSyntaxSelector'); -const keywordSets = require('../../reference/keywordSets'); +const { pseudoElements } = require('../../reference/selectors'); const nodeContextLookup = require('../../utils/nodeContextLookup'); const optionsMatches = require('../../utils/optionsMatches'); const parseSelector = require('../../utils/parseSelector'); @@ -142,7 +142,7 @@ function lastCompoundSelectorWithoutPseudoClasses(selectorNode) { return ( node.type !== 'pseudo' || node.value.startsWith('::') || - keywordSets.pseudoElements.has(node.value.replace(/:/g, '')) + pseudoElements.has(node.value.replace(/:/g, '')) ); }) .join(''); diff --git a/lib/rules/no-unknown-animations/index.js b/lib/rules/no-unknown-animations/index.js index 06415a6f4b..4ec83c964f 100644 --- a/lib/rules/no-unknown-animations/index.js +++ b/lib/rules/no-unknown-animations/index.js @@ -2,7 +2,7 @@ const declarationValueIndex = require('../../utils/declarationValueIndex'); const findAnimationName = require('../../utils/findAnimationName'); -const keywordSets = require('../../reference/keywordSets'); +const { animationNameKeywords } = require('../../reference/keywords'); const report = require('../../utils/report'); const ruleMessages = require('../../utils/ruleMessages'); const validateOptions = require('../../utils/validateOptions'); @@ -41,7 +41,7 @@ const rule = (primary) => { } for (const animationNameNode of animationNames) { - if (keywordSets.animationNameKeywords.has(animationNameNode.value.toLowerCase())) { + if (animationNameKeywords.has(animationNameNode.value.toLowerCase())) { continue; } diff --git a/lib/rules/selector-max-pseudo-class/index.js b/lib/rules/selector-max-pseudo-class/index.js index 466785e199..9cfbfea965 100644 --- a/lib/rules/selector-max-pseudo-class/index.js +++ b/lib/rules/selector-max-pseudo-class/index.js @@ -3,7 +3,7 @@ const isContextFunctionalPseudoClass = require('../../utils/isContextFunctionalPseudoClass'); const isNonNegativeInteger = require('../../utils/isNonNegativeInteger'); const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); -const keywordSets = require('../../reference/keywordSets'); +const { levelOneAndTwoPseudoElements } = require('../../reference/selectors'); const parseSelector = require('../../utils/parseSelector'); const report = require('../../utils/report'); const resolvedNestedSelector = require('postcss-resolve-nested-selector'); @@ -48,7 +48,7 @@ const rule = (primary) => { if ( childNode.type === 'pseudo' && (childNode.value.includes('::') || - keywordSets.levelOneAndTwoPseudoElements.has(childNode.value.toLowerCase().slice(1))) + levelOneAndTwoPseudoElements.has(childNode.value.toLowerCase().slice(1))) ) { return total; } diff --git a/lib/rules/selector-max-specificity/index.js b/lib/rules/selector-max-specificity/index.js index 13473c1b8d..ccd2bbdf40 100644 --- a/lib/rules/selector-max-specificity/index.js +++ b/lib/rules/selector-max-specificity/index.js @@ -5,7 +5,11 @@ const { selectorSpecificity, compare } = require('@csstools/selector-specificity const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); const isStandardSyntaxSelector = require('../../utils/isStandardSyntaxSelector'); -const keywordSets = require('../../reference/keywordSets'); +const { + aNPlusBOfSNotationPseudoClasses, + aNPlusBNotationPseudoClasses, + linguisticPseudoClasses, +} = require('../../reference/selectors'); const optionsMatches = require('../../utils/optionsMatches'); const parseSelector = require('../../utils/parseSelector'); const report = require('../../utils/report'); @@ -122,7 +126,7 @@ const rule = (primary, secondaryOptions) => { if (optionsMatches(secondaryOptions, 'ignoreSelectors', ownValue)) { ownSpecificity = zeroSpecificity(); - } else if (keywordSets.aNPlusBOfSNotationPseudoClasses.has(ownValue.replace(/^:/, ''))) { + } else if (aNPlusBOfSNotationPseudoClasses.has(ownValue.replace(/^:/, ''))) { // TODO: We need to support `` in `ignoreSelectors`. E.g. `:nth-child(even of .foo)`. return selectorSpecificity(node); } else { @@ -147,8 +151,7 @@ const rule = (primary, secondaryOptions) => { const pseudoClass = parentNode.value.toLowerCase().replace(/^:/, ''); return ( - keywordSets.aNPlusBNotationPseudoClasses.has(pseudoClass) || - keywordSets.linguisticPseudoClasses.has(pseudoClass) + aNPlusBNotationPseudoClasses.has(pseudoClass) || linguisticPseudoClasses.has(pseudoClass) ); } diff --git a/lib/rules/selector-pseudo-class-case/index.js b/lib/rules/selector-pseudo-class-case/index.js index 9a46c3b814..0385706a9a 100644 --- a/lib/rules/selector-pseudo-class-case/index.js +++ b/lib/rules/selector-pseudo-class-case/index.js @@ -2,7 +2,7 @@ const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); const isStandardSyntaxSelector = require('../../utils/isStandardSyntaxSelector'); -const keywordSets = require('../../reference/keywordSets'); +const { levelOneAndTwoPseudoElements } = require('../../reference/selectors'); const parseSelector = require('../../utils/parseSelector'); const report = require('../../utils/report'); const ruleMessages = require('../../utils/ruleMessages'); @@ -55,7 +55,7 @@ const rule = (primary, _secondaryOptions, context) => { if ( pseudo.includes('::') || - keywordSets.levelOneAndTwoPseudoElements.has(pseudo.toLowerCase().slice(1)) + levelOneAndTwoPseudoElements.has(pseudo.toLowerCase().slice(1)) ) { return; } diff --git a/lib/rules/selector-pseudo-class-no-unknown/index.js b/lib/rules/selector-pseudo-class-no-unknown/index.js index b1384f508a..75c4ce207c 100644 --- a/lib/rules/selector-pseudo-class-no-unknown/index.js +++ b/lib/rules/selector-pseudo-class-no-unknown/index.js @@ -5,7 +5,13 @@ const isCustomSelector = require('../../utils/isCustomSelector'); const isStandardSyntaxAtRule = require('../../utils/isStandardSyntaxAtRule'); const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); const isStandardSyntaxSelector = require('../../utils/isStandardSyntaxSelector'); -const keywordSets = require('../../reference/keywordSets'); +const { + atRulePagePseudoClasses, + pseudoClasses, + pseudoElements, + webkitScrollbarPseudoClasses, + webkitScrollbarPseudoElements, +} = require('../../reference/selectors'); const optionsMatches = require('../../utils/optionsMatches'); const parseSelector = require('../../utils/parseSelector'); const report = require('../../utils/report'); @@ -74,17 +80,13 @@ const rule = (primary, secondaryOptions) => { const name = value.slice(1).toLowerCase(); if (node.type === 'atrule' && node.name === 'page') { - if (keywordSets.atRulePagePseudoClasses.has(name)) { + if (atRulePagePseudoClasses.has(name)) { return; } index = atRuleParamIndex(node) + pseudoNode.sourceIndex; } else { - if ( - vendor.prefix(name) || - keywordSets.pseudoClasses.has(name) || - keywordSets.pseudoElements.has(name) - ) { + if (vendor.prefix(name) || pseudoClasses.has(name) || pseudoElements.has(name)) { return; } @@ -105,8 +107,8 @@ const rule = (primary, secondaryOptions) => { const prevPseudoElementValue = prevPseudoElement.value.toLowerCase().slice(2); if ( - keywordSets.webkitScrollbarPseudoElements.has(prevPseudoElementValue) && - keywordSets.webkitScrollbarPseudoClasses.has(name) + webkitScrollbarPseudoElements.has(prevPseudoElementValue) && + webkitScrollbarPseudoClasses.has(name) ) { return; } diff --git a/lib/rules/selector-pseudo-element-case/index.js b/lib/rules/selector-pseudo-element-case/index.js index 1c955f3d43..b04ddaf063 100644 --- a/lib/rules/selector-pseudo-element-case/index.js +++ b/lib/rules/selector-pseudo-element-case/index.js @@ -2,7 +2,7 @@ const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); const isStandardSyntaxSelector = require('../../utils/isStandardSyntaxSelector'); -const keywordSets = require('../../reference/keywordSets'); +const { levelOneAndTwoPseudoElements } = require('../../reference/selectors'); const report = require('../../utils/report'); const ruleMessages = require('../../utils/ruleMessages'); const transformSelector = require('../../utils/transformSelector'); @@ -51,7 +51,7 @@ const rule = (primary, _secondaryOptions, context) => { if ( !pseudoElement.includes('::') && - !keywordSets.levelOneAndTwoPseudoElements.has(pseudoElement.toLowerCase().slice(1)) + !levelOneAndTwoPseudoElements.has(pseudoElement.toLowerCase().slice(1)) ) { return; } diff --git a/lib/rules/selector-pseudo-element-colon-notation/index.js b/lib/rules/selector-pseudo-element-colon-notation/index.js index b1358ad64a..f78650eb72 100644 --- a/lib/rules/selector-pseudo-element-colon-notation/index.js +++ b/lib/rules/selector-pseudo-element-colon-notation/index.js @@ -1,7 +1,7 @@ 'use strict'; const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); -const keywordSets = require('../../reference/keywordSets'); +const { levelOneAndTwoPseudoElements } = require('../../reference/selectors'); const parseSelector = require('../../utils/parseSelector'); const report = require('../../utils/report'); const ruleMessages = require('../../utils/ruleMessages'); @@ -53,7 +53,7 @@ const rule = (primary, _secondaryOptions, context) => { selectors.walkPseudos((pseudo) => { const pseudoElement = pseudo.value.replace(/:/g, ''); - if (!keywordSets.levelOneAndTwoPseudoElements.has(pseudoElement.toLowerCase())) { + if (!levelOneAndTwoPseudoElements.has(pseudoElement.toLowerCase())) { return; } diff --git a/lib/rules/selector-pseudo-element-no-unknown/index.js b/lib/rules/selector-pseudo-element-no-unknown/index.js index a9bfb459f3..a8855af77b 100644 --- a/lib/rules/selector-pseudo-element-no-unknown/index.js +++ b/lib/rules/selector-pseudo-element-no-unknown/index.js @@ -2,7 +2,7 @@ const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); const isStandardSyntaxSelector = require('../../utils/isStandardSyntaxSelector'); -const keywordSets = require('../../reference/keywordSets'); +const { pseudoElements } = require('../../reference/selectors'); const optionsMatches = require('../../utils/optionsMatches'); const parseSelector = require('../../utils/parseSelector'); const report = require('../../utils/report'); @@ -73,7 +73,7 @@ const rule = (primary, secondaryOptions) => { const name = value.slice(2); - if (vendor.prefix(name) || keywordSets.pseudoElements.has(name.toLowerCase())) { + if (vendor.prefix(name) || pseudoElements.has(name.toLowerCase())) { return; } diff --git a/lib/rules/selector-type-case/index.js b/lib/rules/selector-type-case/index.js index 00f62af25a..7b62ba13db 100644 --- a/lib/rules/selector-type-case/index.js +++ b/lib/rules/selector-type-case/index.js @@ -9,7 +9,7 @@ const report = require('../../utils/report'); const ruleMessages = require('../../utils/ruleMessages'); const validateOptions = require('../../utils/validateOptions'); const { isString } = require('../../utils/validateTypes'); -const keywordSets = require('../../reference/keywordSets'); +const { mixedCaseSvgTypeSelectors } = require('../../reference/selectors'); const ruleName = 'selector-type-case'; @@ -63,7 +63,7 @@ const rule = (primary, secondaryOptions, context) => { return; } - if (keywordSets.validMixedCaseSvgElements.has(tag.value)) { + if (mixedCaseSvgTypeSelectors.has(tag.value)) { return; } diff --git a/lib/rules/selector-type-no-unknown/index.js b/lib/rules/selector-type-no-unknown/index.js index 817963b5d2..259a3f5af4 100644 --- a/lib/rules/selector-type-no-unknown/index.js +++ b/lib/rules/selector-type-no-unknown/index.js @@ -4,7 +4,7 @@ const isCustomElement = require('../../utils/isCustomElement'); const isKeyframeSelector = require('../../utils/isKeyframeSelector'); const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); const isStandardSyntaxTypeSelector = require('../../utils/isStandardSyntaxTypeSelector'); -const keywordSets = require('../../reference/keywordSets'); +const { htmlTypeSelectors } = require('../../reference/selectors'); const mathMLTags = require('mathml-tag-names'); const optionsMatches = require('../../utils/optionsMatches'); const parseSelector = require('../../utils/parseSelector'); @@ -90,10 +90,9 @@ const rule = (primary, secondaryOptions) => { const tagNameLowerCase = tagName.toLowerCase(); if ( - keywordSets.standardHtmlTags.has(tagNameLowerCase) || + htmlTypeSelectors.has(tagNameLowerCase) || // SVG tags are case-sensitive svgTags.includes(tagName) || - keywordSets.nonStandardHtmlTags.has(tagNameLowerCase) || mathMLTags.includes(tagNameLowerCase) ) { return; diff --git a/lib/rules/time-min-milliseconds/index.js b/lib/rules/time-min-milliseconds/index.js index 631981294a..2b02ea5509 100644 --- a/lib/rules/time-min-milliseconds/index.js +++ b/lib/rules/time-min-milliseconds/index.js @@ -1,7 +1,7 @@ 'use strict'; const declarationValueIndex = require('../../utils/declarationValueIndex'); -const keywordSets = require('../../reference/keywordSets'); +const { longhandTimeProperties, shorthandTimeProperties } = require('../../reference/properties'); const optionsMatches = require('../../utils/optionsMatches'); const postcss = require('postcss'); const report = require('../../utils/report'); @@ -52,14 +52,14 @@ const rule = (primary, secondaryOptions) => { const propertyName = vendor.unprefixed(decl.prop.toLowerCase()); if ( - keywordSets.longhandTimeProperties.has(propertyName) && + longhandTimeProperties.has(propertyName) && !isIgnoredProperty(propertyName) && !isAcceptableTime(decl.value) ) { complain(decl); } - if (keywordSets.shorthandTimeProperties.has(propertyName)) { + if (shorthandTimeProperties.has(propertyName)) { const valueListList = postcss.list.comma(decl.value); for (const valueListString of valueListList) { diff --git a/lib/rules/unit-no-unknown/index.js b/lib/rules/unit-no-unknown/index.js index 9972864bc0..b649c65a18 100644 --- a/lib/rules/unit-no-unknown/index.js +++ b/lib/rules/unit-no-unknown/index.js @@ -5,7 +5,7 @@ const declarationValueIndex = require('../../utils/declarationValueIndex'); const getUnitFromValueNode = require('../../utils/getUnitFromValueNode'); const isStandardSyntaxAtRule = require('../../utils/isStandardSyntaxAtRule'); const isStandardSyntaxDeclaration = require('../../utils/isStandardSyntaxDeclaration'); -const keywordSets = require('../../reference/keywordSets'); +const { units } = require('../../reference/units'); const mediaParser = require('postcss-media-query-parser').default; const optionsMatches = require('../../utils/optionsMatches'); const report = require('../../utils/report'); @@ -80,7 +80,7 @@ const rule = (primary, secondaryOptions) => { return; } - if (keywordSets.units.has(unit.toLowerCase()) && unit.toLowerCase() !== 'x') { + if (units.has(unit.toLowerCase()) && unit.toLowerCase() !== 'x') { return; } diff --git a/lib/rules/value-keyword-case/index.js b/lib/rules/value-keyword-case/index.js index 5d8d299338..ae0f844ae5 100644 --- a/lib/rules/value-keyword-case/index.js +++ b/lib/rules/value-keyword-case/index.js @@ -6,7 +6,19 @@ const getUnitFromValueNode = require('../../utils/getUnitFromValueNode'); const isCounterIncrementCustomIdentValue = require('../../utils/isCounterIncrementCustomIdentValue'); const isCounterResetCustomIdentValue = require('../../utils/isCounterResetCustomIdentValue'); const isStandardSyntaxValue = require('../../utils/isStandardSyntaxValue'); -const keywordSets = require('../../reference/keywordSets'); +const { + animationNameKeywords, + animationShorthandKeywords, + camelCaseKeywords, + fontFamilyKeywords, + fontShorthandKeywords, + gridAreaKeywords, + gridColumnKeywords, + gridRowKeywords, + listStyleShorthandKeywords, + listStyleTypeKeywords, + systemColorsKeywords, +} = require('../../reference/keywords'); const optionsMatches = require('../../utils/optionsMatches'); const report = require('../../utils/report'); const ruleMessages = require('../../utils/ruleMessages'); @@ -31,7 +43,7 @@ const gridColumnProps = new Set(['grid-column', 'grid-column-start', 'grid-colum const mapLowercaseKeywordsToCamelCase = new Map(); -for (const func of keywordSets.camelCaseKeywords) { +for (const func of camelCaseKeywords) { mapLowercaseKeywordsToCamelCase.set(func.toLowerCase(), func); } @@ -74,7 +86,7 @@ const rule = (primary, secondaryOptions, context) => { const valueLowerCase = node.value.toLowerCase(); // Ignore system colors - if (keywordSets.systemColors.has(valueLowerCase)) { + if (systemColorsKeywords.has(valueLowerCase)) { return; } @@ -114,31 +126,25 @@ const rule = (primary, secondaryOptions, context) => { if ( propLowerCase === 'animation' && - !keywordSets.animationShorthandKeywords.has(valueLowerCase) && - !keywordSets.animationNameKeywords.has(valueLowerCase) + !animationShorthandKeywords.has(valueLowerCase) && + !animationNameKeywords.has(valueLowerCase) ) { return; } - if ( - propLowerCase === 'animation-name' && - !keywordSets.animationNameKeywords.has(valueLowerCase) - ) { + if (propLowerCase === 'animation-name' && !animationNameKeywords.has(valueLowerCase)) { return; } if ( propLowerCase === 'font' && - !keywordSets.fontShorthandKeywords.has(valueLowerCase) && - !keywordSets.fontFamilyKeywords.has(valueLowerCase) + !fontShorthandKeywords.has(valueLowerCase) && + !fontFamilyKeywords.has(valueLowerCase) ) { return; } - if ( - propLowerCase === 'font-family' && - !keywordSets.fontFamilyKeywords.has(valueLowerCase) - ) { + if (propLowerCase === 'font-family' && !fontFamilyKeywords.has(valueLowerCase)) { return; } @@ -153,33 +159,27 @@ const rule = (primary, secondaryOptions, context) => { return; } - if (gridRowProps.has(propLowerCase) && !keywordSets.gridRowKeywords.has(valueLowerCase)) { + if (gridRowProps.has(propLowerCase) && !gridRowKeywords.has(valueLowerCase)) { return; } - if ( - gridColumnProps.has(propLowerCase) && - !keywordSets.gridColumnKeywords.has(valueLowerCase) - ) { + if (gridColumnProps.has(propLowerCase) && !gridColumnKeywords.has(valueLowerCase)) { return; } - if (propLowerCase === 'grid-area' && !keywordSets.gridAreaKeywords.has(valueLowerCase)) { + if (propLowerCase === 'grid-area' && !gridAreaKeywords.has(valueLowerCase)) { return; } if ( propLowerCase === 'list-style' && - !keywordSets.listStyleShorthandKeywords.has(valueLowerCase) && - !keywordSets.listStyleTypeKeywords.has(valueLowerCase) + !listStyleShorthandKeywords.has(valueLowerCase) && + !listStyleTypeKeywords.has(valueLowerCase) ) { return; } - if ( - propLowerCase === 'list-style-type' && - !keywordSets.listStyleTypeKeywords.has(valueLowerCase) - ) { + if (propLowerCase === 'list-style-type' && !listStyleTypeKeywords.has(valueLowerCase)) { return; } diff --git a/lib/utils/__tests__/isCustomElement.test.js b/lib/utils/__tests__/isCustomElement.test.js index 739496f763..727834349e 100644 --- a/lib/utils/__tests__/isCustomElement.test.js +++ b/lib/utils/__tests__/isCustomElement.test.js @@ -44,8 +44,8 @@ describe('isCustomElement', () => { expect(isCustomElement('annotation-xml')).toBeFalsy(); }); - // keywordSets tags - it('keywordSets tags', () => { + // keywords tags + it('keywords tags', () => { expect(isCustomElement('acronym')).toBeFalsy(); expect(isCustomElement('applet')).toBeFalsy(); }); diff --git a/lib/utils/findAnimationName.js b/lib/utils/findAnimationName.js index 2784031546..e37bec6683 100644 --- a/lib/utils/findAnimationName.js +++ b/lib/utils/findAnimationName.js @@ -3,7 +3,7 @@ const getUnitFromValueNode = require('./getUnitFromValueNode'); const isStandardSyntaxValue = require('./isStandardSyntaxValue'); const isVariable = require('./isVariable'); -const keywordSets = require('../reference/keywordSets'); +const { animationShorthandKeywords, basicKeywords } = require('../reference/keywords'); const postcssValueParser = require('postcss-value-parser'); /** @typedef {import('postcss-value-parser').Node} Node */ @@ -23,11 +23,7 @@ module.exports = function findAnimationName(value) { const { nodes } = valueNodes; // Handle `inherit`, `initial` and etc - if ( - nodes.length === 1 && - nodes[0] && - keywordSets.basicKeywords.has(nodes[0].value.toLowerCase()) - ) { + if (nodes.length === 1 && nodes[0] && basicKeywords.has(nodes[0].value.toLowerCase())) { return [nodes[0]]; } @@ -53,7 +49,7 @@ module.exports = function findAnimationName(value) { } // Ignore keywords for other animation parts - if (keywordSets.animationShorthandKeywords.has(valueLowerCase)) { + if (animationShorthandKeywords.has(valueLowerCase)) { return; } diff --git a/lib/utils/findFontFamily.js b/lib/utils/findFontFamily.js index c4ba652116..a19260d1ee 100644 --- a/lib/utils/findFontFamily.js +++ b/lib/utils/findFontFamily.js @@ -7,7 +7,11 @@ const isStandardSyntaxValue = require('./isStandardSyntaxValue'); const isValidFontSize = require('./isValidFontSize'); const isVariable = require('./isVariable'); const { assert } = require('./validateTypes'); -const keywordSets = require('../reference/keywordSets'); +const { + basicKeywords, + fontFamilyKeywords, + fontShorthandKeywords, +} = require('../reference/keywords'); const nodeTypesToCheck = new Set(['word', 'string', 'space', 'div']); @@ -41,11 +45,7 @@ module.exports = function findFontFamily(value) { const { nodes: children } = valueNodes; // Handle `inherit`, `initial` and etc - if ( - children.length === 1 && - children[0] && - keywordSets.basicKeywords.has(children[0].value.toLowerCase()) - ) { + if (children.length === 1 && children[0] && basicKeywords.has(children[0].value.toLowerCase())) { return [children[0]]; } @@ -75,10 +75,7 @@ module.exports = function findFontFamily(value) { } // Ignore keywords for other font parts - if ( - keywordSets.fontShorthandKeywords.has(valueLowerCase) && - !keywordSets.fontFamilyKeywords.has(valueLowerCase) - ) { + if (fontShorthandKeywords.has(valueLowerCase) && !fontFamilyKeywords.has(valueLowerCase)) { return; } diff --git a/lib/utils/findListStyleType.js b/lib/utils/findListStyleType.js index b387014667..d241913d0d 100644 --- a/lib/utils/findListStyleType.js +++ b/lib/utils/findListStyleType.js @@ -2,7 +2,11 @@ const isStandardSyntaxValue = require('./isStandardSyntaxValue'); const isVariable = require('./isVariable'); -const keywordSets = require('../reference/keywordSets'); +const { + listStyleImageKeywords, + listStylePositionKeywords, + listStyleTypeKeywords, +} = require('../reference/keywords'); const postcssValueParser = require('postcss-value-parser'); /** @@ -18,11 +22,7 @@ module.exports = function findListStyleType(value) { const { nodes } = valueNodes; // Handle `inherit`, `initial` and etc - if ( - nodes.length === 1 && - nodes[0] && - keywordSets.listStyleTypeKeywords.has(nodes[0].value.toLowerCase()) - ) { + if (nodes.length === 1 && nodes[0] && listStyleTypeKeywords.has(nodes[0].value.toLowerCase())) { return [nodes[0]]; } @@ -49,8 +49,8 @@ module.exports = function findListStyleType(value) { // Ignore keywords for other font parts if ( - keywordSets.listStylePositionKeywords.has(valueLowerCase) || - keywordSets.listStyleImageKeywords.has(valueLowerCase) + listStylePositionKeywords.has(valueLowerCase) || + listStyleImageKeywords.has(valueLowerCase) ) { return; } diff --git a/lib/utils/isContextFunctionalPseudoClass.js b/lib/utils/isContextFunctionalPseudoClass.js index a5b6feb1f3..c4d0246668 100644 --- a/lib/utils/isContextFunctionalPseudoClass.js +++ b/lib/utils/isContextFunctionalPseudoClass.js @@ -1,6 +1,9 @@ 'use strict'; -const keywordSets = require('../reference/keywordSets'); +const { + aNPlusBOfSNotationPseudoClasses, + logicalCombinationsPseudoClasses, +} = require('../reference/selectors'); /** * Check whether a node is a context-functional pseudo-class (i.e. either a logical combination @@ -14,8 +17,8 @@ module.exports = function isContextFunctionalPseudoClass(node) { const normalisedParentName = node.value.toLowerCase().replace(/:+/, ''); return ( - keywordSets.logicalCombinationsPseudoClasses.has(normalisedParentName) || - keywordSets.aNPlusBOfSNotationPseudoClasses.has(normalisedParentName) + logicalCombinationsPseudoClasses.has(normalisedParentName) || + aNPlusBOfSNotationPseudoClasses.has(normalisedParentName) ); } diff --git a/lib/utils/isCounterIncrementCustomIdentValue.js b/lib/utils/isCounterIncrementCustomIdentValue.js index 21593005c1..180999b406 100644 --- a/lib/utils/isCounterIncrementCustomIdentValue.js +++ b/lib/utils/isCounterIncrementCustomIdentValue.js @@ -1,6 +1,6 @@ 'use strict'; -const keywordSets = require('../reference/keywordSets'); +const { counterIncrementKeywords } = require('../reference/keywords'); /** * Check value is a custom ident @@ -11,7 +11,7 @@ module.exports = function (value) { const valueLowerCase = value.toLowerCase(); if ( - keywordSets.counterIncrementKeywords.has(valueLowerCase) || + counterIncrementKeywords.has(valueLowerCase) || Number.isFinite(Number.parseInt(valueLowerCase, 10)) ) { return false; diff --git a/lib/utils/isCounterResetCustomIdentValue.js b/lib/utils/isCounterResetCustomIdentValue.js index 8697f6b483..5de6e72150 100644 --- a/lib/utils/isCounterResetCustomIdentValue.js +++ b/lib/utils/isCounterResetCustomIdentValue.js @@ -1,6 +1,6 @@ 'use strict'; -const keywordSets = require('../reference/keywordSets'); +const { counterResetKeywords } = require('../reference/keywords'); /** * Check value is a custom ident @@ -11,7 +11,7 @@ module.exports = function (value) { const valueLowerCase = value.toLowerCase(); if ( - keywordSets.counterResetKeywords.has(valueLowerCase) || + counterResetKeywords.has(valueLowerCase) || Number.isFinite(Number.parseInt(valueLowerCase, 10)) ) { return false; diff --git a/lib/utils/isCustomElement.js b/lib/utils/isCustomElement.js index 58b2959746..d43d13826f 100644 --- a/lib/utils/isCustomElement.js +++ b/lib/utils/isCustomElement.js @@ -1,6 +1,6 @@ 'use strict'; -const keywordSets = require('../reference/keywordSets'); +const { htmlTypeSelectors } = require('../reference/selectors'); const mathMLTags = require('mathml-tag-names'); const svgTags = require('svg-tags'); @@ -29,11 +29,7 @@ module.exports = function (selector) { return false; } - if (keywordSets.standardHtmlTags.has(selectorLowerCase)) { - return false; - } - - if (keywordSets.nonStandardHtmlTags.has(selectorLowerCase)) { + if (htmlTypeSelectors.has(selectorLowerCase)) { return false; } diff --git a/lib/utils/isKeyframeSelector.js b/lib/utils/isKeyframeSelector.js index 6fd062cd0a..a8734b2456 100644 --- a/lib/utils/isKeyframeSelector.js +++ b/lib/utils/isKeyframeSelector.js @@ -1,6 +1,6 @@ 'use strict'; -const keywordSets = require('../reference/keywordSets'); +const { keyframeSelectorKeywords } = require('../reference/keywords'); /** * Check whether a string is a keyframe selector. @@ -9,7 +9,7 @@ const keywordSets = require('../reference/keywordSets'); * @returns {boolean} */ module.exports = function (selector) { - if (keywordSets.keyframeSelectorKeywords.has(selector)) { + if (keyframeSelectorKeywords.has(selector)) { return true; } diff --git a/lib/utils/isMathFunction.js b/lib/utils/isMathFunction.js index 0b36492f9c..e917758754 100644 --- a/lib/utils/isMathFunction.js +++ b/lib/utils/isMathFunction.js @@ -1,6 +1,6 @@ 'use strict'; -const mathFunctions = require('../reference/mathFunctions'); +const { mathFunctions } = require('../reference/functions'); /** * Check whether a node is math function diff --git a/lib/utils/isStandardSyntaxTypeSelector.js b/lib/utils/isStandardSyntaxTypeSelector.js index 3bf35e4bf5..69c7d2513a 100644 --- a/lib/utils/isStandardSyntaxTypeSelector.js +++ b/lib/utils/isStandardSyntaxTypeSelector.js @@ -1,6 +1,11 @@ 'use strict'; -const keywordSets = require('../reference/keywordSets'); +const { + aNPlusBNotationPseudoClasses, + aNPlusBOfSNotationPseudoClasses, + linguisticPseudoClasses, + shadowTreePseudoElements, +} = require('../reference/selectors'); /** * Check whether a type selector is standard @@ -26,10 +31,10 @@ module.exports = function (node) { if ( parentType === 'pseudo' && - (keywordSets.aNPlusBNotationPseudoClasses.has(normalisedParentName) || - keywordSets.aNPlusBOfSNotationPseudoClasses.has(normalisedParentName) || - keywordSets.linguisticPseudoClasses.has(normalisedParentName) || - keywordSets.shadowTreePseudoElements.has(normalisedParentName)) + (aNPlusBNotationPseudoClasses.has(normalisedParentName) || + aNPlusBOfSNotationPseudoClasses.has(normalisedParentName) || + linguisticPseudoClasses.has(normalisedParentName) || + shadowTreePseudoElements.has(normalisedParentName)) ) { return false; } diff --git a/lib/utils/isValidFontSize.js b/lib/utils/isValidFontSize.js index 7cf16802a0..5c622741b1 100644 --- a/lib/utils/isValidFontSize.js +++ b/lib/utils/isValidFontSize.js @@ -1,6 +1,7 @@ 'use strict'; -const keywordSets = require('../reference/keywordSets'); +const { fontSizeKeywords } = require('../reference/keywords'); +const { lengthUnits } = require('../reference/units'); const valueParser = require('postcss-value-parser'); /** @@ -14,7 +15,7 @@ module.exports = function (word) { return false; } - if (keywordSets.fontSizeKeywords.has(word)) { + if (fontSizeKeywords.has(word)) { return true; } @@ -30,7 +31,7 @@ module.exports = function (word) { return true; } - if (keywordSets.lengthUnits.has(unit.toLowerCase())) { + if (lengthUnits.has(unit.toLowerCase())) { return true; } diff --git a/lib/utils/uniteSets.js b/lib/utils/uniteSets.js new file mode 100644 index 0000000000..6c089bd8cc --- /dev/null +++ b/lib/utils/uniteSets.js @@ -0,0 +1,8 @@ +/** + * Unite two or more sets + * + * @param {Iterable[]} args + */ +module.exports = function uniteSets(...args) { + return new Set([...args].reduce((result, set) => [...result, ...set], [])); +};