diff options
Diffstat (limited to 'node_modules/doiuse/exports/stream.cjs')
| -rw-r--r-- | node_modules/doiuse/exports/stream.cjs | 3087 |
1 files changed, 0 insertions, 3087 deletions
diff --git a/node_modules/doiuse/exports/stream.cjs b/node_modules/doiuse/exports/stream.cjs deleted file mode 100644 index 982a0d35..00000000 --- a/node_modules/doiuse/exports/stream.cjs +++ /dev/null @@ -1,3087 +0,0 @@ -'use strict'; - -var node_stream = require('node:stream'); -var Tokenize = require('css-tokenize'); -var Duplexify = require('duplexify'); -var postcss = require('postcss'); -var sourcemap = require('source-map'); -var multimatch = require('multimatch'); -var browserslist = require('browserslist'); -var caniuse = require('caniuse-lite'); - -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 Tokenize__default = /*#__PURE__*/_interopDefaultLegacy(Tokenize); -var Duplexify__default = /*#__PURE__*/_interopDefaultLegacy(Duplexify); -var postcss__default = /*#__PURE__*/_interopDefaultLegacy(postcss); -var sourcemap__default = /*#__PURE__*/_interopDefaultLegacy(sourcemap); -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 `<a b="xyz">` and `<a b="XYZ">`. - * - * 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, `<option>`s with the `selected` attribute, and the default submit button (if any) of a form. - * - * See: https://caniuse.com/css-default-pseudo - */ - -/** - * @type {import('../features').Feature} - */ -var cssDefaultPseudo = checkSelector(':default'); - -/** - * An explicit, non-whitespace spelling of the descendant combinator. `A >> B` is equivalent to `A B`. - * - * See: https://caniuse.com/css-descendant-gtgt - */ - -/** - * @type {import('../features').Feature} - */ -var cssDescendantGtgt = checkSelector('>>'); - -/** - * Method of overriding the size of viewport in web page using the `@viewport` rule, replacing Apple's own popular `<meta>` viewport implementation. Includes the `extend-to-zoom` width value. - * - * See: https://caniuse.com/css-deviceadaptation - */ - -/** - * @type {import('../features').Feature} - */ -var cssDeviceadaptation = checkAtRule('viewport'); - -/** - * Matches elements based on their directionality. `:dir(ltr)` matches elements which are Left-to-Right. `:dir(rtl)` matches elements which are Right-to-Left. - * - * See: https://caniuse.com/css-dir-pseudo - */ - -/** - * @type {import('../features').Feature} - */ -var cssDirPseudo = checkSelector(':dir('); - -/** - * `display: contents` causes an element's children to appear as if they were direct children of the element's parent, ignoring the element itself. This can be useful when a wrapper element should be ignored when using CSS grid or similar layout techniques. - * - * See: https://caniuse.com/css-display-contents - */ - -/** - * @type {import('../features').Feature} - */ -var cssDisplayContents = { - 'display': 'contents', -}; - -/** - * This function renders a live image generated from an arbitrary HTML element - * - * See: https://caniuse.com/css-element-function - */ - -/** - * @type {import('../features').Feature} - */ -var cssElementFunction = { - '': 'element(', -}; - -var cssEnvFunction = { - '': 'env(', -}; - -/** - * Exclusions defines how inline content flows around elements. It extends the content wrapping ability of floats to any block-level element. - * - * See: https://caniuse.com/css-exclusions - */ - -/** - * @type {import('../features').Feature} - */ -var cssExclusions = { - 'wrap-flow': true, - '-ms-wrap-flow': true, -}; - -var cssFeaturequeries = checkAtRule(['supports']); - -/** - * No description available. - * - * See: This feature comes from MDN: https://developer.mozilla.org/en-US/search?q=::file-selector-button+CSS+pseudo-element - */ - -/** - * @type {import('../features').Feature} - */ -var cssFileSelectorButton = checkSelector(':file-selector-button'); - -/** - * This function filters a CSS input image with a set of filter functions (like blur, grayscale or hue) - * - * See: https://caniuse.com/css-filter-function - */ - -/** - * @type {import('../features').Feature} - */ -var cssFilterFunction = { - '': 'filter(', -}; - -var cssFilters = { - 'filter': true, -}; - -/** - * CSS pseudo-element that allows styling only the first "letter" of text within an element. Useful for implementing initial caps or drop caps styling. - * - * See: https://caniuse.com/css-first-letter - */ - -/** - * @type {import('../features').Feature} - */ -var cssFirstLetter = checkSelector(':first-letter'); - -/** - * Allows styling specifically for the first line of text using the `::first-line` pseudo-element. Note that only a limited set of properties can be applied. - * - * See: https://caniuse.com/css-first-line - */ - -/** - * @type {import('../features').Feature} - */ -var cssFirstLine = checkSelector(':first-line'); - -var cssFixed = { - 'position': 'fixed', -}; - -/** - * The `:focus-visible` pseudo-class applies while an element matches the `:focus` pseudo-class, and the UA determines via heuristics that the focus should be specially indicated on the element (typically via a “focus ring”). - * - * See: https://caniuse.com/css-focus-visible - */ - -/** - * @type {import('../features').Feature} - */ -var cssFocusVisible = checkSelector(':focus-visible'); - -/** - * The `:focus-within` pseudo-class matches elements that either themselves match `:focus` or that have descendants which match `:focus`. - * - * See: https://caniuse.com/css-focus-within - */ - -/** - * @type {import('../features').Feature} - */ -var cssFocusWithin = checkSelector(':focus-within'); - -var cssFontPalette = [ - (rule) => performFeatureCheck('font-palette', rule.name), - checkAtRule('font-palette-values'), -]; - -/** - * `@font-face` descriptor `font-display` that allows control over how a downloadable font renders before it is fully loaded. - * - * See: https://caniuse.com/css-font-rendering-controls - */ - -/** - * @type {import('../features').Feature} - */ -var cssFontRenderingControls = { - 'font-display': true, -}; - -var cssFontStretch = { - 'font-stretch': true, -}; - -var cssGencontent = checkSelector([':before', ':after']); - -const REGEX$1 = /(^|[^-])((linear)|(radial))-gradient/; - -var cssGradients = { - 'background': REGEX$1, - 'background-image': REGEX$1, - 'border-image': REGEX$1, - 'border-image-source': REGEX$1, - 'content': REGEX$1, - 'cursor': REGEX$1, - 'list-style': REGEX$1, - 'list-style-image': REGEX$1, -}; - -/** @see https://drafts.csswg.org/css-grid/ */ - -var cssGrid = { - 'display': ['grid', 'inline-grid', '-ms-grid'], - 'grid': true, - 'grid-area': true, - 'grid-auto-columns': true, - - 'grid-auto-flow': true, - 'grid-auto-rows': true, - 'grid-column': true, - 'grid-column-end': true, - - 'grid-column-start': true, - 'grid-row': true, - 'grid-row-end': true, - 'grid-row-start': true, - - 'grid-template': true, - 'grid-template-areas': true, - 'grid-template-columns': true, - 'grid-template-rows': true, -}; - -const REGEX = /grid/; - -var cssGridAnimation = { - 'transition': REGEX, - 'transition-property': REGEX, -}; - -/** - * Allows some punctuation characters from start (or the end) of text elements to be placed "outside" of the box in order to preserve the reading flow. - * @see https://caniuse.com/css-hanging-punctuation - */ - -/** - * @type {import('../features').Feature} - */ -var cssHangingPunctuation = { - 'hanging-punctuation': true, -}; - -/** - * Select elements containing specific content. For example, `a:has(img)` selects all `<a>` elements that contain an `<img>` 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 `<input>` 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 `<progress>` 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 (`<input>`, `<textarea>`, `<select>`) which are not `:required`. - * @see https://caniuse.com/css-optional-pseudo - */ - -/** - * @type {import('../features').Feature} - */ -var cssOptionalPseudo = checkSelector(':optional'); - -/** - * Originally a single property for controlling overflowing content in both horizontal & vertical directions, the `overflow` property is now a shorthand for `overflow-x` & `overflow-y`. The latest version of the specification also introduces the `clip` value that blocks programmatic scrolling. - * @see https://caniuse.com/css-overflow - */ - -/** - * @type {import('../features').Feature} - */ -var cssOverflow = { - 'overflow': true, - 'overflow-x': true, - 'overflow-y': true, -}; - -/** - * Changes in DOM elements above the visible region of a scrolling box can result in the page moving while the user is in the middle of consuming the content. By default, the value of `overflow-anchor` is `auto`, it can mitigate this jarring user experience by keeping track of the position of an anchor node and adjusting the scroll offset accordingly - * @see https://caniuse.com/css-overflow-anchor - */ - -/** - * @type {import('../features').Feature} - */ -var cssOverflowAnchor = { - 'overflow-anchor': true, -}; - -var cssOverflowOverlay = { - 'overflow': 'overlay', -}; - -var cssOverscrollBehavior = { - 'overscroll-behavior': true, - 'overscroll-behavior-x': true, - 'overscroll-behavior-y': true, -}; - -/** - * Properties to control the way elements are broken across (printed) pages. - * @see https://caniuse.com/css-page-break - */ - -/** - * @type {import('../features').Feature} - */ -var cssPageBreak = { - 'page-break-after': true, - 'page-break-before': true, - 'page-break-inside': true, -}; - -/** - * CSS at-rule (`@page`) to define page-specific rules when printing web pages, such as margin per page and page dimensions. - * @see https://caniuse.com/css-paged-media - */ - -/** - * @type {import('../features').Feature} - */ -var cssPagedMedia = checkAtRule('page'); - -/** - * Allows programmatic generation of images used by CSS - * @see https://caniuse.com/css-paint-api - */ - -/** - * @type {import('../features').Feature} - */ -var cssPaintApi = { '': 'paint(' }; - -var cssPlaceholder = [ - checkSelector(':placeholder'), -]; - -/** - * :placeholder-shown CSS pseudo-class - * Input elements can sometimes show placeholder text as a hint to the user on what to type in. See, for example, the placeholder attribute in HTML5. The :placeholder-shown pseudo-class matches an input element that is showing such placeholder text. - * @see https://caniuse.com/css-placeholder-shown - */ - -/** - * @type {import('../features').Feature} - */ -var cssPlaceholderShown = checkSelector(':placeholder-shown'); - -var cssPrintColorAdjust = { - 'print-color-adjust': true, -}; - -/** - * CSS :read-only and :read-write selectors - * :read-only and :read-write pseudo-classes to match elements which are considered user-alterable - * @see https://caniuse.com/css-read-only-write - */ - -/** - * @type {import('../features').Feature} - */ -var cssReadOnlyWrite = checkSelector([':read-only', ':read-write']); - -/** - * Rebeccapurple color - * The new color added in CSS Color Module Level 4 - * @see https://caniuse.com/css-rebeccapurple - */ - -/** - * @type {import('../features').Feature} - */ -var cssRebeccapurple = { - '': 'rebeccapurple', -}; - -var cssReflections = { - 'box-reflect': true, - '-webkit-box-reflect': true, -}; - -/** - * CSS Regions - * Method of flowing content into multiple elements, allowing magazine-like layouts. While once supported in WebKit-based browsers and Internet Explorer, implementing the feature is no longer being pursued by any browser. - * @see https://caniuse.com/css-regions - */ - -/** - * @type {import('../features').Feature} - */ -var cssRegions = { - 'flow-into': true, - 'flow-from': true, - '-webkit-flow-into': true, - '-webkit-flow-from': true, -}; - -/** - * CSS Relative colors - * The CSS Relative Color syntax allows a color to be defined relative to another color using the `from` keyword and optionally `calc()` for any of the color values. - * @see https://caniuse.com/css-relative-colors - */ - -/** - * @type {import('../features').Feature} - */ -var cssRelativeColors = { - '': /((rgb)|(rgba)|(hsl)|(hsla)|(hwb))\(\s*from/, -}; - -var cssRepeatingGradients = { - '': [ - 'repeating-linear-gradient', - 'repeating-radial-gradient', - ], -}; - -var cssResize = { - 'resize': true, -}; - -var cssRevertValue = { - '': 'revert', - -}; - -/** - * #rrggbbaa hex color notation - * The CSS Color Module Level 4 defines new 4 & 8 character hex notation for color to include the opacity level. - * @see https://caniuse.com/css-rrggbbaa - */ - -/** - * @type {import('../features').Feature} - */ -var cssRrggbbaa = { - '': [ - /#[\da-f]{8}/i, - /#[\da-f]{4}(\W|$)/i, - ], -}; - -/** - * CSS Scroll-behavior - * Method of specifying the scrolling behavior for a scrolling box, when scrolling happens due to navigation or CSSOM scrolling APIs. - * @see https://caniuse.com/css-scroll-behavior - */ - -/** - * @type {import('../features').Feature} - */ -var cssScrollBehavior = { - 'scroll-behavior': true, -}; - -/** - * CSS @scroll-timeline - * CSS property that allows animations to be driven by a container's scroll position - * @see https://caniuse.com/css-scroll-timeline - */ - -const checkAt = checkAtRule('scroll-timeline'); - -/** - * @type {import('../features').Feature} - */ -var cssScrollTimeline = (node) => { - // check for @scroll-timeline - if (checkAt(node)) { - return true; - } - - // check for animation-timeline - if (node.type !== 'decl') return false; - if (node.prop.startsWith('animation-timeline')) { - return true; - } - - return false; -}; - -var cssScrollbar = { - 'scrollbar-color': true, - 'scrollbar-width': true, -}; - -const ATTRIBUTE_IDENTIFIER$1 = '[^\\~|^$*\\]]*'; - -// Export for testing -const REGEXES$1 = { - 'HAS_ATTRIBUTE': new RegExp(`\\[${ATTRIBUTE_IDENTIFIER$1}\\]`), - 'MATCH_ATTRIBUTE': new RegExp(`\\[${ATTRIBUTE_IDENTIFIER$1}=${ATTRIBUTE_IDENTIFIER$1}\\]`), - 'WORD_ATTRIBUTE': new RegExp(`\\[${ATTRIBUTE_IDENTIFIER$1}\\~=${ATTRIBUTE_IDENTIFIER$1}\\]`), - 'SUBCODE_ATTRIBUTE': new RegExp(`\\[${ATTRIBUTE_IDENTIFIER$1}\\|=${ATTRIBUTE_IDENTIFIER$1}\\]`), - 'BRACKET_PARENS': /(\[[^=\]]*(=("[^"]*")|[^\]]+|)])|(\([^)]*\))/g, -}; - -/** - * @param {RegExp} pattern - * @return {(str:string) => boolean} - */ -function matchOutsideOfBrackets(pattern) { - if (!(pattern instanceof RegExp)) { - throw new TypeError('matchOutsideOfBrackets expects a RegExp'); - } - return (string) => pattern.test(string.replaceAll(REGEXES$1.BRACKET_PARENS, '')); -} - -var cssSel2 = checkSelector([ - ':first-child', - ':link', - ':visited', - ':active', - ':hover', - ':focus', - ':lang', - REGEXES$1.HAS_ATTRIBUTE, - REGEXES$1.MATCH_ATTRIBUTE, - REGEXES$1.WORD_ATTRIBUTE, - REGEXES$1.SUBCODE_ATTRIBUTE, - matchOutsideOfBrackets(/\*/), - matchOutsideOfBrackets(/>/), - matchOutsideOfBrackets(/\+/), - matchOutsideOfBrackets(/\./), - matchOutsideOfBrackets(/#/), -]); - -const ATTRIBUTE_IDENTIFIER = '[^\\~|^$*\\]]*'; - -// Export for testing -const REGEXES = { - 'SIBLING_SELECTOR': /^[^[]*~/, - 'STARTSWITH_ATTRIBUTE': new RegExp(`\\[${ATTRIBUTE_IDENTIFIER}\\^=${ATTRIBUTE_IDENTIFIER}\\]`), - 'ENDSWITH_ATTRIBUTE': new RegExp(`\\[${ATTRIBUTE_IDENTIFIER}\\$=${ATTRIBUTE_IDENTIFIER}\\]`), - 'INSENSITIVE_ATTRIBUTE': new RegExp(`\\[${ATTRIBUTE_IDENTIFIER}\\*=${ATTRIBUTE_IDENTIFIER}\\]`), -}; - -var cssSel3 = checkSelector([ - ':root', - ':nth-child', - ':nth-last-child', - 'nth-of-type', - 'nth-last-of-type', - ':last-child', - ':first-of-type', - ':last-of-type', - ':only-child', - ':only-of-type', - ':empty', - ':target', - ':enabled', - ':disabled', - ':checked', - ':not', - REGEXES.SIBLING_SELECTOR, - REGEXES.STARTSWITH_ATTRIBUTE, - REGEXES.ENDSWITH_ATTRIBUTE, - REGEXES.INSENSITIVE_ATTRIBUTE, -]); - -var cssSelection = checkSelector(':selection'); - -var cssShapes = { - 'shape-outside': true, - 'shape-image-threshold': true, - 'shape-margin': true, -}; - -/** - * CSS Scroll Snap - * CSS technique that allows customizable scrolling experiences like pagination of carousels by setting defined snap positions. - * @see https://caniuse.com/css-snappoints - */ - -/** - * @type {import('../features').Feature} - */ -var cssSnappoints = { - 'scroll-snap-type': true, - 'scroll-padding': true, - 'scroll-padding-top': true, - 'scroll-padding-right': true, - 'scroll-padding-bottom': true, - 'scroll-padding-left': true, - 'scroll-padding-inline': true, - 'scroll-padding-inline-start': true, - 'scroll-padding-inline-end': true, - 'scroll-padding-block': true, - 'scroll-padding-block-start': true, - 'scroll-padding-block-end': true, - 'scroll-snap-align': true, - 'scroll-margin': true, - 'scroll-margin-top': true, - 'scroll-margin-right': true, - 'scroll-margin-bottom': true, - 'scroll-margin-left': true, - 'scroll-margin-inline': true, - 'scroll-margin-inline-start': true, - 'scroll-margin-inline-end': true, - 'scroll-margin-block': true, - 'scroll-margin-block-start': true, - 'scroll-margin-block-end': true, - 'scroll-snap-stop': true, -}; - -var cssSticky = { - 'position': 'sticky', -}; - -/** - * CSS Subgrid - * Feature of the CSS Grid Layout Module Level 2 that allows a grid-item with its own grid to align in one or both dimensions with its parent grid. - * @see https://caniuse.com/css-subgrid - */ - -/** - * @type {import('../features').Feature} - */ -var cssSubgrid = { - '': 'subgrid', -}; - -/** - * CSS.supports() API - * The CSS.supports() static methods returns a Boolean value indicating if the browser supports a given CSS feature, or not. - * @see https://caniuse.com/css-supports-api - */ - -/** - * @type {import('../features').Feature} - */ -var cssSupportsApi = {}; - -/* this feature appears in JS, so it's not linted by this tool */ - -var cssTable = { - 'display': [ - 'table', - 'table-', - 'inline-table', - ], -}; - -/** - * CSS3 text-align-last - * CSS property to describe how the last line of a block or a line right before a forced line break when `text-align` is `justify`. - * @see https://caniuse.com/css-text-align-last - */ - -/** - * @type {import('../features').Feature} - */ -var cssTextAlignLast = { - 'text-align-last': true, -}; - -/** - * CSS text-box-trim & text-box-edge - * Provides the ability to remove the vertical space appearing above and below text glyphs, allowing more precise positioning and alignment. Previously specified as the `leading-trim` & `text-edge` properties. - * @see https://caniuse.com/css-text-box-trim - */ - -/** - * @type {import('../features').Feature} - */ -var cssTextBoxTrim = { - 'text-box-trim': true, - 'text-box-edge': true, -}; - -/** - * CSS text-indent - * The `text-indent` property applies indentation to lines of inline content in a block. - * @see https://caniuse.com/css-text-indent - */ - -/** - * @type {import('../features').Feature} - */ -var cssTextIndent = { - 'text-indent': true, -}; - -/** - * CSS text-justify - * CSS property to define how text should be justified when `text-align: justify` is set. - * @see https://caniuse.com/css-text-justify - */ - -/** - * @type {import('../features').Feature} - */ -var cssTextJustify = { - 'text-justify': true, -}; - -/** - * CSS text-orientation - * The CSS `text-orientation` property specifies the orientation of text within a line. Current values only have an effect in vertical typographic modes (defined with the `writing-mode` property) - * @see https://caniuse.com/css-text-orientation - */ - -/** - * @type {import('../features').Feature} - */ -var cssTextOrientation = { - 'text-orientation': true, -}; - -/** - * CSS Text 4 text-spacing - * No description available. - * @see This feature comes from MDN: https://developer.mozilla.org/en-US/search?q=CSS+Text+4+text-spacing - */ - -/** - * @type {import('../features').Feature} - */ -var cssTextSpacing = { - 'text-spacing': true, -}; - -var cssTextshadow = { - 'text-shadow': true, -}; - -var cssTouchAction = { - 'touch-action': true, -}; - -var cssTransitions = { - 'transition': true, - 'transition-property': true, - 'transition-duration': true, - 'transition-delay': true, - 'transition-timing-function': true, -}; - -/** - * CSS unicode-bidi property - * No description available. - * @see This feature comes from MDN: https://developer.mozilla.org/en-US/search?q=CSS+unicode-bidi+property - */ - -/** - * @type {import('../features').Feature} - */ -var cssUnicodeBidi = { - 'unicode-bidi': true, -}; - -var cssUnsetValue = { - '': 'unset', -}; - -/** - * @param {import('postcss').ChildNode} rule - * @return {boolean} - */ -var cssVariables = (rule) => { - if (rule.type !== 'decl') return false; - return (rule.prop.startsWith('--') || rule.value.includes('var(')); -}; - -/** - * CSS @when / @else conditional rules - * Syntax allowing CSS conditions (like media and support queries) to be written more simply, as well as making it possibly to write mutually exclusive rules using `@else` statements. - * @see https://caniuse.com/css-when-else - */ - -/** - * @type {import('../features').Feature} - */ -var cssWhenElse = checkAtRule(['when', 'else']); - -/** - * CSS widows & orphans - * CSS properties to control when lines break across pages or columns by defining the amount of lines that must be left before or after the break. - * @see https://caniuse.com/css-widows-orphans - */ - -/** - * @type {import('../features').Feature} - */ -var cssWidowsOrphans = { - 'widows': true, - 'orphans': true, -}; - -/** - * width: stretch property - * No description available. - * @see This feature comes from MDN: https://developer.mozilla.org/en-US/search?q=width:+stretch+property - */ - -/** - * @type {import('../features').Feature} - */ -var cssWidthStretch = { - 'width': 'stretch', -}; - -/** - * CSS writing-mode property - * Property to define whether lines of text are laid out horizontally or vertically and the direction in which blocks progress. - * @see https://caniuse.com/css-writing-mode - */ - -/** - * @type {import('../features').Feature} - */ -var cssWritingMode = { - 'writing-mode': true, -}; - -/** - * CSS zoom - * Non-standard method of scaling content. - * @see https://caniuse.com/css-zoom - */ - -/** - * @type {import('../features').Feature} - */ -var cssZoom = { - 'zoom': true, -}; - -/** - * CSS3 attr() function for all properties - * While `attr()` is supported for effectively all browsers for the `content` property, CSS Values and Units Level 5 adds the ability to use `attr()` on **any** CSS property, and to use it for non-string values (e.g. numbers, colors). - * @see https://caniuse.com/css3-attr - */ - -/** - * @type {import('../features').Feature} - */ -var css3Attr = (rule) => { - if (rule.type !== 'decl') return false; - if (rule.prop === 'content') { - return false; - } - - return rule.toString().includes('attr('); -}; - -var css3Boxsizing = { - 'box-sizing': true, -}; - -var css3Colors = { - '': [ - 'rgba', - 'hsl', - 'hsla', - ], -}; - -var css3Cursors = { - 'cursor': [ - 'none', - 'context-menu', - 'cell', - 'vertical-text', - 'alias', - 'copy', - 'no-drop', - 'not-allowed', - 'nesw-resize', - 'nwse-resize', - 'col-resize', - 'row-resize', - 'all-scroll', - ], -}; - -var css3CursorsGrab = { - 'cursor': ['grab', 'grabbing'], -}; - -var css3CursorsNewer = { - 'cursor': ['zoom-in', 'zoom-out'], -}; - -var css3Tabsize = { - 'tab-size': true, -}; - -/** - * CSS currentColor value - * A CSS value that will apply the existing `color` value to other properties like `background-color`, etc. - * @see https://caniuse.com/currentcolor - */ - -/** - * @type {import('../features').Feature} - */ -var currentcolor = { - '': 'currentColor', -}; - -/** - * Window.devicePixelRatio - * Read-only property that returns the ratio of the (vertical) size of one physical pixel on the current display device to the size of one CSS pixel. - * @see https://caniuse.com/devicepixelratio - */ - -/** - * @type {import('../features').Feature} - */ -var devicepixelratio = {}; - -/* this feature is found in JS and is not linted by this tool */ - -/** - * ui-serif, ui-sans-serif, ui-monospace and ui-rounded values for font-family - * Allows more control when choosing system interface fonts - * @see https://caniuse.com/extended-system-fonts - */ - -/** - * @type {import('../features').Feature} - */ -var extendedSystemFonts = { - 'font-family': ['ui-serif', 'ui-sans-serif', 'ui-monospace', 'ui-rounded'], -}; - -var flexbox = { - 'display': [ - 'flex', - 'inline-flex', - ], - 'flex': true, - 'flex-grow': true, - 'flex-shrink': true, - 'flex-basis': true, - 'flex-direction': true, - 'flex-wrap': true, - 'flex-flow': true, -}; - -/** - * gap property for Flexbox - * `gap` for flexbox containers to create gaps/gutters between flex items - * @see https://caniuse.com/flexbox-gap - */ - -/** - * @type {import('../features').Feature} - */ -var flexboxGap = (rule) => { - if (/display:\s(inline-)?flex/.test(rule.toString()) - && rule.toString().includes('gap:') - ) { - return true; - } - - return false; -}; - -/** - * display: flow-root - * The element generates a block container box, and lays out its contents using flow layout. It always establishes a new block formatting context for its contents. It provides a better solution to the most use cases of the "clearfix" hack. - * @see https://caniuse.com/flow-root - */ - -/** - * @type {import('../features').Feature} - */ -var flowRoot = { - 'display': 'flow-root', -}; - -/** - * system-ui value for font-family - * Value for `font-family` that represents the default user interface font. - * @see https://caniuse.com/font-family-system-ui - */ - -/** - * @type {import('../features').Feature} - */ -var fontFamilySystemUi = { - 'font-family': 'system-ui', -}; - -var fontFeature = { - 'font-feature-settings': true, - 'font-variant-ligatures': true, - 'font-language-override': true, - 'font-kerning': true, -}; - -/** - * CSS3 font-kerning - * Controls the usage of the kerning information (spacing between letters) stored in the font. Note that this only affects OpenType fonts with kerning information, it has no effect on other fonts. - * @see https://caniuse.com/font-kerning - */ - -/** - * @type {import('../features').Feature} - */ -var fontKerning = { - 'font-kerning': true, -}; - -/** - * CSS Font Loading - * This CSS module defines a scripting interface to font faces in CSS, allowing font faces to be easily created and loaded from script. It also provides methods to track the loading status of an individual font, or of all the fonts on an entire page. - * @see https://caniuse.com/font-loading - */ - -/** - * @type {import('../features').Feature} - */ -var fontLoading = {}; - -/* this feature appears in JS and as such is not linted */ - -var fontSizeAdjust = { - 'font-size-adjust': true, -}; - -/** - * CSS font-smooth - * Controls the application of anti-aliasing when fonts are rendered. - * @see https://caniuse.com/font-smooth - */ - -/** - * @type {import('../features').Feature} - */ -var fontSmooth = { - 'font-smooth': true, -}; - -var fontUnicodeRange = { - 'unicode-range': true, -}; - -/** - * CSS font-variant-alternates - * Controls the usage of alternate glyphs associated to alternative names defined in @font-feature-values for certain types of OpenType fonts. - * @see https://caniuse.com/font-variant-alternates - */ - -/** - * @type {import('../features').Feature} - */ -var fontVariantAlternates = { - 'font-variant-alternates': true, -}; - -/** - * CSS font-variant-numeric - * CSS property that provides different ways of displaying numbers, fractions, and ordinal markers. - * @see https://caniuse.com/font-variant-numeric - */ - -/** - * @type {import('../features').Feature} - */ -var fontVariantNumeric = { - 'font-variant-numeric': true, -}; - -var fontface = [ - checkAtRule('font-face'), -]; - -var fullscreen = checkSelector(':fullscreen'); - -/** - * getComputedStyle - * API to get the current computed CSS styles applied to an element. This may be the current value applied by an animation or as set by a stylesheet. - * @see https://caniuse.com/getcomputedstyle - */ - -/** - * @type {import('../features').Feature} - */ -var getcomputedstyle = {}; - -/* this is a js api, so we don't lint it */ - -var inlineBlock = { - 'display': 'inline-block', -}; - -const VALUES = ['max-content', 'min-content', 'fit-content', 'fill-available', 'stretch', 'fill']; - -var intrinsicWidth = { - 'width': VALUES, - 'min-width': VALUES, - 'max-width': VALUES, - 'height': VALUES, - 'min-height': VALUES, - 'max-height': VALUES, -}; - -/** - * CSS justify-content: space-evenly - * The "space-evenly" value for the `justify-content` property distributes the space between items evenly. It is similar to space-around but provides equal instead of half-sized space on the edges. Can be used in both CSS flexbox & grid. - * @see https://caniuse.com/justify-content-space-evenly - */ - -/** - * @type {import('../features').Feature} - */ -var justifyContentSpaceEvenly = { - 'justify-content': 'space-evenly', -}; - -var kerningPairsLigatures = { - 'text-rendering': 'optimizeLegibility', -}; - -var mdnCssUnicodeBidiIsolate = { - 'unicode-bidi': 'isolate', -}; - -var mdnCssUnicodeBidiIsolateOverride = { - 'unicode-bidi': 'isolate-override', -}; - -var mdnCssUnicodeBidiPlaintext = { - 'unicode-bidi': 'plaintext', -}; - -var mdnTextDecorationColor = { - 'text-decoration-color': true, -}; - -var mdnTextDecorationLine = { - 'text-decoration-line': true, -}; - -var mdnTextDecorationShorthand = { - 'text-decoration': true, -}; - -var mdnTextDecorationStyle = { - 'text-decoration-style': true, -}; - -var minmaxwh = { - 'min-width': true, - 'max-width': true, - 'min-height': true, - 'max-height': true, -}; - -/** - * @param {import('postcss').ChildNode} rule - * @return {boolean} - */ -var multibackgrounds = (rule) => { - if (rule.type !== 'decl') return false; - if (!/^background-?/.test(rule.prop)) return false; - return postcss.list.comma(rule.value).length > 1; -}; - -var multicolumn = { - 'columns': true, - 'column-width': true, - 'column-gap': true, - 'column-rule': true, - 'column-rule-color': true, - 'column-rule-width': true, - 'column-count': true, - 'column-rule-style': true, - 'column-span': true, - 'column-fill': true, - 'break-before': true, - 'break-after': true, - 'break-inside': true, -}; - -var objectFit = { - 'object-fit': true, - 'object-position': true, -}; - -var outline = { - 'outline': true, - 'outline-style': true, - 'outline-width': true, - 'outline-color': true, -}; - -var pointer = { - 'touch-action': true, -}; - -var pointerEvents = { - 'pointer-events': true, -}; - -/** - * prefers-color-scheme media query - * Media query to detect if the user has set their system to use a light or dark color theme. - * @see https://caniuse.com/prefers-color-scheme - */ - -/** - * @type {import('../features').Feature} - */ -var prefersColorScheme = checkAtRule('media', 'prefers-color-scheme'); - -/** - * TODO: initially implement feature - * prefers-reduced-motion media query - * CSS media query based on a user preference for preferring reduced motion (animation, etc). - * @see https://caniuse.com/prefers-reduced-motion - */ - -/** - * @type {import('../features').Feature} - */ -var prefersReducedMotion = checkAtRule('media', 'prefers-reduced-motion'); - -var rem = checkCSSLengthUnits('rem'); - -/** - * display: run-in - * If the run-in box contains a block box, same as block. If a block box follows the run-in box, the run-in box becomes the first inline box of the block box. If an inline box follows, the run-in box becomes a block box. - * @see https://caniuse.com/run-in - */ - -/** - * @type {import('../features').Feature} - */ -var runIn = { - 'display': 'run-in', -}; - -/** - * Scoped CSS - * Allows CSS rules to be scoped to part of the document, based on the position of the style element. The attribute has been [removed from the current specification](https://github.com/whatwg/html/issues/552). - * @see https://caniuse.com/style-scoped - */ - -/** - * @type {import('../features').Feature} - */ -var styleScoped = {}; - -/* this feature appears in HTML, so we don't lint it */ - -/** - * SVG in CSS backgrounds - * Method of using SVG images as CSS backgrounds - * @see https://caniuse.com/svg-css - */ - -/** - * @type {import('../features').Feature} - */ -var svgCss = (rule) => { - if (rule.type !== 'decl') return false; - if (/url\([\S\s]*svg/g.test( - rule.toString(), - )) { - return true; - } - - return false; -}; - -var textDecoration = { - 'text-decoration-style': true, - 'text-decoration-line': true, - 'text-decoration-color': true, - 'text-decoration': /\w \w/, - 'text-decoration-thickness': true, - 'text-decoration-skip': true, - 'text-decoration-skip-ink': true, -}; - -/** - * text-emphasis styling - * Method of using small symbols next to each glyph to emphasize a run of text, commonly used in East Asian languages. The `text-emphasis` shorthand, and its `text-emphasis-style` and `text-emphasis-color` longhands, can be used to apply marks to the text. The `text-emphasis-position` property, which inherits separately, allows setting the emphasis marks' position with respect to the text. - * @see https://caniuse.com/text-emphasis - */ - -/** - * @type {import('../features').Feature} - */ -var textEmphasis = { - 'text-emphasis': true, - 'text-emphasis-style': true, - 'text-emphasis-color': true, - 'text-emphasis-position': true, -}; - -var textOverflow = { - 'text-overflow': true, -}; - -var textSizeAdjust = { - 'text-size-adjust': true, -}; - -/** - * CSS text-stroke and text-fill - * Method of declaring the outline (stroke) width and color for text. - * @see https://caniuse.com/text-stroke - */ - -/** - * @type {import('../features').Feature} - */ -var textStroke = { - 'text-stroke-color': true, - 'text-stroke-width': true, - 'text-stroke': true, - 'text-fill-color': true, -}; - -var transforms2d = { - 'transform': true, - 'transform-origin': true, -}; - -var transforms3d = { - 'perspective': true, - 'perspective-origin': true, - 'transform-style': true, - 'backface-visibility': true, - 'transform': '3d', -}; - -/** - * TTF/OTF - TrueType and OpenType font support - * Support for the TrueType (.ttf) and OpenType (.otf) outline font formats in @font-face. - * @see https://caniuse.com/ttf - */ - -/** - * @type {import('../features').Feature} - */ -var ttf = (rule) => { - const ruleText = rule.toString(); - - if (ruleText.includes('@font-face') && ( - (ruleText.includes('.ttf') || ruleText.includes('.otf')) - )) { - return true; - } - - return false; -}; - -var userSelectNone = { - 'user-select': true, -}; - -/** - * Variable fonts - * OpenType font settings that allows a single font file to behave like multiple fonts: it can contain all the allowed variations in width, weight, slant, optical size, or any other exposed axes of variation as defined by the font designer. Variations can be applied via the `font-variation-settings` property. - * @see https://caniuse.com/variable-fonts - */ - -/** - * @type {import('../features').Feature} - */ -var variableFonts = { - 'font-variation-settings': true, -}; - -/** - * Small, Large, and Dynamic viewport units - * Viewport units similar to `vw` and `vh` that are based on shown or hidden - * browser UI states to address shortcomings of the original units. Currently - * defined as the - * `sv*` units (`svb`, `svh`, `svi`, `svmax`, `svmin`, `svw`), - * `lv*` units (`lvb`, `lvh`, `lvi`, `lvmax`, `lvmin`, `lvw`), - * `dv*` units (`dvb`, `dvh`, `dvi`, `dvmax`, `dvmin`, `dvw`) - * and the logical `vi`/`vb` units. - * @see https://caniuse.com/viewport-unit-variants - * @type {import('../features').Feature} - */ -var viewportUnitVariants = checkCSSLengthUnits( - /* sv* units */ - 'svb', - 'svh', - 'svi', - 'svmax', - 'svmin', - 'svw', - - /* lv* units */ - 'lvb', - 'lvh', - 'lvi', - 'lvmax', - 'lvmin', - 'lvw', - - /* dv* units */ - 'dvb', - 'dvh', - 'dvi', - 'dvmax', - 'dvmin', - 'dvw', - - /* vi/vb units */ - 'vi', - 'vb', -); - -var viewportUnits = { - '': [ - 'vw', - 'vh', - 'vmin', - 'vmax', - ], -}; - -/** - * CSS -webkit-user-drag property - * The non-standard `-webkit-user-drag` CSS property can be used to either make an element draggable or explicitly non-draggable (like links and images). See the standardized [draggable attribute/property](/mdn-api_htmlelement_draggable) for the recommended alternative method of accomplishing the same functionality. - * @see https://caniuse.com/webkit-user-drag - */ - -/** - * @type {import('../features').Feature} - */ -var webkitUserDrag = { - 'webkit-user-drag': true, -}; - -var willChange = { - 'will-change': true, -}; - -var wordBreak = { - 'word-break': true, -}; - -var wordwrap = { - 'overflow-wrap': true, - 'word-wrap': true, -}; - -/* THIS FILE IS AUTOGENERATED */ - -/** @typedef {RegExp|string|((value:string) => boolean)} FeatureCheck */ - -/** @typedef {((rule:import('postcss').ChildNode) => boolean)} RuleCheck */ - -/** @typedef {Record<string, FeatureCheck|FeatureCheck[]|boolean> | RuleCheck | RuleCheck[]} Feature */ - -/** @enum {Feature} */ -const FEATURES = { - 'alternate-stylesheet': alternateStylesheet, - 'background-attachment': backgroundAttachment, - 'background-clip-text': backgroundClipText, - 'background-img-opts': backgroundImgOpts, - 'background-position-x-y': backgroundPositionXY, - 'background-repeat-round-space': backgroundRepeatRoundSpace, - 'border-image': borderImage, - 'border-radius': borderRadius, - 'calc': calc, - 'ch-unit': chUnit, - 'css-all': cssAll, - 'css-animation': cssAnimation, - 'css-any-link': cssAnyLink, - 'css-appearance': cssAppearance, - 'css-at-counter-style': cssAtCounterStyle, - 'css-autofill': cssAutofill, - 'css-backdrop-filter': cssBackdropFilter, - 'css-background-offsets': cssBackgroundOffsets, - 'css-backgroundblendmode': cssBackgroundblendmode, - 'css-boxdecorationbreak': cssBoxdecorationbreak, - 'css-boxshadow': cssBoxshadow, - 'css-canvas': cssCanvas, - 'css-caret-color': cssCaretColor, - 'css-cascade-layers': cssCascadeLayers, - 'css-case-insensitive': cssCaseInsensitive, - 'css-clip-path': cssClipPath, - 'css-color-adjust': cssColorAdjust, - 'css-color-function': cssColorFunction, - 'css-conic-gradients': cssConicGradients, - 'css-container-queries': cssContainerQueries, - 'css-container-queries-style': cssContainerQueriesStyle, - 'css-container-query-units': cssContainerQueryUnits, - 'css-containment': cssContainment, - 'css-content-visibility': cssContentVisibility, - 'css-counters': cssCounters, - 'css-crisp-edges': cssCrispEdges, - 'css-cross-fade': cssCrossFade, - 'css-default-pseudo': cssDefaultPseudo, - 'css-descendant-gtgt': cssDescendantGtgt, - 'css-deviceadaptation': cssDeviceadaptation, - 'css-dir-pseudo': cssDirPseudo, - 'css-display-contents': cssDisplayContents, - 'css-element-function': cssElementFunction, - 'css-env-function': cssEnvFunction, - 'css-exclusions': cssExclusions, - 'css-featurequeries': cssFeaturequeries, - 'css-file-selector-button': cssFileSelectorButton, - 'css-filter-function': cssFilterFunction, - 'css-filters': cssFilters, - 'css-first-letter': cssFirstLetter, - 'css-first-line': cssFirstLine, - 'css-fixed': cssFixed, - 'css-focus-visible': cssFocusVisible, - 'css-focus-within': cssFocusWithin, - 'css-font-palette': cssFontPalette, - 'css-font-rendering-controls': cssFontRenderingControls, - 'css-font-stretch': cssFontStretch, - 'css-gencontent': cssGencontent, - 'css-gradients': cssGradients, - 'css-grid': cssGrid, - 'css-grid-animation': cssGridAnimation, - 'css-hanging-punctuation': cssHangingPunctuation, - 'css-has': cssHas, - 'css-hyphens': cssHyphens, - 'css-image-orientation': cssImageOrientation, - 'css-image-set': cssImageSet, - 'css-in-out-of-range': cssInOutOfRange, - 'css-indeterminate-pseudo': cssIndeterminatePseudo, - 'css-initial-letter': cssInitialLetter, - 'css-initial-value': cssInitialValue, - 'css-lch-lab': cssLchLab, - 'css-letter-spacing': cssLetterSpacing, - 'css-line-clamp': cssLineClamp, - 'css-logical-props': cssLogicalProps, - 'css-marker-pseudo': cssMarkerPseudo, - 'css-masks': cssMasks, - 'css-matches-pseudo': cssMatchesPseudo, - 'css-math-functions': cssMathFunctions, - 'css-media-interaction': cssMediaInteraction, - 'css-media-range-syntax': cssMediaRangeSyntax, - 'css-media-resolution': cssMediaResolution, - 'css-media-scripting': cssMediaScripting, - 'css-mediaqueries': cssMediaqueries, - 'css-mixblendmode': cssMixblendmode, - 'css-motion-paths': cssMotionPaths, - 'css-namespaces': cssNamespaces, - 'css-nesting': cssNesting, - 'css-not-sel-list': cssNotSelList, - 'css-nth-child-of': cssNthChildOf, - 'css-opacity': cssOpacity, - 'css-optional-pseudo': cssOptionalPseudo, - 'css-overflow': cssOverflow, - 'css-overflow-anchor': cssOverflowAnchor, - 'css-overflow-overlay': cssOverflowOverlay, - 'css-overscroll-behavior': cssOverscrollBehavior, - 'css-page-break': cssPageBreak, - 'css-paged-media': cssPagedMedia, - 'css-paint-api': cssPaintApi, - 'css-placeholder': cssPlaceholder, - 'css-placeholder-shown': cssPlaceholderShown, - 'css-print-color-adjust': cssPrintColorAdjust, - 'css-read-only-write': cssReadOnlyWrite, - 'css-rebeccapurple': cssRebeccapurple, - 'css-reflections': cssReflections, - 'css-regions': cssRegions, - 'css-relative-colors': cssRelativeColors, - 'css-repeating-gradients': cssRepeatingGradients, - 'css-resize': cssResize, - 'css-revert-value': cssRevertValue, - 'css-rrggbbaa': cssRrggbbaa, - 'css-scroll-behavior': cssScrollBehavior, - 'css-scroll-timeline': cssScrollTimeline, - 'css-scrollbar': cssScrollbar, - 'css-sel2': cssSel2, - 'css-sel3': cssSel3, - 'css-selection': cssSelection, - 'css-shapes': cssShapes, - 'css-snappoints': cssSnappoints, - 'css-sticky': cssSticky, - 'css-subgrid': cssSubgrid, - 'css-supports-api': cssSupportsApi, - 'css-table': cssTable, - 'css-text-align-last': cssTextAlignLast, - 'css-text-box-trim': cssTextBoxTrim, - 'css-text-indent': cssTextIndent, - 'css-text-justify': cssTextJustify, - 'css-text-orientation': cssTextOrientation, - 'css-text-spacing': cssTextSpacing, - 'css-textshadow': cssTextshadow, - 'css-touch-action': cssTouchAction, - 'css-transitions': cssTransitions, - 'css-unicode-bidi': cssUnicodeBidi, - 'css-unset-value': cssUnsetValue, - 'css-variables': cssVariables, - 'css-when-else': cssWhenElse, - 'css-widows-orphans': cssWidowsOrphans, - 'css-width-stretch': cssWidthStretch, - 'css-writing-mode': cssWritingMode, - 'css-zoom': cssZoom, - 'css3-attr': css3Attr, - 'css3-boxsizing': css3Boxsizing, - 'css3-colors': css3Colors, - 'css3-cursors': css3Cursors, - 'css3-cursors-grab': css3CursorsGrab, - 'css3-cursors-newer': css3CursorsNewer, - 'css3-tabsize': css3Tabsize, - 'currentcolor': currentcolor, - 'devicepixelratio': devicepixelratio, - 'extended-system-fonts': extendedSystemFonts, - 'flexbox': flexbox, - 'flexbox-gap': flexboxGap, - 'flow-root': flowRoot, - 'font-family-system-ui': fontFamilySystemUi, - 'font-feature': fontFeature, - 'font-kerning': fontKerning, - 'font-loading': fontLoading, - 'font-size-adjust': fontSizeAdjust, - 'font-smooth': fontSmooth, - 'font-unicode-range': fontUnicodeRange, - 'font-variant-alternates': fontVariantAlternates, - 'font-variant-numeric': fontVariantNumeric, - 'fontface': fontface, - 'fullscreen': fullscreen, - 'getcomputedstyle': getcomputedstyle, - 'inline-block': inlineBlock, - 'intrinsic-width': intrinsicWidth, - 'justify-content-space-evenly': justifyContentSpaceEvenly, - 'kerning-pairs-ligatures': kerningPairsLigatures, - 'mdn-css-unicode-bidi-isolate': mdnCssUnicodeBidiIsolate, - 'mdn-css-unicode-bidi-isolate-override': mdnCssUnicodeBidiIsolateOverride, - 'mdn-css-unicode-bidi-plaintext': mdnCssUnicodeBidiPlaintext, - 'mdn-text-decoration-color': mdnTextDecorationColor, - 'mdn-text-decoration-line': mdnTextDecorationLine, - 'mdn-text-decoration-shorthand': mdnTextDecorationShorthand, - 'mdn-text-decoration-style': mdnTextDecorationStyle, - 'minmaxwh': minmaxwh, - 'multibackgrounds': multibackgrounds, - 'multicolumn': multicolumn, - 'object-fit': objectFit, - 'outline': outline, - 'pointer': pointer, - 'pointer-events': pointerEvents, - 'prefers-color-scheme': prefersColorScheme, - 'prefers-reduced-motion': prefersReducedMotion, - 'rem': rem, - 'run-in': runIn, - 'style-scoped': styleScoped, - 'svg-css': svgCss, - 'text-decoration': textDecoration, - 'text-emphasis': textEmphasis, - 'text-overflow': textOverflow, - 'text-size-adjust': textSizeAdjust, - 'text-stroke': textStroke, - 'transforms2d': transforms2d, - 'transforms3d': transforms3d, - 'ttf': ttf, - 'user-select-none': userSelectNone, - 'variable-fonts': variableFonts, - 'viewport-unit-variants': viewportUnitVariants, - 'viewport-units': viewportUnits, - 'webkit-user-drag': webkitUserDrag, - 'will-change': willChange, - 'word-break': wordBreak, - 'wordwrap': wordwrap, -}; - -/** - * @template T - * @typedef {{missing: T, partial: T}} Filter - */ - -/** - * @typedef {Object} MissingSupportResultStats - * @prop {string} title - * @prop {caniuse.Feature} caniuseData - * @prop {string} [missing] - * @prop {Record<string, Record<string, string>>} [missingData] - * @prop {string} [partial] - * @prop {Record<string, Record<string, string>>} [partialData] - */ - -/** - * @typedef {Partial<Record<keyof FEATURES, MissingSupportResultStats>>} BrowserSupportStats - */ - -/** - * @typedef {Object} MissingSupportResult - * @prop {string[][]} browsers - * @prop {Partial<Record<keyof FEATURES, MissingSupportResultStats>>} features - */ - -class BrowserSelection { - #list; - - /** - * @param {string | string[]} [query] - * @param {string | false} [from] - */ - constructor(query, from) { - this.browsersRequest = query; - const options = from ? { path: from } : {}; - this.#list = browserslist__default["default"](this.browsersRequest, options).map((browser) => browser.split(' ')); - } - - /** - * @param {string} browser - * @param {string} version - * @return {string[]|undefined} - */ - test(browser, version) { - const versions = version.split('-'); - - if (versions.length === 1) { - versions.push(versions[0]); - } - - return this.#list.find(([b, v]) => b === browser && v >= versions[0] && v <= versions[1]); - } - - list() { - return [...this.#list]; - } - - /** - * @param {Record<string, Record<string, string>>} browserStats - * @return {string} - */ - static lackingBrowsers(browserStats) { - const result = []; - for (const browser of Object.keys(browserStats)) { - result.push(formatBrowserName(browser, Object.keys(browserStats[browser]))); - } - return result.join(', '); - } - - /** - * @param {import('caniuse-lite').StatsByAgentID} stats - * @return {Filter<Record<string,Record<string, string>>>} - */ - filterStats(stats) { - /** @type {Filter<Record<string,Record<string, string>>>} */ - const result = { missing: {}, partial: {} }; - for (const [browser, versions] of Object.entries(stats)) { - /** @type {Filter<Record<string,string>>} */ - const feature = { missing: {}, partial: {} }; - for (const [version, support] of Object.entries(versions)) { - const selected = this.test(browser, version); - - // check if browser is NOT fully (i.e., don't have 'y' in their stats) supported - if (!selected) continue; - if ((/(^|\s)y($|\s)/.test(support))) continue; - // when it's not partially supported ('a'), it's missing - const type = (/(^|\s)a($|\s)/.test(support) ? 'partial' : 'missing'); - - if (!feature[type]) { - feature[type] = {}; - } - - feature[type][selected[1]] = support; - } - if (Object.keys(feature.missing).length > 0) { - result.missing[browser] = feature.missing; - } - - if (Object.keys(feature.partial).length > 0) { - result.partial[browser] = feature.partial; - } - } - return result; - } - - /** - * Get data on CSS features not supported by the given autoprefixer-like - * browser selection. - * @return {BrowserSupportStats} `features` is an array of: - * ``` - * { - * 'feature-name': { - * title: 'Title of feature' - * missing: "IE (8), Chrome (31)" - * missingData: { - * // map of browser -> version -> (lack of)support code - * ie: { '8': 'n' }, - * chrome: { '31': 'n' } - * } - * partialData: { - * // map of browser -> version -> (partial)support code - * ie: { '7': 'a' }, - * ff: { '29': 'a #1' } - * } - * caniuseData: { - * // caniuse-db json data for this feature - * } - * }, - * 'feature-name-2': {} // etc. - * } - * ``` - * - * `feature-name` is a caniuse-db slug. - */ - compileBrowserSupport() { - /** @type {Partial<Record<keyof FEATURES, MissingSupportResultStats>>} */ - const result = {}; - - for (const key of Object.keys(FEATURES)) { - const feature = /** @type {keyof FEATURES} */ (key); - const packedFeature = caniuse__namespace.features[feature]; - const featureData = caniuse__namespace.feature(packedFeature); - const lackData = this.filterStats(featureData.stats); - const missingData = lackData.missing; - const partialData = lackData.partial; - // browsers with missing or partial support for this feature - const missing = BrowserSelection.lackingBrowsers(missingData); - const partial = BrowserSelection.lackingBrowsers(partialData); - - if (missing.length > 0 || partial.length > 0) { - result[feature] = { - title: featureData.title, - caniuseData: featureData, - ...(missing.length > 0 ? { missingData, missing } : null), - ...(partial.length > 0 ? { partialData, partial } : null), - }; - } - } - - return result; - } - - /** - * @see BrowserSelection.compileBrowserSupport - * @param {ConstructorParameters<typeof this>} constructorParameters - * @return {MissingSupportResult} `{browsers, features}` - */ - static missingSupport(...constructorParameters) { - const selection = new BrowserSelection(...constructorParameters); - return { - browsers: selection.list(), - features: selection.compileBrowserSupport(), - }; - } -} - -/** - * @typedef DetectorCallbackArgument - * @prop {!import('postcss').ChildNode} usage - * @prop {keyof FEATURES} feature - * @prop {(keyof FEATURES & string)[]} ignore - */ - -/** - * @callback DetectorCallback - * @param {DetectorCallbackArgument} result - * @return {any} - */ - -const PLUGIN_OPTION_COMMENT = 'doiuse-'; -const DISABLE_FEATURE_COMMENT = `${PLUGIN_OPTION_COMMENT}disable`; -const ENABLE_FEATURE_COMMENT = `${PLUGIN_OPTION_COMMENT}enable`; - -/** - * Strip the contents of url literals so they aren't matched - * by our naive substring matching. - * @param {string} input - * @return {string} - */ -function stripUrls(input) { - return input.replaceAll(/url\([^)]*\)/g, 'url()'); -} - -/** - * Detect the use of any of a given list of CSS features. - * ``` - * var detector = new Detector(featureList) - * detector.process(css, cb) - * ``` - * - * `featureList`: an array of feature slugs (see caniuse-db) - * `cb`: a callback that gets called for each usage of one of the given features, - * called with an argument like: - * ``` - * { - * usage: {} // postcss node where usage was found - * feature: {} // caniuse-db feature slug - * ignore: {} // caniuse-db feature to ignore in current file - * } - * ``` - */ -class Detector { - /** - * @param {(keyof FEATURES & string)[]} featureList an array of feature slugs (see caniuse-db) - */ - constructor(featureList) { - /** @type {Partial<FEATURES>} */ - this.features = {}; - for (const feature of featureList) { - if (FEATURES[feature]) { - this.features[feature] = FEATURES[feature]; - } - } - /** @type {(keyof FEATURES & string)[]} */ - this.ignore = []; - } - - /** - * @param {import('postcss').Comment} comment - * @return {void} - */ - comment(comment) { - const text = comment.text.toLowerCase(); - - if (!text.startsWith(PLUGIN_OPTION_COMMENT)) return; - const option = text.split(' ', 1)[0]; - const value = text.replace(option, '').trim(); - - switch (option) { - case DISABLE_FEATURE_COMMENT: { - if (value === '') { - // @ts-expect-error Skip cast - this.ignore = Object.keys(this.features); - } else { - for (const feat of value.split(',')) { - /** @type {any} */ - const f = feat.trim(); - if (!this.ignore.includes(f)) { - this.ignore.push(f); - } - } - } - break; - } - case ENABLE_FEATURE_COMMENT: { - if (value === '') { - this.ignore = []; - } else { - const without = new Set(value.split(',').map((feat) => feat.trim())); - this.ignore = this.ignore.filter((index) => !without.has(index)); - } - break; - } - } - } - - /** - * @param {import('postcss').Container} node - * @param {DetectorCallback} callback - * @return {void} - */ - node(node, callback) { - node.each((child) => { - if (child.type === 'comment') { - this.comment(child); - return; - } - - for (const [feat] of Object.entries(this.features).filter(([, featValue]) => { - if (!featValue) return false; - if (typeof featValue === 'function') { - return featValue(child); - } - if (Array.isArray(featValue)) { - return featValue.some((function_) => function_(child)); - } - if (child.type !== 'decl') { - return false; - } - - return Object.entries(featValue).some(([property, value]) => { - if (property !== '' && property !== child.prop) return false; - if (value === true) return true; - if (value === false) return false; - return performFeatureCheck(value, stripUrls(child.value)); - }); - })) { - const feature = /** @type {keyof FEATURES} */ (feat); - callback({ usage: child, feature, ignore: this.ignore }); - } - if (child.type !== 'decl') { - this.node(child, callback); - } - }); - } - - /** - * @param {import('postcss').Root} node - * @param {DetectorCallback} callback - * @return {void} - */ - process(node, callback) { - // Reset ignoring rules specified by inline comments per each file - this.ignore = []; - - // Recursively walk nodes in file - this.node(node, callback); - } -} - -/** @typedef {import('../data/features.js').FeatureKeys} FeatureKeys */ - -/** - * @typedef {Object} OnFeatureUsageArguments - * @prop {FeatureKeys} feature - * @prop {import('./BrowserSelection.js').MissingSupportResultStats|undefined} featureData - * @prop {import('postcss').Node} usage - * @prop {string} message - */ - -/** - * @callback OnFeatureUsage - * @param {OnFeatureUsageArguments} result - * @return {any} - */ - -/** - * @typedef {Object} DoIUseOptions - * @prop {ConstructorParameters<typeof BrowserSelection>[0]} [browsers] - * @prop {FeatureKeys[]} [ignore] - * @prop {OnFeatureUsage} [onFeatureUsage] - * @prop {string[]} [ignoreFiles] - */ - -class DoIUse { - static default = null; - - /** - * @param {DoIUseOptions} [optionsOrBrowserQuery] - */ - constructor(optionsOrBrowserQuery) { - const options = (typeof optionsOrBrowserQuery === 'string') - ? { browsers: optionsOrBrowserQuery } - : { ...optionsOrBrowserQuery }; - this.browserQuery = options.browsers; - this.onFeatureUsage = options.onFeatureUsage; - this.ignoreOptions = options.ignore; - this.ignoreFiles = options.ignoreFiles; - this.info = this.info.bind(this); - this.postcss = this.postcss.bind(this); - } - - /** - * @param {Object} [options] - * @param {ConstructorParameters<typeof BrowserSelection>[1]} [options.from] - */ - info(options = {}) { - const { browsers, features } = BrowserSelection.missingSupport(this.browserQuery, options.from); - - return { - browsers, - features, - }; - } - - /** @type {import('postcss').TransformCallback} */ - postcss(css, result) { - let from; - if (css.source && css.source.input) { - from = css.source.input.file; - } - const { features } = BrowserSelection.missingSupport(this.browserQuery, from); - // @ts-expect-error Needs cast - const detector = new Detector(Object.keys(features)); - - return detector.process(css, ({ feature, usage, ignore }) => { - if (ignore && ignore.includes(feature)) { - return; - } - - if (this.ignoreOptions && this.ignoreOptions.includes(feature)) { - return; - } - - if (!usage.source) { - throw new Error('No source?'); - } - if (this.ignoreFiles && multimatch__default["default"](usage.source.input.from, this.ignoreFiles).length > 0) { - return; - } - - const data = features[feature]; - if (!data) { - throw new Error('No feature data?'); - } - const messages = []; - if (data.missing) { - messages.push(`not supported by: ${data.missing}`); - } - if (data.partial) { - messages.push(`only partially supported by: ${data.partial}`); - } - - let message = `${data.title} ${messages.join(' and ')} (${feature})`; - - result.warn(message, { node: usage, plugin: 'doiuse' }); - - if (this.onFeatureUsage) { - if (!usage.source) { - throw new Error('No usage source?'); - } - const { start, input } = usage.source; - if (!start) { - throw new Error('No usage source start?'); - } - - const map = css.source && css.source.input.map; - const mappedStart = map && map.consumer().originalPositionFor(start); - - const file = (mappedStart && mappedStart.source) || input.file || input.from; - const line = (mappedStart && mappedStart.line) || start.line; - const column = (mappedStart && mappedStart.column) || start.column; - - message = `${file}:${line}:${column}: ${message}`; - - this.onFeatureUsage({ - feature, - featureData: features[feature], - usage, - message, - }); - } - }); - } -} - -/* eslint-disable no-underscore-dangle */ - -/** @typedef {import('../../data/features.js').FeatureKeys} FeatureKeys */ -/** @typedef {import('./SourceMapTransform.js').SourceMapTransformation} SourceMapTransformation */ - -class RuleUsageTransform extends node_stream.Transform { - /** @type {import("postcss").Processor} */ - #processor; - - #skipErrors; - - #filename; - - /** - * @param {Object} options - * @param {string} options.browsers - * @param {FeatureKeys[]} [options.ignore] - * @param {boolean} [options.skipErrors] - * @param {string} [filename] Filename for outputting source code locations. - */ - constructor(options, filename = '<streaming css input>') { - super({ - objectMode: true, - }); - this.#processor = postcss__default["default"]([new DoIUse({ - browsers: options.browsers, - ignore: options.ignore, - onFeatureUsage: (usage) => { - this.push(usage); - }, - })]); - this.#filename = filename; - this.#skipErrors = options.skipErrors; - } - - /** - * @param {SourceMapTransformation} rule - * @param {any} encoding - * @param {Function} callback - */ - async _transform(rule, encoding, callback) { - let caughtError; - try { - const mapper = new sourcemap__default["default"].SourceMapGenerator(); - const lines = rule.content.split('\n'); - let oline = rule.line; - let ocol = rule.column; - for (const [lineNumber, content] of lines.entries()) { - mapper.addMapping({ - generated: { line: lineNumber + 1, column: 1 }, - original: { line: oline, column: ocol }, - source: this.#filename, - }); - mapper.addMapping({ - generated: { line: lineNumber + 1, column: content.length }, - original: { line: oline, column: ocol + content.length }, - source: this.#filename, - }); - oline += 1; - ocol = 1; - } - await this.#processor.process(rule.content, { - from: this.#filename, map: { prev: mapper.toString() }, - }); - } catch (error) { - if (this.#skipErrors) { - this.emit('warning', error); - } else { - caughtError = error; - } - } - callback(caughtError); - } -} - -/* eslint-disable no-underscore-dangle */ - -const NEW_LINE_CHAR = '\n'.codePointAt(0); - -/** - * @typedef {Object} SourceMapTransformation - * @prop {number} line - * @prop {number} column - * @prop {string} content - */ - -class SourceMapTransform extends node_stream.Transform { - constructor() { - super({ objectMode: true }); - } - - /** - * @type {?{location:[number,number], buffers: Buffer[]}} - * buffer for the current incoming rule. - */ - #current = null; - - /** track depth to handle rules nested in at-rules. */ - #depth = 0; - - /** track this and pass it downstream for source mapping. */ - #line = 1; - - /** track this and pass it downstream for source mapping. */ - #column = 1; - - /** - * @param {[string,Buffer]} chunk - * @param {any} encoding - * @param {Function} callback - */ - _transform([type, buf], encoding, callback) { - if ((type === 'rule_start' || type === 'atrule_start')) { - this.#depth += 1; - } - if (this.#depth > 0 && !this.#current) { - this.#current = { location: [this.#line, this.#column], buffers: [] }; - } - if (type === 'rule_end' || type === 'atrule_end') { - this.#depth -= 1; - } - - if (this.#current) { - this.#current.buffers.push(buf); - if (this.#depth === 0) { - // Push rule - this.push({ - line: this.#current.location[0], - column: this.#current.location[1], - content: Buffer.concat(this.#current.buffers).toString(), - }); - this.#current = null; - } - } - - // Update position - for (const char of buf) { - if (char === NEW_LINE_CHAR) { - this.#line += 1; - this.#column = 1; - } else { - this.#column += 1; - } - } - - callback(); - } -} - -/* eslint-disable no-underscore-dangle */ - -/** @typedef {import('../../data/features.js').FeatureKeys} FeatureKeys */ - -class CssUsageDuplex extends Duplexify__default["default"] { - /** - * @param {Object} options - * @param {string} options.browsers - * @param {FeatureKeys[]} [options.ignore] - * @param {boolean} [options.skipErrors] - * @param {string} [filename] Filename for outputting source code locations. - */ - constructor(options, filename) { - const streams = [ - new Tokenize__default["default"](), - new SourceMapTransform(), - new RuleUsageTransform(options, filename), - ]; - node_stream.pipeline( - // @ts-expect-error Bad typings - ...streams, - () => { - // noop (Error handled by Duplexify) - }, - ); - super(streams[0], streams.at(-1), { objectMode: true }); - } -} - -/** - * @param {ConstructorParameters<typeof CssUsageDuplex>} options - * @return {CssUsageDuplex} - */ -function index(...options) { - return new CssUsageDuplex(...options); -} - -module.exports = index; |
