'use strict'; var multimatch = require('multimatch'); var browserslist = require('browserslist'); var caniuse = require('caniuse-lite'); var postcss = require('postcss'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n["default"] = e; return Object.freeze(n); } var multimatch__default = /*#__PURE__*/_interopDefaultLegacy(multimatch); var browserslist__default = /*#__PURE__*/_interopDefaultLegacy(browserslist); var caniuse__namespace = /*#__PURE__*/_interopNamespace(caniuse); /** * No description available. * * See: This feature comes from MDN: https://developer.mozilla.org/en-US/search?q=Alternate+stylesheet */ // This feature is only in HTML, so we don't lint it /** * @type {import('../features').Feature} */ var alternateStylesheet = {}; /** * Method of defining how a background image is attached to a scrollable element. Values include `scroll` (default), `fixed` and `local`. * * See: https://caniuse.com/background-attachment */ /** * @type {import('../features').Feature} */ var backgroundAttachment = { 'background-attachment': [ 'fixed', 'local', ], }; /** * Non-standard method of clipping a background image to the foreground text. * * See: https://caniuse.com/background-clip-text */ /** * @type {import('../features').Feature} */ var backgroundClipText = { 'background-clip': 'text', '-webkit-background-clip': 'text', }; var backgroundImgOpts = { 'background-clip': true, 'background-origin': true, 'background-size': true, }; var backgroundPositionXY = { 'background-position-x': true, 'background-position-y': true, }; /** * Allows CSS background images to be repeated without clipping. * * See: https://caniuse.com/background-repeat-round-space */ /** * @type {import('../features').Feature} */ var backgroundRepeatRoundSpace = { 'background-repeat': ['round', 'space'], }; var borderImage = { 'border-image': true, 'border-image-outset': true, 'border-image-repeat': true, 'border-image-slice': true, 'border-image-source': true, 'border-image-width': true, }; var borderRadius = { 'border-radius': true, 'border-top-left-radius': true, 'border-top-right-radius': true, 'border-bottom-right-radius': true, 'border-bottom-left-radius': true, }; var calc = { '': 'calc(', }; /** @typedef {RegExp|string|((value:string) => boolean)} FeatureCheck */ /** * @param {string} browserKey * @param {string[]} [versions] * @return {string} */ function formatBrowserName(browserKey, versions) { const entry = caniuse.agents[browserKey]; const browserName = entry ? entry.browser : null; if (!versions) { return browserName || ''; } return (`${browserName} (${versions.join(',')})`); } /** * * @param {FeatureCheck|FeatureCheck[]} check * @param {?string|undefined} candidate */ function performFeatureCheck(check, candidate) { if (check == null || candidate == null) return false; if (check instanceof RegExp) { return check.test(candidate); } switch (typeof check) { case 'string': return candidate.includes(check); case 'function': return check(candidate); case 'boolean': return check; case 'object': if (Array.isArray(check)) { return check.some((c) => performFeatureCheck(c, candidate)); } // Fallthrough default: console.error(check); throw new TypeError(`Unexpected feature check: ${check}`); } } /** * @param {FeatureCheck|FeatureCheck[]} selector * @return {(rule:import('postcss').ChildNode) => boolean} */ function checkSelector(selector) { return (rule) => rule.type === 'rule' && performFeatureCheck(selector, rule.selector); } /** * @param {FeatureCheck|FeatureCheck[]} [name] * @param {FeatureCheck|FeatureCheck[]} [parameters] * @return {(rule:import('postcss').ChildNode) => boolean} */ function checkAtRule(name, parameters) { return (rule) => rule.type === 'atrule' && performFeatureCheck(name, rule.name) && (!parameters || performFeatureCheck(parameters, rule.params)); } /** * @see https://drafts.csswg.org/css-values/#lengths * @see https://drafts.csswg.org/css-values/#number-value * @param {string[]} units * @return {(rule:import('postcss').ChildNode) => boolean} */ function checkCSSLengthUnits(...units) { const regexp = new RegExp(`(\\+-)?[\\d.]*\\.?\\d+(e(\\+-)?\\d+)?(${units.join('|')})`, 'i'); return (rule) => ( (rule.type === 'decl') ? performFeatureCheck(regexp, rule.value) : ((rule.type === 'atrule') ? performFeatureCheck(regexp, rule.params) : false)); } /** * Unit representing the width of the character "0" in the current font, of particular use in combination with monospace fonts. * @see https://caniuse.com/ch-unit * @type {import('../features').Feature} */ var chUnit = checkCSSLengthUnits('ch'); var cssAll = { 'all': true, }; var cssAnimation = { 'animation': true, 'animation-name': true, 'animation-duration': true, 'animation-timing-function': true, 'animation-iteration-count': true, 'animation-direction': true, 'animation-play-state': true, 'animation-delay': true, 'animation-fill-mode': true, }; // @keyframes isn't checked for, but if you try to use it, // you'll still get a warning anyway because of the 'animation' property var cssAnyLink = checkSelector([':any-link', ':-webkit-any-link']); var cssAppearance = { 'appearance': true, '-webkit-appearance': true, '-moz-appearance': true, }; var cssAtCounterStyle = checkAtRule('counter-style'); var cssAutofill = checkSelector([':autofill', ':-webkit-autofill']); var cssBackdropFilter = { 'backdrop-filter': true, }; /** * @param {import('postcss').ChildNode} rule * @return {boolean} */ var cssBackgroundOffsets = (rule) => { if (rule.type !== 'decl') return false; if (rule.prop !== 'background-position') return false; return postcss.list.space(rule.value).length > 2; }; var cssBackgroundblendmode = { 'background-blend-mode': true, }; /** * Controls whether the box's margins, borders, padding, and other decorations wrap the broken edges of the box fragments (when the box is split by a break (page/column/region/line). * * See: https://caniuse.com/css-boxdecorationbreak */ /** * @type {import('../features').Feature} */ var cssBoxdecorationbreak = { 'box-decoration-break': true, '-webkit-box-decoration-break': true, }; var cssBoxshadow = { 'box-shadow': true, }; /** * @param {import('postcss').ChildNode} rule * @return {boolean} */ var cssCanvas = (rule) => { if (rule.type !== 'decl') return false; if (!rule.prop.startsWith('background')) return false; return rule.value.startsWith('-webkit-canvas'); }; /** * The `caret-color` property allows the color to be set of the caret (blinking text insertion pointer) in an editable text area. * * See: https://caniuse.com/css-caret-color */ /** * @type {import('../features').Feature} */ var cssCaretColor = { 'caret-color': true, }; /** * The `@layer` at-rule allows authors to explicitly layer their styles in the cascade, before specificity and order of appearance are considered. * * See: https://caniuse.com/css-cascade-layers */ /** * @type {import('../features').Feature} */ var cssCascadeLayers = checkAtRule('layer'); /** * Including an `i` before the `]` in a CSS attribute selector causes the attribute value to be matched in an ASCII-case-insensitive manner. For example, `[b="xyz" i]` would match both `` and ``. * * See: https://caniuse.com/css-case-insensitive */ /** * @type {import('../features').Feature} */ var cssCaseInsensitive = (rule) => { if (rule.type !== 'rule') { return false; } if (/\[.*i]/.test(rule.selector)) { return true; } return false; }; var cssClipPath = { 'clip-path': true, }; /** * The `print-color-adjust` (or `-webkit-print-color-adjust` as prefixed in WebKit/Blink browsers) property is a CSS extension that can be used to force printing of background colors and images. * * See: https://caniuse.com/css-color-adjust */ /** * @type {import('../features').Feature} */ var cssColorAdjust = { 'print-color-adjust': true, '-webkit-print-color-adjust': true, }; /** * The CSS `color()` function allows the browser to display colors in any color space, such as the P3 color space which can display colors outside of the default sRGB color space. * * See: https://caniuse.com/css-color-function */ /** * @type {import('../features').Feature} */ var cssColorFunction = { '': 'color(', }; const REGEX$2 = /(^|[^-])(repeating-)?conic-gradient/; var cssConicGradients = { 'background': REGEX$2, 'background-image': REGEX$2, 'border-image': REGEX$2, 'border-image-source': REGEX$2, 'content': REGEX$2, 'cursor': REGEX$2, 'list-style': REGEX$2, 'list-style-image': REGEX$2, }; /** * Size queries in Container Queries provide a way to query the size of a container, and conditionally apply CSS to the content of that container. * * See: https://caniuse.com/css-container-queries */ /** * @type {import('../features').Feature} */ var cssContainerQueries = checkAtRule('container'); var cssContainerQueriesStyle = checkAtRule('container', 'style('); var cssContainerQueryUnits = checkCSSLengthUnits( 'cqw', 'cqh', 'cqi', 'cqb', 'cqmin', 'cqmax', ); /** * The CSS `contain` property lets developers limit the scope of the browser's styles, layout and paint work for faster and more efficient rendering. * * See: https://caniuse.com/css-containment */ /** * @type {import('../features').Feature} */ var cssContainment = { 'contain': true, }; /** * Provides control over when elements are rendered, so rendering can be skipped for elements not yet in the user's viewport. * * See: https://caniuse.com/css-content-visibility */ /** * @type {import('../features').Feature} */ var cssContentVisibility = { 'content-visibility': true, }; var cssCounters = { 'counter-reset': true, 'counter-increment': true, '': 'counter(', }; /** * Scales images with an algorithm that preserves edges and contrast, without smoothing colors or introducing blur. This is intended for images such as pixel art. Official values that accomplish this for the `image-rendering` property are `crisp-edges` and `pixelated`. * * See: https://caniuse.com/css-crisp-edges */ /** * @type {import('../features').Feature} */ var cssCrispEdges = { 'image-rendering': ['crisp-edges', 'pixelated'], }; /** * Image function to create a "crossfade" between images. This allows one image to transition (fade) into another based on a percentage value. * * See: https://caniuse.com/css-cross-fade */ /** * @type {import('../features').Feature} */ var cssCrossFade = { '': [ 'cross-fade(', '-webkit-cross-fade(', ], }; /** * The `:default` pseudo-class matches checkboxes and radio buttons which are checked by default, `` elements that contain an `` child. * @see https://caniuse.com/css-has */ /** * @type {import('../features').Feature} */ var cssHas = checkSelector(':has'); var cssHyphens = { 'hyphens': true, }; var cssImageOrientation = { 'image-orientation': true, }; /** * Method of letting the browser pick the most appropriate CSS image from a given set. * @see https://caniuse.com/css-image-set */ /** * @type {import('../features').Feature} */ var cssImageSet = { '': 'image-set(', }; /** * If a temporal or number `` has `max` and/or `min` attributes, then `:in-range` matches when the value is within the specified range and `:out-of-range` matches when the value is outside the specified range. If there are no range constraints, then neither pseudo-class matches. * @see https://caniuse.com/css-in-out-of-range */ /** * @type {import('../features').Feature} */ var cssInOutOfRange = checkSelector([ ':in-range', ':out-of-range', ]); /** * The `:indeterminate` pseudo-class matches indeterminate checkboxes, indeterminate `` bars, and radio buttons with no checked button in their radio button group. * @see https://caniuse.com/css-indeterminate-pseudo */ /** * @type {import('../features').Feature} */ var cssIndeterminatePseudo = checkSelector(':indeterminate'); /** * Method of creating an enlarged cap, including a drop or raised cap, in a robust way. * @see https://caniuse.com/css-initial-letter */ /** * @type {import('../features').Feature} */ var cssInitialLetter = { 'initial-letter': true, }; var cssInitialValue = { '': 'initial', }; /** * The `lch()` and `lab()` color functions are based on the CIE LAB color space, representing colors in a way that closely matches human perception and provides access to a wider spectrum of colors than offered by the usual RGB color space. * @see https://caniuse.com/css-lch-lab */ /** * @type {import('../features').Feature} */ var cssLchLab = { '': [ 'lch(', 'lab(', ], }; /** * Controls spacing between characters of text (i.e. "tracking" in typographical terms). Not to be confused with kerning. * @see https://caniuse.com/css-letter-spacing */ /** * @type {import('../features').Feature} */ var cssLetterSpacing = { 'letter-spacing': true, }; /** * CSS property that will contain text to a given amount of lines when used in combination with `display: -webkit-box`. It will end with ellipsis when `text-overflow: ellipsis` is included. * @see https://caniuse.com/css-line-clamp */ /** * @type {import('../features').Feature} */ var cssLineClamp = { 'line-clamp': true, '-webkit-line-clamp': true, }; var cssLogicalProps = { 'block-size': true, 'inline-size': true, 'min-block-size': true, 'min-inline-size': true, 'max-block-size': true, 'max-inline-size': true, 'margin-block-start': true, 'margin-block-end': true, 'margin-inline-start': true, 'margin-inline-end': true, 'margin-block': true, 'margin-inline': true, 'inset-block-start': true, 'inset-block-end': true, 'inset-inline-start': true, 'inset-inline-end': true, 'inset-block': true, 'inset-inline': true, 'inset': true, 'padding-block-start': true, 'padding-block-end': true, 'padding-inline-start': true, 'padding-inline-end': true, 'padding-block': true, 'padding-inline': true, 'border-block-start-width': true, 'border-block-end-width': true, 'border-inline-start-width': true, 'border-inline-end-width': true, 'border-block-width': true, 'border-inline-width': true, 'border-block-start-style': true, 'border-block-end-style': true, 'border-inline-start-style': true, 'border-inline-end-style': true, 'border-block-style': true, 'border-inline-style': true, 'border-block-start-color': true, 'border-block-end-color': true, 'border-inline-start-color': true, 'border-inline-end-color': true, 'border-block-color': true, 'border-inline-color': true, 'border-block-start': true, 'border-block-end': true, 'border-inline-start': true, 'border-inline-end': true, 'border-block': true, 'border-inline': true, 'border-start-start-radius': true, 'border-start-end-radius': true, 'border-end-start-radius': true, 'border-end-end-radius': true, 'text-align': ['start', 'end'], 'float': ['inline-start', 'inline-end'], 'resize': ['block', 'inline'], 'overflow-block': true, 'overflow-inline': true, }; /** * The `::marker` pseudo-element allows list item markers to be styled or have their content value customized. * @see https://caniuse.com/css-marker-pseudo */ /** * @type {import('../features').Feature} */ var cssMarkerPseudo = checkSelector(':marker'); var cssMasks = { 'clip-path': true, 'mask': true, 'mask-border': true, 'mask-border-mode': true, 'mask-border-outset': true, 'mask-border-repeat': true, 'mask-border-slice': true, 'mask-border-source': true, 'mask-border-width': true, 'mask-clip': true, 'mask-composite': true, 'mask-image': true, 'mask-mode': true, 'mask-origin': true, 'mask-position': true, 'mask-repeat': true, 'mask-size': true, 'mask-type': true, // and webkit versions '-webkit-clip-path': true, '-webkit-mask': true, '-webkit-mask-border': true, '-webkit-mask-border-mode': true, '-webkit-mask-border-outset': true, '-webkit-mask-border-repeat': true, '-webkit-mask-border-slice': true, '-webkit-mask-border-source': true, '-webkit-mask-border-width': true, '-webkit-mask-clip': true, '-webkit-mask-composite': true, '-webkit-mask-image': true, '-webkit-mask-mode': true, '-webkit-mask-origin': true, '-webkit-mask-position': true, '-webkit-mask-repeat': true, '-webkit-mask-size': true, '-webkit-mask-type': true, }; var cssMatchesPseudo = checkSelector([ ':is', ':where', ':matches', ':any', ':-webkit-any', ':-webkit-is', ':-webkit-where', ':-webkit-matches', ]); var cssMathFunctions = { '': ['min(', 'max(', 'clamp('], }; /** * Allows a media query to be set based on the presence and accuracy of the user's pointing device, and whether they have the ability to hover over elements on the page. This includes the `pointer`, `any-pointer`, `hover`, and `any-hover` media features. * @see https://caniuse.com/css-media-interaction */ /** * @type {import('../features').Feature} */ var cssMediaInteraction = checkAtRule('media', [ 'pointer', 'any-pointer', 'hover', 'any-hover', ]); var cssMediaRangeSyntax = checkAtRule('media', [' > ', ' < ', ' <= ', ' >= ']); var cssMediaResolution = checkAtRule('media', ['min-resolution', 'max-resolution', 'resolution', 'device-pixel-ratio']); /** * No description available. * @see This feature comes from MDN: https://developer.mozilla.org/en-US/search?q=Media+Queries:+scripting+media+feature */ /** * @type {import('../features').Feature} */ var cssMediaScripting = checkAtRule('media', ['scripting']); var cssMediaqueries = checkAtRule(['media']); var cssMixblendmode = { 'mix-blend-mode': true, }; var cssMotionPaths = { 'offset-path': true, }; /** * Using the `@namespace` at-rule, elements of other namespaces (e.g. SVG) can be targeted using the pipe (`|`) selector. * @see https://caniuse.com/css-namespaces */ /** * @type {import('../features').Feature} */ var cssNamespaces = checkAtRule('namespace'); /** * CSS nesting provides the ability to nest one style rule inside another, with the selector of the child rule relative to the selector of the parent rule. Similar behavior previously required a CSS pre-processor. * @see https://caniuse.com/css-nesting */ /** * @type {import('../features').Feature} */ var cssNesting = (rule) => { if (rule.type === 'rule' && rule.parent.type === 'rule') { return true; } if (rule.type === 'atrule' && rule.parent.type === 'rule') { return true; } return false; }; /** * Selectors Level 3 only allowed `:not()` pseudo-class to accept a single simple selector, which the element must not match any of. Thus, `:not(a, .b, [c])` or `:not(a.b[c])` did not work. Selectors Level 4 allows `:not()` to accept a list of selectors. Thus, `:not(a):not(.b):not([c])` can instead be written as `:not(a, .b, [c])` and `:not(a.b[c])` works as intended. * @see https://caniuse.com/css-not-sel-list */ /** * @type {import('../features').Feature} */ var cssNotSelList = checkSelector( (selector) => selector.includes(':not(') && !/:not\(.?#?-?[\w[\]-]+\)/.test(selector), ); /** * The newest versions of `:nth-child()` and `:nth-last-child()` accept an optional `of S` clause which filters the children to only those which match the selector list `S`. For example, `:nth-child(1 of .foo)` selects the first child among the children that have the `foo` class (ignoring any non-`foo` children which precede that child). Similar to `:nth-of-type`, but for arbitrary selectors instead of only type selectors. * @see https://caniuse.com/css-nth-child-of */ /** * @type {import('../features').Feature} */ var cssNthChildOf = checkSelector( (selector) => /:nth-(child|last-child)\(\s*\d+\s*of/.test(selector), ); var cssOpacity = { 'opacity': true, }; /** * The `:optional` pseudo-class matches form inputs (``, `