webpack
Version:
Packs ECMAScript/CommonJs/AMD modules for the browser. Allows you to split your codebase into multiple bundles, which can be loaded on demand. Supports loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.
7,471 lines • 205 kB
JavaScript
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author sheo13666q @sheo13666q
*/
// GENERATED by tooling/generate-css-data.js — do not edit.
// Sources: mdn-data, color-name and @mdn/browser-compat-data, at the versions yarn.lock pins.
"use strict";
/** @typedef {(sums: Map<string, number>[]) => [string, number[]] | null} MathArgumentReader */
/** @typedef {(values: number[], strategy: string, table: Map<number, number>) => number | null} MathOperation */
// The arithmetic the math-function descriptors at the end of this file bind to.
// It knows nothing of CSS beyond the shape of an evaluated argument, and names
// no math function: which one uses which is the descriptors' business, and
// `lib/css/syntax.js` only drives the binding.
/**
* Add two doubles, or decline when the sum carries rounding of its own.
* @param {number} a one term
* @param {number} b the other
* @returns {number | null} their exact sum, or `null`
*/
const exactAdd = (a, b) => {
const sum = a + b;
return sum - b === a && sum - a === b ? sum : null;
};
/**
* Multiply, or decline, on the same terms.
* @param {number} a the value
* @param {number} k the factor
* @returns {number | null} their exact product, or `null`
*/
const exactMultiply = (a, k) => {
const product = a * k;
if (!Number.isFinite(product)) return null;
if (a === 0 || k === 0) return product;
return product / k === a ? product : null;
};
/**
* Add two doubles. Every sum a stylesheet can write is finite, and one that is
* not is no value to print.
* @param {number} a one term
* @param {number} b the other
* @returns {number | null} their sum, or `null`
*/
const foldAdd = (a, b) => {
const sum = a + b;
return Number.isFinite(sum) ? sum : null;
};
/**
* @param {number} a the value
* @param {number} k the factor
* @returns {number | null} their product, or `null`
*/
const foldMultiply = (a, k) => {
const product = a * k;
return Number.isFinite(product) ? product : null;
};
/**
* @param {number} a the value
* @param {number} k the divisor
* @returns {number | null} their quotient, or `null` where there is none
*/
const foldDivide = (a, k) => {
if (k === 0) return null;
const quotient = a / k;
return Number.isFinite(quotient) ? quotient : null;
};
/**
* `floor(value / step)` for a positive step, checked against the step exactly.
* The double quotient can land an ulp either side of an integer, which would put
* the multiple a whole step out, so the candidate is verified by multiplying
* back and nudged at most once either way.
* @param {number} value the dividend
* @param {number} step the divisor, greater than zero
* @returns {number | null} the floor, or `null` when it cannot be pinned down
*/
const exactFloorDivide = (value, step) => {
let n = Math.floor(value / step);
if (!Number.isFinite(n)) return null;
for (let attempt = 0; attempt < 3; attempt++) {
const at = exactMultiply(n, step);
const next = exactMultiply(n + 1, step);
if (at === null || next === null) return null;
if (at > value) {
n--;
continue;
}
if (next <= value) {
n++;
continue;
}
return n;
}
return null;
};
/**
* One evaluated argument list, read as a shared unit and its coefficients. A
* percentage is refused: its basis can be negative (a `background-position`
* against an image wider than its box), and comparing two of them depends on
* that sign in a way `calc()`'s arithmetic does not — scaling a percentage is
* linear, picking the smaller of two is not.
* @param {Map<string, number>[]} sums the evaluated arguments
* @returns {[string, number[]] | null} the shared unit and the coefficients
*/
const readSameUnit = (sums) => {
/** @type {string | null} */
let shared = null;
/** @type {number[]} */
const values = [];
for (const sum of sums) {
if (sum.size !== 1) return null;
const [[key, coefficient]] = sum;
if (key === "%") return null;
if (shared === null) shared = key;
else if (shared !== key) return null;
values.push(coefficient);
}
return shared === null ? null : [shared, values];
};
/**
* The same, narrowed to arguments that reduced to a plain `<number>`.
* @param {Map<string, number>[]} sums the evaluated arguments
* @returns {[string, number[]] | null} the unit (always `""`) and the numbers
*/
const readNumber = (sums) => {
const shared = readSameUnit(sums);
return shared === null || shared[0] !== "" ? null : shared;
};
/**
* Read a trigonometric function's one argument as degrees. A bare number is
* radians (CSS Values 4 §10.6), and an angle is the unit it was written in;
* either way what the fold needs is the one measure the tables are keyed by.
* @param {Map<string, number>} quarterTurnAngle a quarter turn in each unit that spells one exactly
* @returns {MathArgumentReader} the reader
*/
const angleReader = (quarterTurnAngle) => (sums) => {
const shared = readSameUnit(sums);
if (shared === null) return null;
const [unit, [angle]] = shared;
// A radian is what a bare number is read as, and the one angle unit that
// spells no quarter turn exactly — so the table states none for it.
if (unit === "" || unit === "rad") return ["", [(angle * 180) / Math.PI]];
const quarter = quarterTurnAngle.get(unit);
if (quarter === undefined) return null;
return ["", [(angle * 90) / quarter]];
};
/**
* @param {number[]} values the coefficients
* @returns {number} the smallest
*/
const minimum = (values) => Math.min(...values);
/**
* @param {number[]} values the coefficients
* @returns {number} the largest
*/
const maximum = (values) => Math.max(...values);
/**
* CSS Values 4 §10.4: the lower bound wins a contradictory pair.
* @param {number[]} values the lower bound, the value and the upper bound
* @returns {number} the value held between them
*/
const clamp = ([lower, value, upper]) =>
Math.max(lower, Math.min(value, upper));
/**
* @param {number[]} values the one coefficient
* @returns {number} its magnitude
*/
const absolute = ([value]) => Math.abs(value);
/**
* The one operation whose answer changes unit: a sign is a `<number>`. Every
* unit reaching here scales by a positive factor, so the coefficient's sign is
* the value's even where the factor is not known.
* @param {number[]} values the one coefficient
* @returns {number} its sign
*/
const sign = ([value]) => Math.sign(value);
/**
* @param {number[]} values the coefficients
* @returns {number | null} the root of their squares, or `null`
*/
const hypotenuse = (values) => {
const total = Math.hypot(...values);
return Number.isFinite(total) ? total : null;
};
/**
* The multiple of `step` that `strategy` rounds `value` to, as CSS Values 4
* §10.6 defines them and headless Chromium confirms: `nearest` breaks a tie
* toward positive infinity, and the other three are the ceiling, the floor and
* the truncation. A step of zero is NaN per the spec and engines do not agree
* on what that renders as; a negative one is left alone rather than reasoned
* about.
* @param {number[]} values the value and the step
* @param {string} strategy one of the grammar's rounding strategies
* @returns {number | null} the rounded multiple, or `null`
*/
const round = ([value, step], strategy) => {
if (!(step > 0)) return null;
const below = exactFloorDivide(value, step);
if (below === null) return null;
const at = /** @type {number} */ (exactMultiply(below, step));
// Exactly on a step is where engines stop agreeing: these are step functions,
// so an ulp of error in the engine's own conversion moves the answer a whole
// step. Headless Chromium reads `round(down,10cm,2cm)` as `8cm` and
// `round(down,-7cm,.5cm)` as `-7.5cm`. Away from a boundary the gap is orders
// of magnitude wider than any such error, so only the boundary is refused.
if (at === value) return null;
let multiple;
if (strategy === "down") {
multiple = below;
} else if (strategy === "up") {
multiple = below + 1;
} else if (strategy === "to-zero") {
multiple = value < 0 ? below + 1 : below;
} else {
// The remainder is in `[0, step)`, so twice it against the step is the
// comparison, and an exact half rounds up — toward positive infinity.
const remainder = exactAdd(value, -at);
if (remainder === null) return null;
const doubled = exactMultiply(remainder, 2);
if (doubled === null) return null;
multiple = doubled >= step ? below + 1 : below;
}
return exactMultiply(multiple, step);
};
/**
* The remainder carrying the divisor's sign.
* @param {number[]} values the dividend and the divisor
* @returns {number | null} the remainder, or `null`
*/
const modulus = ([value, divisor]) => {
if (divisor === 0) return null;
const remainder = value % divisor;
// A zero remainder is the boundary these two share with `round()`, and engines
// do not agree on it: headless Chromium reads `mod(10px,-2px)` and
// `mod(-9px,3px)` as the divisor where both are zero.
if (remainder === 0) return null;
// A remainder on the other side of zero is brought back across it.
return remainder < 0 === divisor < 0
? remainder
: exactAdd(remainder, divisor);
};
/**
* The remainder carrying the dividend's sign, which is what `%` already does.
* @param {number[]} values the dividend and the divisor
* @returns {number | null} the remainder, or `null`
*/
const remainder = ([value, divisor]) => {
if (divisor === 0) return null;
// The same zero boundary `modulus` declines.
const rest = value % divisor;
return rest === 0 ? null : rest;
};
/**
* @param {number[]} values the one radicand
* @returns {number | null} its root, or `null` where there is none
*/
const squareRoot = ([value]) => (value >= 0 ? Math.sqrt(value) : null);
/**
* @param {number[]} values the base and the exponent
* @returns {number | null} the power, or `null`
*/
const power = ([base, exponent]) => {
const raised = base ** exponent;
return Number.isFinite(raised) ? raised : null;
};
/**
* @param {number[]} values the value and, optionally, the base
* @returns {number | null} the logarithm, or `null` where there is none
*/
const logarithm = ([value, base]) => {
if (!(value > 0)) return null;
if (base === undefined) return Math.log(value);
// A base of one divides by zero and a negative one has no logarithm at all;
// both leave a quotient that is not a number.
const quotient = Math.log(value) / Math.log(base);
return Number.isFinite(quotient) ? quotient : null;
};
/**
* @param {number[]} values the one exponent
* @returns {number | null} `e` raised to it, or `null`
*/
const exponential = ([value]) => {
const raised = Math.exp(value);
return Number.isFinite(raised) ? raised : null;
};
/**
* The value a table gives at a whole number of eighth turns, where a real
* computation would answer an ulp away from it — `Math.sin(Math.PI)` is 1.2e-16
* rather than the zero the table states.
* @param {number} degrees the angle
* @param {Map<number, number>} table the function's eighth-turn table
* @returns {number | undefined} the stated value, or undefined
*/
const eighthTurn = (degrees, table) => {
const eighths = degrees / 45;
return Number.isInteger(eighths)
? table.get(((eighths % 8) + 8) % 8)
: undefined;
};
/**
* An inverse trigonometric function answers with an angle, and an angle is the
* one thing the printer does not round — a `rotate()` runs it back through trig,
* where a truncated digit is a different matrix. So only the arguments the table
* states are taken: everywhere else the real answer carries digits that are
* noise (`asin(.5)` is 30.000000000000004 degrees) and no shorter than the call.
* @param {number[]} values the one argument
* @param {string} keyword unused
* @param {Map<number, number>} table the arguments the table states
* @returns {number | null} the angle in degrees, or `null`
*/
const statedAngle = ([value], keyword, table) => {
const stated = table.get(value);
return stated === undefined ? null : stated;
};
/**
* Tangent, which has an asymptote an odd quarter turn from zero: the table
* states no value there because there is none, and a double still answers with
* a very large one.
* @param {number[]} values the angle in degrees
* @param {string} keyword unused
* @param {Map<number, number>} table the eighth-turn table
* @returns {number | null} its tangent, or `null` at an asymptote
*/
const tangent = ([degrees], keyword, table) => {
const stated = eighthTurn(degrees, table);
if (stated !== undefined) return stated;
const quarters = degrees / 90;
if (Number.isInteger(quarters) && ((quarters % 2) + 2) % 2 === 1) return null;
return Math.tan((degrees * Math.PI) / 180);
};
/**
* @param {number[]} values the angle in degrees
* @param {string} keyword unused
* @param {Map<number, number>} table the eighth-turn table
* @returns {number | null} its cosine
*/
const cosine = ([degrees], keyword, table) => {
const stated = eighthTurn(degrees, table);
return stated === undefined ? Math.cos((degrees * Math.PI) / 180) : stated;
};
/**
* @param {number[]} values the angle in degrees
* @param {string} keyword unused
* @param {Map<number, number>} table the eighth-turn table
* @returns {number | null} its sine
*/
const sine = ([degrees], keyword, table) => {
const stated = eighthTurn(degrees, table);
return stated === undefined ? Math.sin((degrees * Math.PI) / 180) : stated;
};
/**
* The eight directions the arc tangent of a ratio is a whole number of degrees
* in, an eighth turn apart. Both zero is refused: the spec leaves it to the
* engine.
* @param {number[]} values the two coordinates
* @returns {number | null} the angle in degrees, or `null`
*/
const arcTangent2 = ([y, x]) => {
if (y === 0 && x === 0) return null;
if (y === 0) return x > 0 ? 0 : 180;
if (x === 0) return y > 0 ? 90 : -90;
if (Math.abs(y) !== Math.abs(x)) return null;
if (x > 0) return y > 0 ? 45 : -45;
return y > 0 ? 135 : -135;
};
// Properties whose value is CSS's `{1,4}` box notation, where an omitted value
// is copied from the opposite side. That makes a repeated value redundant:
// `margin:1px 1px 1px 1px` is `margin:1px`. `border-radius` collapses each side
// of its `/` independently.
const BOX_SHORTHANDS = new Set([
"border-color",
"border-image-outset",
"border-image-width",
"border-radius",
"border-style",
"border-width",
"corner-shape",
"inset",
"margin",
"mask-border-outset",
"mask-border-width",
"padding",
"scroll-margin",
"scroll-padding"
]);
// The subset carrying a second box after a `/`, which collapses on its own.
const SLASH_BOX_SHORTHANDS = new Set(["border-radius"]);
// The four longhands each box shorthand sets, in the order `{1,4}` writes them:
// `top right bottom left`, or clockwise from the top left for a corner family.
// Only the families whose longhands are those four: merging those into the
// shorthand sets exactly the same properties, resetting nothing extra.
// prettier-ignore
const BOX_LONGHANDS = new Map([
["border-color", ["border-top-color", "border-right-color", "border-bottom-color", "border-left-color"]],
["border-radius", ["border-top-left-radius", "border-top-right-radius", "border-bottom-right-radius", "border-bottom-left-radius"]],
["border-style", ["border-top-style", "border-right-style", "border-bottom-style", "border-left-style"]],
["border-width", ["border-top-width", "border-right-width", "border-bottom-width", "border-left-width"]],
["corner-shape", ["corner-top-left-shape", "corner-top-right-shape", "corner-bottom-right-shape", "corner-bottom-left-shape"]],
["inset", ["top", "right", "bottom", "left"]],
["margin", ["margin-top", "margin-right", "margin-bottom", "margin-left"]],
["padding", ["padding-top", "padding-right", "padding-bottom", "padding-left"]],
["scroll-margin", ["scroll-margin-top", "scroll-margin-right", "scroll-margin-bottom", "scroll-margin-left"]],
["scroll-padding", ["scroll-padding-top", "scroll-padding-right", "scroll-padding-bottom", "scroll-padding-left"]]
]);
// The shorthands setting exactly two longhands, positionally — the same merge
// as the box families, two values wide. Only these: a shorthand gathering a
// whole family resets longhands `computed` does not name.
const PAIR_LONGHANDS = new Map([
[
"border-block-color",
["border-block-start-color", "border-block-end-color"]
],
[
"border-block-style",
["border-block-start-style", "border-block-end-style"]
],
[
"border-block-width",
["border-block-start-width", "border-block-end-width"]
],
[
"border-inline-color",
["border-inline-start-color", "border-inline-end-color"]
],
[
"border-inline-style",
["border-inline-start-style", "border-inline-end-style"]
],
[
"border-inline-width",
["border-inline-start-width", "border-inline-end-width"]
],
[
"contain-intrinsic-size",
["contain-intrinsic-width", "contain-intrinsic-height"]
],
[
"corner-block-end-shape",
["corner-end-start-shape", "corner-end-end-shape"]
],
[
"corner-block-start-shape",
["corner-start-start-shape", "corner-start-end-shape"]
],
[
"corner-bottom-shape",
["corner-bottom-left-shape", "corner-bottom-right-shape"]
],
[
"corner-inline-end-shape",
["corner-start-end-shape", "corner-end-end-shape"]
],
[
"corner-inline-start-shape",
["corner-start-start-shape", "corner-end-start-shape"]
],
["corner-left-shape", ["corner-top-left-shape", "corner-bottom-left-shape"]],
[
"corner-right-shape",
["corner-top-right-shape", "corner-bottom-right-shape"]
],
["corner-top-shape", ["corner-top-left-shape", "corner-top-right-shape"]],
["gap", ["row-gap", "column-gap"]],
["inset-block", ["inset-block-start", "inset-block-end"]],
["inset-inline", ["inset-inline-start", "inset-inline-end"]],
["interest-delay", ["interest-delay-start", "interest-delay-end"]],
["margin-block", ["margin-block-start", "margin-block-end"]],
["margin-inline", ["margin-inline-start", "margin-inline-end"]],
["overflow", ["overflow-x", "overflow-y"]],
["overscroll-behavior", ["overscroll-behavior-x", "overscroll-behavior-y"]],
["padding-block", ["padding-block-start", "padding-block-end"]],
["padding-inline", ["padding-inline-start", "padding-inline-end"]],
["place-content", ["align-content", "justify-content"]],
["place-items", ["align-items", "justify-items"]],
["place-self", ["align-self", "justify-self"]],
[
"scroll-margin-block",
["scroll-margin-block-start", "scroll-margin-block-end"]
],
[
"scroll-margin-inline",
["scroll-margin-inline-start", "scroll-margin-inline-end"]
],
[
"scroll-padding-block",
["scroll-padding-block-start", "scroll-padding-block-end"]
],
[
"scroll-padding-inline",
["scroll-padding-inline-start", "scroll-padding-inline-end"]
]
]);
// The subset whose two-value form is newer than the longhands, so only a merge
// collapsing to one value may emit it.
const ONE_VALUE_PAIR_SHORTHANDS = new Set(["overflow"]);
// The pair shorthands the target's `placeShorthand` ability gates, newer than
// the longhands they merge.
const PLACE_SHORTHANDS = new Set([
"place-content",
"place-items",
"place-self"
]);
// The keywords a shorthand's longhands disagree on, so a merge writing one into
// every slot would turn a declaration the engine kept into a shorthand it drops:
// `justify-items` takes `left` and `align-items` does not.
const UNSHARED_LONGHAND_KEYWORDS = new Map([
["place-content", new Set(["baseline", "first", "last", "left", "right"])],
["place-items", new Set(["left", "legacy", "right"])],
["place-self", new Set(["left", "right"])]
]);
// The shorthands written as an order-free `||` of their own longhands, each
// appearing once, in grammar order. A merge emits every value, so the only
// question is whether each parses back into the longhand it was authored on.
// prettier-ignore
// The properties whose value ends in a family list, out of the grammars: the
// longhand and the shorthands that reference it.
const FAMILY_LIST_PROPERTIES = new Set(["font", "font-family"]);
const FAMILY_LONGHANDS = new Map([
[
"border-block-end",
[
"border-block-end-width",
"border-block-end-style",
"border-block-end-color"
]
],
[
"border-block-start",
[
"border-block-start-width",
"border-block-start-style",
"border-block-start-color"
]
],
[
"border-bottom",
["border-bottom-width", "border-bottom-style", "border-bottom-color"]
],
[
"border-inline-end",
[
"border-inline-end-width",
"border-inline-end-style",
"border-inline-end-color"
]
],
[
"border-inline-start",
[
"border-inline-start-width",
"border-inline-start-style",
"border-inline-start-color"
]
],
[
"border-left",
["border-left-width", "border-left-style", "border-left-color"]
],
[
"border-right",
["border-right-width", "border-right-style", "border-right-color"]
],
["border-top", ["border-top-width", "border-top-style", "border-top-color"]],
[
"column-rule",
["column-rule-width", "column-rule-style", "column-rule-color"]
],
["flex-flow", ["flex-direction", "flex-wrap"]],
[
"list-style",
["list-style-type", "list-style-position", "list-style-image"]
],
["outline", ["outline-width", "outline-style", "outline-color"]],
[
"text-decoration",
[
"text-decoration-line",
"text-decoration-style",
"text-decoration-color",
"text-decoration-thickness"
]
],
["text-emphasis", ["text-emphasis-style", "text-emphasis-color"]],
["text-wrap", ["text-wrap-mode", "text-wrap-style"]]
]);
// The properties whose comma-separated items take a `<custom-ident>`, where a
// vendor spelling is a name the engine parses rather than one it may drop — so a
// later declaration listing an earlier one's items cannot be its fallback.
const CUSTOM_IDENT_LIST_PROPERTIES = new Set([
"animation",
"animation-name",
"animation-trigger",
"font-family",
"font-variant",
"font-variant-alternates",
"timeline-trigger-name",
"timeline-trigger-source",
"transition",
"transition-property",
"trigger-scope",
"will-change"
]);
// The shorthands whose grammar juxtaposes its longhands in a fixed order, so a
// merge writes every value by position rather than reading which slot takes it.
const ORDERED_LONGHANDS = new Map([
["flex", ["flex-grow", "flex-shrink", "flex-basis"]]
]);
const SLASH_LONGHANDS = new Map([
[
"grid-area",
["grid-row-start", "grid-column-start", "grid-row-end", "grid-column-end"]
],
["grid-column", ["grid-column-start", "grid-column-end"]],
["grid-row", ["grid-row-start", "grid-row-end"]]
]);
// Every longhand each shorthand sets, so one block can be asked whether another
// could shadow it. Not every shorthand prefixes its longhands: `inset` sets `top`.
const SHORTHAND_LONGHANDS = new Map([
[
"-moz-outline-radius",
new Set([
"-moz-outline-radius-bottomleft",
"-moz-outline-radius-bottomright",
"-moz-outline-radius-topleft",
"-moz-outline-radius-topright"
])
],
[
"-ms-content-zoom-limit",
new Set(["-ms-content-zoom-limit-max", "-ms-content-zoom-limit-min"])
],
[
"-ms-content-zoom-snap",
new Set(["-ms-content-zoom-snap-points", "-ms-content-zoom-snap-type"])
],
[
"-ms-scroll-limit",
new Set([
"-ms-scroll-limit-x-max",
"-ms-scroll-limit-x-min",
"-ms-scroll-limit-y-max",
"-ms-scroll-limit-y-min"
])
],
[
"-ms-scroll-snap-x",
new Set(["-ms-scroll-snap-points-x", "-ms-scroll-snap-type"])
],
[
"-ms-scroll-snap-y",
new Set(["-ms-scroll-snap-points-y", "-ms-scroll-snap-type"])
],
[
"-webkit-border-after",
new Set([
"border-block-end-color",
"border-block-end-style",
"border-block-end-width"
])
],
[
"-webkit-border-before",
new Set([
"border-block-start-color",
"border-block-start-style",
"border-block-start-width"
])
],
[
"-webkit-border-end",
new Set([
"border-inline-end-color",
"border-inline-end-style",
"border-inline-end-width"
])
],
[
"-webkit-border-start",
new Set([
"border-inline-start-color",
"border-inline-start-style",
"border-inline-start-width"
])
],
[
"-webkit-mask",
new Set([
"-webkit-mask-attachment",
"-webkit-mask-clip",
"-webkit-mask-image",
"-webkit-mask-origin",
"-webkit-mask-position",
"-webkit-mask-repeat"
])
],
[
"-webkit-text-stroke",
new Set(["-webkit-text-stroke-color", "-webkit-text-stroke-width"])
],
[
"animation",
new Set([
"animation-delay",
"animation-direction",
"animation-duration",
"animation-fill-mode",
"animation-iteration-count",
"animation-name",
"animation-play-state",
"animation-timeline",
"animation-timing-function"
])
],
[
"animation-range",
new Set(["animation-range-end", "animation-range-start"])
],
[
"background",
new Set([
"background-attachment",
"background-clip",
"background-color",
"background-image",
"background-origin",
"background-position",
"background-position-x",
"background-position-y",
"background-repeat",
"background-size"
])
],
[
"background-position",
new Set(["background-position-x", "background-position-y"])
],
[
"border",
new Set([
"border-bottom-color",
"border-bottom-style",
"border-bottom-width",
"border-color",
"border-left-color",
"border-left-style",
"border-left-width",
"border-right-color",
"border-right-style",
"border-right-width",
"border-style",
"border-top-color",
"border-top-style",
"border-top-width",
"border-width"
])
],
[
"border-block",
new Set([
"border-block-color",
"border-block-end-color",
"border-block-end-style",
"border-block-end-width",
"border-block-start-color",
"border-block-start-style",
"border-block-start-width",
"border-block-style",
"border-block-width"
])
],
[
"border-block-color",
new Set(["border-block-end-color", "border-block-start-color"])
],
[
"border-block-end",
new Set([
"border-block-end-color",
"border-block-end-style",
"border-block-end-width"
])
],
[
"border-block-start",
new Set([
"border-block-start-color",
"border-block-start-style",
"border-block-start-width"
])
],
[
"border-block-style",
new Set(["border-block-end-style", "border-block-start-style"])
],
[
"border-block-width",
new Set(["border-block-end-width", "border-block-start-width"])
],
[
"border-bottom",
new Set([
"border-bottom-color",
"border-bottom-style",
"border-bottom-width"
])
],
[
"border-color",
new Set([
"border-bottom-color",
"border-left-color",
"border-right-color",
"border-top-color"
])
],
[
"border-image",
new Set([
"border-image-outset",
"border-image-repeat",
"border-image-slice",
"border-image-source",
"border-image-width"
])
],
[
"border-inline",
new Set([
"border-inline-color",
"border-inline-end-color",
"border-inline-end-style",
"border-inline-end-width",
"border-inline-start-color",
"border-inline-start-style",
"border-inline-start-width",
"border-inline-style",
"border-inline-width"
])
],
[
"border-inline-color",
new Set(["border-inline-end-color", "border-inline-start-color"])
],
[
"border-inline-end",
new Set([
"border-inline-end-color",
"border-inline-end-style",
"border-inline-end-width"
])
],
[
"border-inline-start",
new Set([
"border-inline-start-color",
"border-inline-start-style",
"border-inline-start-width"
])
],
[
"border-inline-style",
new Set(["border-inline-end-style", "border-inline-start-style"])
],
[
"border-inline-width",
new Set(["border-inline-end-width", "border-inline-start-width"])
],
[
"border-left",
new Set(["border-left-color", "border-left-style", "border-left-width"])
],
[
"border-radius",
new Set([
"border-bottom-left-radius",
"border-bottom-right-radius",
"border-top-left-radius",
"border-top-right-radius"
])
],
[
"border-right",
new Set(["border-right-color", "border-right-style", "border-right-width"])
],
[
"border-style",
new Set([
"border-bottom-style",
"border-left-style",
"border-right-style",
"border-top-style"
])
],
[
"border-top",
new Set(["border-top-color", "border-top-style", "border-top-width"])
],
[
"border-width",
new Set([
"border-bottom-width",
"border-left-width",
"border-right-width",
"border-top-width"
])
],
["caret", new Set(["caret-animation", "caret-color", "caret-shape"])],
[
"column-rule",
new Set(["column-rule-color", "column-rule-style", "column-rule-width"])
],
["columns", new Set(["column-count", "column-height", "column-width"])],
[
"contain-intrinsic-size",
new Set(["contain-intrinsic-height", "contain-intrinsic-width"])
],
["container", new Set(["container-name", "container-type"])],
[
"corner-block-end-shape",
new Set(["corner-end-end-shape", "corner-end-start-shape"])
],
[
"corner-block-start-shape",
new Set(["corner-start-end-shape", "corner-start-start-shape"])
],
[
"corner-bottom-shape",
new Set(["corner-bottom-left-shape", "corner-bottom-right-shape"])
],
[
"corner-inline-end-shape",
new Set(["corner-end-end-shape", "corner-start-end-shape"])
],
[
"corner-inline-start-shape",
new Set(["corner-start-end-shape", "corner-start-start-shape"])
],
[
"corner-left-shape",
new Set(["corner-bottom-left-shape", "corner-top-left-shape"])
],
[
"corner-right-shape",
new Set(["corner-bottom-right-shape", "corner-top-right-shape"])
],
[
"corner-shape",
new Set([
"corner-bottom-left-shape",
"corner-bottom-right-shape",
"corner-top-left-shape",
"corner-top-right-shape"
])
],
[
"corner-top-shape",
new Set(["corner-top-left-shape", "corner-top-right-shape"])
],
["flex", new Set(["flex-basis", "flex-grow", "flex-shrink"])],
["flex-flow", new Set(["flex-direction", "flex-wrap"])],
[
"font",
new Set([
"font-family",
"font-size",
"font-stretch",
"font-style",
"font-variant",
"font-weight",
"line-height"
])
],
["gap", new Set(["column-gap", "row-gap"])],
[
"grid",
new Set([
"column-gap",
"grid-auto-columns",
"grid-auto-flow",
"grid-auto-rows",
"grid-column-gap",
"grid-row-gap",
"grid-template-areas",
"grid-template-columns",
"grid-template-rows",
"row-gap"
])
],
[
"grid-area",
new Set([
"grid-column-end",
"grid-column-start",
"grid-row-end",
"grid-row-start"
])
],
["grid-column", new Set(["grid-column-end", "grid-column-start"])],
["grid-gap", new Set(["grid-column-gap", "grid-row-gap"])],
["grid-row", new Set(["grid-row-end", "grid-row-start"])],
[
"grid-template",
new Set([
"grid-template-areas",
"grid-template-columns",
"grid-template-rows"
])
],
["inset", new Set(["bottom", "left", "right", "top"])],
["inset-block", new Set(["inset-block-end", "inset-block-start"])],
["inset-inline", new Set(["inset-inline-end", "inset-inline-start"])],
["interest-delay", new Set(["interest-delay-end", "interest-delay-start"])],
[
"list-style",
new Set(["list-style-image", "list-style-position", "list-style-type"])
],
[
"margin",
new Set(["margin-bottom", "margin-left", "margin-right", "margin-top"])
],
["margin-block", new Set(["margin-block-end", "margin-block-start"])],
["margin-inline", new Set(["margin-inline-end", "margin-inline-start"])],
[
"mask",
new Set([
"mask-clip",
"mask-composite",
"mask-image",
"mask-mode",
"mask-origin",
"mask-position",
"mask-repeat",
"mask-size"
])
],
[
"mask-border",
new Set([
"mask-border-mode",
"mask-border-outset",
"mask-border-repeat",
"mask-border-slice",
"mask-border-source",
"mask-border-width"
])
],
[
"offset",
new Set([
"offset-anchor",
"offset-distance",
"offset-path",
"offset-position",
"offset-rotate"
])
],
["outline", new Set(["outline-color", "outline-style", "outline-width"])],
["overflow", new Set(["overflow-x", "overflow-y"])],
[
"overscroll-behavior",
new Set(["overscroll-behavior-x", "overscroll-behavior-y"])
],
[
"padding",
new Set(["padding-bottom", "padding-left", "padding-right", "padding-top"])
],
["padding-block", new Set(["padding-block-end", "padding-block-start"])],
["padding-inline", new Set(["padding-inline-end", "padding-inline-start"])],
["place-content", new Set(["align-content", "justify-content"])],
["place-items", new Set(["align-items", "justify-items"])],
["place-self", new Set(["align-self", "justify-self"])],
["position-try", new Set(["position-try-fallbacks", "position-try-order"])],
[
"scroll-margin",
new Set([
"scroll-margin-bottom",
"scroll-margin-left",
"scroll-margin-right",
"scroll-margin-top"
])
],
[
"scroll-margin-block",
new Set(["scroll-margin-block-end", "scroll-margin-block-start"])
],
[
"scroll-margin-inline",
new Set(["scroll-margin-inline-end", "scroll-margin-inline-start"])
],
[
"scroll-padding",
new Set([
"scroll-padding-bottom",
"scroll-padding-left",
"scroll-padding-right",
"scroll-padding-top"
])
],
[
"scroll-padding-block",
new Set(["scroll-padding-block-end", "scroll-padding-block-start"])
],
[
"scroll-padding-inline",
new Set(["scroll-padding-inline-end", "scroll-padding-inline-start"])
],
[
"scroll-timeline",
new Set(["scroll-timeline-axis", "scroll-timeline-name"])
],
[
"text-decoration",
new Set([
"text-decoration-color",
"text-decoration-line",
"text-decoration-style",
"text-decoration-thickness"
])
],
["text-emphasis", new Set(["text-emphasis-color", "text-emphasis-style"])],
["text-wrap", new Set(["text-wrap-mode", "text-wrap-style"])],
[
"timeline-trigger",
new Set([
"timeline-trigger-activation-range",
"timeline-trigger-activation-range-end",
"timeline-trigger-activation-range-start",
"timeline-trigger-active-range",
"timeline-trigger-active-range-end",
"timeline-trigger-active-range-start",
"timeline-trigger-name",
"timeline-trigger-source"
])
],
[
"timeline-trigger-activation-range",
new Set([
"timeline-trigger-activation-range-end",
"timeline-trigger-activation-range-start"
])
],
[
"timeline-trigger-active-range",
new Set([
"timeline-trigger-active-range-end",
"timeline-trigger-active-range-start"
])
],
[
"transition",
new Set([
"transition-behavior",
"transition-delay",
"transition-duration",
"transition-property",
"transition-timing-function"
])
],
["view-timeline", new Set(["view-timeline-axis", "view-timeline-name"])]
]);
// Every longhand the three merge tables above can consume, so a block is asked
// once whether it holds anything mergeable at all. Two of them have to be
// present before any shorthand can be written, and almost no block holds one,
// which is what keeps the merge off the declarations it cannot serve.
const MERGE_LONGHANDS = new Set([
"align-content",
"align-items",
"align-self",
"border-block-end-color",
"border-block-end-style",
"border-block-end-width",
"border-block-start-color",
"border-block-start-style",
"border-block-start-width",
"border-bottom-color",
"border-bottom-left-radius",
"border-bottom-right-radius",
"border-bottom-style",
"border-bottom-width",
"border-inline-end-color",
"border-inline-end-style",
"border-inline-end-width",
"border-inline-start-color",
"border-inline-start-style",
"border-inline-start-width",
"border-left-color",
"border-left-style",
"border-left-width",
"border-right-color",
"border-right-style",
"border-right-width",
"border-top-color",
"border-top-left-radius",
"border-top-right-radius",
"border-top-style",
"border-top-width",
"bottom",
"column-gap",
"column-rule-color",
"column-rule-style",
"column-rule-width",
"contain-intrinsic-height",
"contain-intrinsic-width",
"corner-bottom-left-shape",
"corner-bottom-right-shape",
"corner-end-end-shape",
"corner-end-start-shape",
"corner-start-end-shape",
"corner-start-start-shape",
"corner-top-left-shape",
"corner-top-right-shape",
"flex-basis",
"flex-direction",
"flex-grow",
"flex-shrink",
"flex-wrap",
"grid-column-end",
"grid-column-start",
"grid-row-end",
"grid-row-start",
"inset-block-end",
"inset-block-start",
"inset-inline-end",
"inset-inline-start",
"interest-delay-end",
"interest-delay-start",
"justify-content",
"justify-items",
"justify-self",
"left",
"list-style-image",
"list-style-position",
"list-style-type",
"margin-block-end",
"margin-block-start",
"margin-bottom",
"margin-inline-end",
"margin-inline-start",
"margin-left",
"margin-right",
"margin-top",
"outline-color",
"outline-style",
"outline-width",
"overflow-x",
"overflow-y",
"overscroll-behavior-x",
"overscroll-behavior-y",
"padding-block-end",
"padding-block-start",
"padding-bottom",
"padding-inline-end",
"padding-inline-start",
"padding-left",
"padding-right",
"padding-top",
"right",
"row-gap",
"scroll-margin-block-end",
"scroll-margin-block-start",
"scroll-margin-bottom",
"scroll-margin-inline-end",
"scroll-margin-inline-start",
"scroll-margin-left",
"scroll-margin-right",
"scroll-margin-top",
"scroll-padding-block-end",
"scroll-padding-block-start",
"scroll-padding-bottom",
"scroll-padding-inline-end",
"scroll-padding-inline-start",
"scroll-padding-left",
"scroll-padding-right",
"scroll-padding-top",
"text-decoration-color",
"text-decoration-line",
"text-decoration-style",
"text-decoration-thickness",
"text-emphasis-color",
"text-emphasis-style",
"text-wrap-mode",
"text-wrap-style",
"top"
]);
// The initial keyword each of these may drop when another component stands
// beside it: omitting the group it belongs to leaves exactly that keyword. The
// second half is every keyword that group offers — a value naming two of them
// (`grid-auto-flow:row dense column`) fills the slot twice and is invalid, so
// dropping the initial there would print a value the author never wrote.
/** @type {Map<string, [string, string[]]>} */
// prettier-ignore
const OMITTABLE_INITIAL_KEYWORDS = new Map([["grid-auto-flow", ["row", ["column","row"]]]]);
// What each of those longhands accepts as a whole value: the keywords it names,
// and the value classes it reaches. A value acceptable to a second slot is what
// makes the merge ambiguous, and `FAMILY_SLOT_CLASSES` names a type the printer
// cannot classify as readily as one it can, so an unknown one declines.
// prettier-ignore
const FAMILY_SLOT_KEYWORDS = new Map([["border-block-end-width", ["medium","thick","thin"]], ["border-block-end-style", ["dashed","dotted","double","groove","hidden","inset","none","outset","ridge","solid"]], ["border-block-end-color", []], ["border-block-start-width", ["medium","thick","thin"]], ["border-block-start-style", ["dashed","dotted","double","groove","hidden","inset","none","outset","ridge","solid"]], ["border-block-start-color", []], ["border-bottom-width", ["medium","thick","thin"]], ["border-bottom-style", ["dashed","dotted","double","groove","hidden","inset","none","outset","ridge","solid"]], ["border-bottom-color", []], ["border-inline-end-width", ["medium","thick","thin"]], ["border-inline-end-style", ["dashed","dotted","double","groove","hidden","inset","none","outset","ridge","solid"]], ["border-inline-end-color", []], ["border-inline-start-width", ["medium","thick","thin"]], ["border-inline-start-style", ["dashed","dotted","double","groove","hidden","inset","none","outset","ridge","solid"]], ["border-inline-start-color", []], ["border-left-width", ["medium","thick","thin"]], ["border-left-style", ["dashed","dotted","double","groove","hidden","inset","none","outset","ridge","solid"]], ["border-left-color", []], ["border-right-width", ["medium","thick","thin"]], ["border-right-style", ["dashed","dotted","double","groove","hidden","inset","none","outset","ridge","solid"]], ["border-right-color", []], ["border-top-width", ["medium","thick","thin"]], ["border-top-style", ["dashed","dotted","double","groove","hidden","inset","none","outset","ridge","solid"]], ["border-top-color", []], ["column-rule-width", ["medium","thick","thin"]], ["column-rule-style", ["dashed","dotted","double","groove","hidden","inset","none","outset","ridge","solid"]], ["column-rule-color", []], ["flex-direction", ["column","column-reverse","row","row-reverse"]], ["flex-wrap", ["nowrap","wrap","wrap-reverse"]], ["list-style-type", ["none"]], ["list-style-position", ["inside","outside"]], ["list-style-image", ["none"]], ["outline-width", ["medium","thick","thin"]], ["outline-style", ["auto","dashed","dotted","double","groove","inset","none","outset","ridge","solid"]], ["outline-color", ["auto"]], ["text-decoration-line", ["blink","grammar-error","line-through","none","overline","spelling-error","underline"]], ["text-decoration-style", ["dashed","dotted","double","solid","wavy"]], ["text-decoration-color", []], ["text-decoration-thickness", ["auto","from-font"]], ["text-emphasis-style", ["circle","dot","double-circle","filled","none","open","sesame","triangle"]], ["text-emphasis-color", []], ["text-wrap-mode", ["nowrap","wrap"]], ["text-wrap-style", ["auto","balance","pretty","stable"]]]);
// prettier-ignore
const FAMILY_SLOT_CLASSES = new Map([["border-block-end-width", ["length"]], ["border-block-end-style", []], ["border-block-end-color", ["color"]], ["border-block-start-width", ["length"]], ["border-block-start-style", []], ["border-block-start-color", ["color"]], ["border-bottom-width", ["length"]], ["border-bottom-style", []], ["border-bottom-color", ["color"]], ["border-inline-end-width", ["length"]], ["border-inline-end-style", []], ["border-inline-end-color", ["color"]], ["border-inline-start-width", ["length"]], ["border-inline-start-style", []], ["border-inline-start-color", ["color"]], ["border-left-width", ["length"]], ["border-left-style", []], ["border-left-color", ["color"]], ["border-right-width", ["length"]], ["border-right-style", []], ["border-right-color", ["color"]], ["border-top-width", ["length"]], ["border-top-style", []], ["border-top-color", ["color"]], ["column-rule-width", ["length"]], ["column-rule-style", []], ["column-rule-color", ["color"]], ["flex-direction", []], ["flex-wrap", []], ["list-style-type", ["custom-ident","string"]], ["list-style-position", []], ["list-style-image", ["image"]], ["outline-width", ["length"]], ["outline-style", []], ["outline-color", ["color"]], ["text-decoration-line", []], ["text-decoration-style", []], ["text-decoration-color", ["color"]], ["text-decoration-thickness", ["length","percentage"]], ["text-emphasis-style", ["string"]], ["text-emphasis-color", ["color"]], ["text-wrap-mode", []], ["text-wrap-style", []]]);
// The identifiers that are a `<color>` on their own — named, system and the two
// context-dependent ones. Read off the `<color>` grammar outside any function,
// so a channel keyword like the `none` in `hsl(0 none 0)` is not among them.
// cspell:ignore accentcolor accentcolortext activeborder activecaption activetext aliceblue antiquewhite appworkspace aqua aquamarine azure background beige bisque black blanchedalmond blue blueviolet brown burlywood buttonborder buttonface buttonhighlight buttonshadow buttontext cadetblue canvas canvastext captiontext chartreuse chocolate coral cornflowerblue cornsilk crimson currentcolor cyan darkblue darkcyan darkgoldenrod darkgray darkgreen darkgrey darkkhaki darkmagenta darkolivegreen darkorange darkorchid darkred darksalmon darkseagreen darkslateblue darkslategray darkslategrey darkturquoise darkviolet deeppink deepskyblue dimgray dimgrey dodgerblue field fieldtext firebrick floralwhite forestgreen fuchsia gainsboro ghostwhite gold goldenrod gray graytext green greenyellow grey highlight highlighttext honeydew hotpink inactiveborder inactivecaption inactivecaptiontext indianred indigo infobackground infotext ivory khaki lavender lavenderblush lawngreen lemonchiffon lightblue lightcoral lightcyan lightgoldenrodyellow lightgray lightgreen lightgrey lightpink lightsalmon lightseagreen lightskyblue lightslategray lightslategrey lightsteelblue lightyellow lime limegreen linen linktext magenta mark marktext maroon mediumaquamarine mediumblue mediumorchid mediumpurple mediumseagreen mediumslateblue mediumspringgreen mediumturquoise mediumvioletred menu menutext midnightblue mintcream mistyrose moccasin navajowhite navy oldlace olive olivedrab orange orangered orchid palegoldenrod palegreen paleturquoise palevioletred papayawhip peachpuff peru pink plum powderblue purple rebeccapurple red rosybrown royalblue saddlebrown salmon sandybrown scrollbar seagreen seashell selecteditem selecteditemtext sienna silver skyblue slateblue slategray slategrey snow springgreen steelblue tan teal thistle threeddarkshadow threedface threedhighlight threedlightshadow threedshadow tomato transparent turquoise violet visitedtext wheat white whitesmoke window windowframe windowtext yellow yellowgreen
const COLOR_KEYWORDS = new Set([
"accentcolor",
"accentcolortext",
"activeborder",
"activecaption",
"activetext",
"aliceblue",
"antiquewhite",
"appworkspace",
"aqua",
"aquamarine",
"azure",
"background",
"beige",
"bisque",
"black",
"blanchedalmond",
"blue",
"blueviolet",
"brown",
"burlywood",
"buttonborder",
"buttonface",
"buttonhighlight",
"buttonshadow",
"buttontext",
"cadetblue",
"canvas",
"canvastext",
"captiontext",
"chartreuse",
"chocolate",
"coral",
"cornflowerblue",
"cornsilk",
"crimson",
"currentcolor",
"cyan",
"darkblue",
"darkcyan",
"darkgoldenrod",
"darkgray",
"darkgreen",
"darkgrey",
"darkkhaki",
"darkmagenta",
"darkolivegreen",
"darkorange",
"darkorchid",
"darkred",
"darksalmon",
"darkseagreen",
"darkslateblue",
"darkslategray",
"darkslategrey",
"darkturquoise",
"darkviolet",
"deeppink",
"deepskyblue",
"dimgray",
"dimgrey",
"dodgerblue",
"field",
"fieldtext",
"firebrick",
"floralwhite",
"forestgreen",
"fuchsia",
"gainsboro",
"ghostwhite",
"gold",
"goldenrod",
"gray",
"graytext",
"green",
"greenyellow",
"grey",
"highlight",
"highlighttext",
"honeydew",
"hotpink",
"inactiveborder",
"inactivecaption",
"inactivecaptiontext",
"indianred",
"indigo",
"infobackground",
"infotext",
"ivory",
"khaki",
"lavender",
"lavenderblush",
"lawngreen",
"lemonchiffon",
"lightblue",
"lightcoral",
"lightcyan",
"lightgoldenrodyellow",
"lightgray",
"lightgreen",
"lightgrey",
"lightpink",
"lightsalmon",
"lightseagreen",
"lightskyblue",
"lightslategray",
"lightslategrey",
"lightsteelblue",
"lightyellow",
"lime",
"limegreen",
"linen",
"linktext",
"magenta",
"mark",
"marktext",
"maroon",
"mediumaquamarine",
"mediumblue",
"mediumorchid",
"mediumpurple",
"mediumseagreen",
"mediumslateblue",
"mediumspringgreen",
"mediumturquoise",
"mediumvioletred",
"menu",
"menutext",
"midnightblue",
"mintcream",
"mistyrose",
"moccasin",
"navajowhite",
"navy",
"oldlace",
"olive",
"olivedrab",
"orange",
"orangered",
"orchid",
"palegoldenrod",
"palegreen",
"paleturquoise",
"palevioletred",
"papayawhip",
"peachpuff",
"peru",
"pink",
"plum",
"powderblue",
"purple",
"rebeccapurple",
"red",
"rosybrown",
"royalblue",
"saddlebrown",
"salmon",
"sandybrown",
"scrollbar",
"seagreen",
"seashell",
"selecteditem",
"selecteditemtext",
"sienna",
"silver",
"skyblue",
"slateblue",
"slategray",
"slategrey",
"snow",
"springgreen",
"steelblue",
"tan",
"teal",
"thistle",
"threeddarkshadow",
"threedface",
"threedhighlight",
"threedlightshadow",
"threedshadow",
"tomato",
"transparent",
"turquoise",
"violet",
"visitedtext",
"wheat",
"white",
"whitesmoke",
"window",
"windowframe",
"windowtext",
"yellow",
"yellowgreen"
]);
// The name prefix a declaration between two box longhands must not carry for the
// merge to step over it. The shorthand's first segment, which is deliberately
// wider than the family: `border-color` blocks every `border*` property, since
// `border`, `border-top` and `border-block-start-color` all write its longhands
// and `mdn-data`'s `computed` lists only some of them.
const BOX_FAMILY_PREFIX = new Map([
["border-color", "border"],
["border-radius", "border"],
["border-style", "border"],
["border-width", "border"],
["corner-shape", "corner"],
["inset", "inset"],
["margin", "margin"],
["padding", "padding"],
["scroll-margin", "scroll"],
["scroll-padding", "scroll"]
]);
// Functions that take a `<color>` directly, so a hash among their arguments is a
// hex color rather than a case-sensitive reference (`element(#id)`). Only direct
// arguments: a gradient nested in `image-set()` is matched as the gradient.
const COLOR_ARGUMENT_FUNCTIONS = new Set([
"alpha",
"color",
"color-mix",
"conic-gradient",
"cross-fade",
"drop-shadow",
"image",
"light-dark",
"linear-gradient",
"radial-gradient",
"repeating-conic-gradient",
"repeating-linear-gradient",
"repeating-radial-gradient"
]);
// The functions that are a color rather than take one, out of `<color>`'s own
// grammar — what says a call fills a slot a color fills.
const COLOR_FUNCTIONS = new Set([
"color",
"color-mix",
"hsl",
"hsla",
"hwb",
"lab",
"lch",
"light-dark",
"oklab",
"oklch",
"rgb",
"rgba"
]);
// Functions that substitute an arbitrary token sequence, so two identical
// references need not be one repeated value: with `--x:1px 2px`,
// `margin:var(--x) var(--x)` is four values, not two.
const SUBSTITUTION_FUNCTIONS = new Set([
"attr",
"env",
"first-valid",
"if",
"inherit",
"paint",
"param",
"random-item",
"var"
]);
// The pseudo-class functions whose argument is An+B, where `2n+1` is the
// notation `odd` names in one byte less.
const NTH_PSEUDO_FUNCTIONS = new Set([
"nth-child",
"nth-last-child",
"nth-last-of-type",
"nth-of-type"
]);
// Each An+B pseudo-class whose one-element case has a name of its own:
// `:nth-child(1)` is what `:first-child` selects, in fewer bytes.
const NTH_NAMED_EQUIVALENTS = new Map([
["nth-child", "first-child"],
["nth-last-child", "last-child"],
["nth-last-of-type", "last-of-type"],
["nth-of-type", "first-of-type"]
]);
// The properties taking a color and never an identifier of the author's own, so
// a named color written in one is that color and may be spelled the shortest way.
const COLOR_ONLY_PROPERTIES = new Set([
"-moz-border-bottom-colors",
"-moz-border-left-colors",
"-moz-border-right-colors",
"-moz-border-top-colors",
"-ms-scrollbar-3dlight-color",
"-ms-scrollbar-arrow-color",
"-ms-scrollbar-base-color",
"-ms-scrollbar-darkshadow-color",
"-ms-scrollbar-face-color",
"-ms-scrollbar-highlight-color",
"-ms-scrollbar-shadow-color",
"-ms-scrollbar-track-color",
"-webkit-border-after",
"-webkit-border-after-color",
"-webkit-border-before",
"-webkit-border-before-color",
"-webkit-border-end",
"-webkit-border-end-color",
"-webkit-border-start",
"-webkit-border-start-color",
"-webkit-tap-highlight-color",
"-webkit-text-fill-color",
"-webkit-text-stroke",
"-webkit-text-stroke-color",
"accent-color",
"backdrop-filter",
"background-color",
"border",
"border-block",
"border-block-color",
"border-block-end",
"border-block-end-color",
"border-block-start",
"border-block-start-color",
"border-bottom",
"border-bottom-color",
"border-color",
"border-inline",
"border-inline-color",
"border-inline-end",
"border-inline-end-color",
"border-inline-start",
"border-inline-start-color",
"border-left",
"border-left-color",
"border-right",
"border-right-color",
"border-top",
"border-top-color",
"box-shadow",
"caret",
"caret-color",
"color",
"column-rule",
"column-rule-color",
"fill",
"filter",
"flood-color",
"lighting-color",
"outline",
"outline-color",
"scrollbar-color",
"stop-color",
"stroke",
"stroke-color",
"text-decoration",
"text-decoration-color",
"text-emphasis",
"text-emphasis-color",
"text-shadow"
]);
// The properties whose value is keywords alone, so an identifier standing
// directly in one is a keyword rather than a name of the author's — and matches
// ASCII case-insensitively. A call's arguments are read against the function's
// own grammar, so they are not covered.
const KEYWORD_ONLY_PROPERTIES = new Set([
"-moz-appearance",
"-moz-context-properties",
"-moz-float-edge",
"-moz-force-broken-image-icon",
"-moz-orient",
"-moz-stack-sizing",
"-moz-text-blink",
"-moz-user-focus",
"-moz-user-input",
"-moz-user-modify",
"-moz-window-dragging",
"-moz-window-shadow",
"-ms-accelerator",
"-ms-block-progression",
"-ms-content-zoom-chaining",
"-ms-content-zoom-snap",
"-ms-content-zoom-snap-type",
"-ms-content-zooming",
"-ms-high-contrast-adjust",
"-ms-ime-align",
"-ms-overflow-style",
"-ms-scroll-chaining",
"-ms-scroll-rails",
"-ms-scroll-snap-type",
"-ms-scroll-snap-x",
"-ms-scroll-snap-y",
"-ms-scroll-translation",
"-ms-text-autospace",
"-ms-touch-select",
"-ms-user-select",
"-ms-wrap-flow",
"-ms-wrap-through",
"-webkit-appearance",
"-webkit-border-after-style",
"-webkit-border-before-style",
"-webkit-border-end-style",
"-webkit-border-start-style",
"-webkit-mask-attachment",
"-webkit-mask-clip",
"-webkit-mask-composite",
"-webkit-mask-origin",
"-webkit-mask-repeat",
"-webkit-mask-repeat-x",
"-webkit-mask-repeat-y",
"-webkit-overflow-scrolling",
"-webkit-touch-callout",
"-webkit-user-modify",
"-webkit-user-select",
"align-content",
"align-items",
"align-self",
"align-tracks",
"alignment-baseline",
"all",
"animation-composition",
"animation-direction",
"animation-fill-mode",
"animation-play-state",
"animation-timing-function",
"appearance",
"backface-visibility",
"background-attachment",
"background-blend-mode",
"background-clip",
"background-origin",
"background-repeat",
"baseline-source",
"border-block-end-style",
"border-block-start-style",
"border-block-style",
"border-bottom-style",
"border-collapse",
"border-image-repeat",
"border-inline-end-style",
"border-inline-start-style",
"border-inline-style",
"border-left-style",
"border-right-style",
"border-shape",
"border-style",
"border-top-style",
"box-align",
"box-decoration-break",
"box-direction",
"box-lines",
"box-orient",
"box-pack",
"box-sizing",
"break-after",
"break-before",
"break-inside",
"caption-side",
"caret-animation",
"caret-shape",
"clear",
"clip",
"clip-rule",
"color-interpolation-filters",
"column-fill",
"column-rule-style",
"column-span",
"column-wrap",
"contain",
"container-type",
"content-visibility",
"corner-block-end-shape",
"corner-block-start-shape",
"corner-bottom-left-shape",
"corner-bottom-right-shape",
"corner-bottom-shape",
"corner-end-end-shape",
"corner-end-start-shape",
"corner-inline-end-shape",
"corner-inline-start-shape",
"corner-left-shape",
"corner-right-shape",
"corner-shape",
"corner-start-end-shape",
"corner-start-start-shape",
"corner-top-left-shape",
"corner-top-right-shape",
"corner-top-shape",
"d",
"direction",
"display",
"dominant-baseline",
"dynamic-range-limit",
"empty-cells",
"field-sizing",
"fill-rule",
"flex-direction",
"flex-flow",
"flex-wrap",
"float",
"font-kerning",
"font-optical-sizing",
"font-synthesis",
"font-synthesis-position",
"font-synthesis-small-caps",
"font-synthesis-style",
"font-synthesis-weight",
"font-variant",
"font-variant-alternates",
"font-variant-caps",
"font-variant-east-asian",
"font-variant-emoji",
"font-variant-ligatures",
"font-variant-numeric",
"font-variant-position",
"forced-color-adjust",
"frame-sizing",
"grid-auto-flow",
"hanging-punctuation",
"hyphens",
"image-rendering",
"ime-mode",
"initial-letter-align",
"interactivity",
"interpolate-size",
"isolation",
"justify-content",
"justify-items",
"justify-self",
"justify-tracks",
"line-break",
"list-style-position",
"margin-trim",
"mask-border-mode",
"mask-border-repeat",
"mask-clip",
"mask-composite",
"mask-mode",
"mask-origin",
"mask-repeat",
"mask-type",
"masonry-auto-flow",
"math-shift",
"math-style",
"mix-blend-mode",
"object-fit",
"object-view-box",
"outline-style",
"overflow",
"overflow-anchor",
"overflow-block",
"overflow-clip-box",
"overflow-inline",
"overflow-wrap",
"overflow-x",
"overflow-y",
"overlay",
"overscroll-behavior",
"overscroll-behavior-block",
"overscroll-behavior-inline",
"overscroll-behavior-x",
"overscroll-behavior-y",
"page-break-after",
"page-break-before",
"page-break-inside",
"paint-order",
"place-content",
"place-items",
"place-self",
"pointer-events",
"position",
"position-area",
"position-try-order",
"position-visibility",
"print-color-adjust",
"reading-flow",
"resize",
"ruby-align",
"ruby-merge",
"ruby-overhang",
"ruby-position",
"scroll-behavior",
"scroll-initial-target",
"scroll-marker-group",
"scroll-snap-align",
"scroll-snap-points-x",
"scroll-snap-points-y",
"scroll-snap-stop",
"scroll-snap-type",
"scroll-snap-type-x",
"scroll-snap-type-y",
"scroll-target-group",
"scroll-timeline-axis",
"scrollbar-gutter",
"scrollbar-width",
"shape-rendering",
"speak-as",
"stroke-linecap",
"stroke-linejoin",
"table-layout",
"text-align",
"text-align-last",
"text-anchor",
"text-box",
"text-box-edge",
"text-box-trim",
"text-decoration-line",
"text-decoration-skip",
"text-decoration-skip-ink",
"text-decoration-style",
"text-emphasis-position",
"text-justify",
"text-orientation",
"text-rendering",
"text-spacing-trim",
"text-transform",
"text-underline-position",
"text-wrap",
"text-wrap-mode",
"text-wrap-style",
"touch-action",
"transform",
"transform-box",
"transform-style",
"transition-behavior",
"transition-timing-function",
"unicode-bidi",
"user-select",
"vector-effect",
"view-timeline-axis",
"view-transition-scope",
"visibility",
"white-space",
"white-space-collapse",
"word-break",
"word-wrap",
"writing-mode"
]);
// Each two-keyword `display` -> the single keyword naming the same box.
const DISPLAY_SHORT_FORMS = new Map([
["block flex", "flex"],
["block flow", "block"],
["block flow-root", "flow-root"],
["block grid", "grid"],
["block table", "table"],
["inline flex", "inline-flex"],
["inline flow", "inline"],
["inline flow-root", "inline-block"],
["inline grid", "inline-grid"],
["inline ruby", "ruby"],
["inline table", "inline-table"],
["run-in flow", "run-in"]
]);
// Each property whose value is a list of shadows -> the count of lengths a
// shadow cannot go below, past which a trailing zero is already implied.
const SHADOW_PROPERTIES = new Map([
["box-shadow", 2],
["text-shadow", 2]
]);
// Each shorthand -> the keywords one of its values may drop, each with every
// spelling its own slot takes: the slot's keywords, and each function it
// accepts written `name()`. A sibling out of that set means the value fills the
// slot twice, which is a declaration the engine drops.
const SHORTHAND_INITIAL_KEYWORDS = new Map([
[
"animation",
new Map([
[
"ease",
{
spellings: new Set([
"cubic-bezier()",
"ease",
"ease-in",
"ease-in-out",
"ease-out",
"linear",
"linear()",
"step-end",
"step-start",
"steps()"
]),
classes: new Set()
}
],
[
"normal",
{
spellings: new Set([
"alternate",
"alternate-reverse",
"normal",
"reverse"
]),
classes: new Set()
}
],
[
"running",
{ spellings: new Set(["paused", "running"]), classes: new Set() }
]
])
],
[
"background",
new Map([
[
"none",
{
spellings: new Set([
"color()",
"color-mix()",
"conic-gradient()",
"cross-fade()",
"element()",
"hsl()",
"hsla()",
"hwb()",
"image()",
"image-set()",
"lab()",
"lch()",
"light-dark()",
"linear-gradient()",
"none",
"oklab()",
"oklch()",
"paint()",
"radial-gradient()",
"repeating-conic-gradient()",
"repeating-linear-gradient()",
"repeating-radial-gradient()",
"rgb()",
"rgba()",
"src()",
"type()",
"url()"
]),
classes: new Set()
}
],
[
"repeat",
{
spellings: new Set([
"no-repeat",
"repeat",
"repeat-x",
"repeat-y",
"round",
"space"
]),
classes: new Set()
}
],
[
"scroll",
{ spellings: new Set(["fixed", "local", "scroll"]), classes: new Set() }
],
[
"transparent",
{
spellings: new Set([
"color()",
"color-mix()",
"hsl()",
"hsla()",
"hwb()",
"lab()",
"lch()",
"light-dark()",
"oklab()",
"oklch()",
"rgb()",
"rgba()"
]),
classes: new Set(["color"])
}
]
])
],
[
"border",
new Map([
[
"currentcolor",
{
spellings: new Set([
"color()",
"color-mix()",
"hsl()",
"hsla()",
"hwb()",
"lab()",
"lch()",
"light-dark()",
"oklab()",
"oklch()",
"rgb()",
"rgba()"
]),
classes: new Set(["color"])
}
],
[
"medium",
{
spellings: new Set(["medium", "thick", "thin"]),
classes: new Set(["length"])
}
],
[
"none",
{
spellings: new Set([
"dashed",
"dotted",
"double",
"groove",
"hidden",
"inset",
"none",
"outset",
"ridge",
"solid"
]),
classes: new Set()
}
]
])
],
[
"border-bottom",
new Map([
[
"currentcolor",
{
spellings: new Set([
"color()",
"color-mix()",
"hsl()",
"hsla()",
"hwb()",
"lab()",
"lch()",
"light-dark()",
"oklab()",
"oklch()",
"rgb()",
"rgba()"
]),
classes: new Set(["color"])
}
],
[
"medium",
{
spellings: new Set(["medium", "thick", "thin"]),
classes: new Set(["length"])
}
],
[
"none",
{
spellings: new Set([
"dashed",
"dotted",
"double",
"groove",
"hidden",
"inset",
"none",
"outset",
"ridge",
"solid"
]),
classes: new Set()
}
]
])
],
[
"border-image",
new Map([
[
"none",
{
spellings: new Set([
"color()",
"color-mix()",
"conic-gradient()",
"cross-fade()",
"element()",
"hsl()",
"hsla()",
"hwb()",
"image()",
"image-set()",
"lab()",
"lch()",
"light-dark()",
"linear-gradient()",
"none",
"oklab()",
"oklch()",
"paint()",
"radial-gradient()",
"repeating-conic-gradient()",
"repeating-linear-gradient()",
"repeating-radial-gradient()",
"rgb()",
"rgba()",
"src()",
"type()",
"url()"
]),
classes: new Set()
}
],
[
"stretch",
{
spellings: new Set(["repeat", "round", "space", "stretch"]),
classes: new Set()
}
]
])
],
[
"border-left",
new Map([
[
"currentcolor",
{
spellings: new Set([
"color()",
"color-mix()",
"hsl()",
"hsla()",
"hwb()",
"lab()",
"lch()",
"light-dark()",
"oklab()",
"oklch()",
"rgb()",
"rgba()"
]),
classes: new Set(["color"])
}
],
[
"medium",
{
spellings: new Set(["medium", "thick", "thin"]),
classes: new Set(["length"])
}
],
[
"none",
{
spellings: new Set([
"dashed",
"dotted",
"double",
"groove",
"hidden",
"inset",
"none",
"outset",
"ridge",
"solid"
]),
classes: new Set()
}
]
])
],
[
"border-right",
new Map([
[
"currentcolor",
{
spellings: new Set([
"color()",
"color-mix()",
"hsl()",
"hsla()",
"hwb()",
"lab()",
"lch()",
"light-dark()",
"oklab()",
"oklch()",
"rgb()",
"rgba()"
]),
classes: new Set(["color"])
}
],
[
"medium",
{
spellings: new Set(["medium", "thick", "thin"]),
classes: new Set(["length"])
}
],
[
"none",
{
spellings: new Set([
"dashed",
"dotted",
"double",
"groove",
"hidden",
"inset",
"none",
"outset",
"ridge",
"solid"
]),
classes: new Set()
}
]
])
],
[
"border-top",
new Map([
[
"currentcolor",
{
spellings: new Set([
"color()",
"color-mix()",
"hsl()",
"hsla()",
"hwb()",
"lab()",
"lch()",
"light-dark()",
"oklab()",
"oklch()",
"rgb()",
"rgba()"
]),
classes: new Set(["color"])
}
],
[
"medium",
{
spellings: new Set(["medium", "thick", "thin"]),
classes: new Set(["length"])
}
],
[
"none",
{
spellings: new Set([
"dashed",
"dotted",
"double",
"groove",
"hidden",
"inset",
"none",
"outset",
"ridge",
"solid"
]),
classes: new Set()
}
]
])
],
[
"column-rule",
new Map([
[
"currentcolor",
{
spellings: new Set([
"color()",
"color-mix()",
"hsl()",
"hsla()",
"hwb()",
"lab()",
"lch()",
"light-dark()",
"oklab()",
"oklch()",
"rgb()",
"rgba()"
]),
classes: new Set(["color"])
}
],
[
"medium",
{
spellings: new Set(["medium", "thick", "thin"]),
classes: new Set(["length"])
}
],
[
"none",
{
spellings: new Set([
"dashed",
"dotted",
"double",
"groove",
"hidden",
"inset",
"none",
"outset",
"ridge",
"solid"
]),
classes: new Set()
}
]
])
],
[
"flex-flow",
new Map([
[
"nowrap",
{
spellings: new Set(["balance", "nowrap", "wrap", "wrap-reverse"]),
classes: new Set()
}
],
[
"row",
{
spellings: new Set([
"column",
"column-reverse",
"row",
"row-reverse"
]),
classes: new Set()
}
]
])
],
[
"list-style",
new Map([
[
"outside",
{ spellings: new Set(["inside", "outside"]), classes: new Set() }
]
])
],
[
"mask",
new Map([
[
"add",
{
spellings: new Set(["add", "exclude", "intersect", "subtract"]),
classes: new Set()
}
],
[
"match-source",
{
spellings: new Set(["alpha", "luminance", "match-source"]),
classes: new Set()
}
],
[
"none",
{
spellings: new Set([
"color()",
"color-mix()",
"conic-gradient()",
"cross-fade()",
"element()",
"hsl()",
"hsla()",
"hwb()",
"image()",
"image-set()",
"lab()",
"lch()",
"light-dark()",
"linear-gradient()",
"none",
"oklab()",
"oklch()",
"paint()",
"radial-gradient()",
"repeating-conic-gradient()",
"repeating-linear-gradient()",
"repeating-radial-gradient()",
"rgb()",
"rgba()",
"src()",
"type()",
"url()"
]),
classes: new Set()
}
],
[
"repeat",
{
spellings: new Set([
"no-repeat",
"repeat",
"repeat-x",
"repeat-y",
"round",
"space"
]),
classes: new Set()
}
]
])
],
[
"mask-border",
new Map([
[
"alpha",
{ spellings: new Set(["alpha", "luminance"]), classes: new Set() }
],
[
"none",
{
spellings: new Set([
"color()",
"color-mix()",
"conic-gradient()",
"cross-fade()",
"element()",
"hsl()",
"hsla()",
"hwb()",
"image()",
"image-set()",
"lab()",
"lch()",
"light-dark()",
"linear-gradient()",
"none",
"oklab()",
"oklch()",
"paint()",
"radial-gradient()",
"repeating-conic-gradient()",
"repeating-linear-gradient()",
"repeating-radial-gradient()",
"rgb()",
"rgba()",
"src()",
"type()",
"url()"
]),
classes: new Set()
}
],
[
"stretch",
{
spellings: new Set(["repeat", "round", "space", "stretch"]),
classes: new Set()
}
]
])
],
[
"outline",
new Map([
[
"medium",
{
spellings: new Set(["medium", "thick", "thin"]),
classes: new Set(["length"])
}
],
[
"none",
{
spellings: new Set([
"auto",
"dashed",
"dotted",
"double",
"groove",
"inset",
"none",
"outset",
"ridge",
"solid"
]),
classes: new Set()
}
]
])
],
[
"text-decoration",
new Map([
[
"currentcolor",
{
spellings: new Set([
"color()",
"color-mix()",
"hsl()",
"hsla()",
"hwb()",
"lab()",
"lch()",
"light-dark()",
"oklab()",
"oklch()",
"rgb()",
"rgba()"
]),
classes: new Set(["color"])
}
],
[
"none",
{
spellings: new Set([
"blink",
"grammar-error",
"line-through",
"none",
"overline",
"spelling-error",
"underline"
]),
classes: new Set()
}
],
[
"solid",
{
spellings: new Set(["dashed", "dotted", "double", "solid", "wavy"]),
classes: new Set()
}
]
])
],
[
"text-emphasis",
new Map([
[
"currentcolor",
{
spellings: new Set([
"color()",
"color-mix()",
"hsl()",
"hsla()",
"hwb()",
"lab()",
"lch()",
"light-dark()",
"oklab()",
"oklch()",
"rgb()",
"rgba()"
]),
classes: new Set(["color"])
}
],
[
"none",
{
spellings: new Set([
"circle",
"dot",
"double-circle",
"filled",
"none",
"open",
"sesame",
"triangle"
]),
classes: new Set(["string"])
}
]
])
],
[
"transition",
new Map([
[
"all",
{
spellings: new Set(["all", "none"]),
classes: new Set(["custom-ident"])
}
],
[
"ease",
{
spellings: new Set([
"cubic-bezier()",
"ease",
"ease-in",
"ease-in-out",
"ease-out",
"linear",
"linear()",
"step-end",
"step-start",
"steps()"
]),
classes: new Set()
}
],
[
"normal",
{ spellings: new Set(["allow-discrete", "normal"]), classes: new Set() }
]
])
]
]);
// Each `font-stretch` keyword -> the percentage it names, which is the same
// value in fewer bytes.
const FONT_STRETCH_PERCENTAGES = new Map([
["ultra-condensed", "50%"],
["extra-condensed", "62.5%"],
["condensed", "75%"],
["semi-condensed", "87.5%"],
["normal", "100%"],
["semi-expanded", "112.5%"],
["expanded", "125%"],
["extra-expanded", "150%"],
["ultra-expanded", "200%"]
]);
// Each `<filter-function>` with an optional argument -> the amount an omitted
// one means, which is what writing that amount already says.
const FILTER_FUNCTION_OMITTED = new Map([
["blur", "0"],
["brightness", "1"],
["contrast", "1"],
["grayscale", "1"],
["hue-rotate", "0"],
["invert", "1"],
["opacity", "1"],
["saturate", "1"],
["sepia", "1"]
]);
// The generic font families: an unquoted one of these names the generic rather
// than a family called that, so a quoted family spelled like one keeps its quotes.
const GENERIC_FONT_FAMILIES = new Set([
"cursive",
"emoji",
"fangsong",
"fantasy",
"math",
"monospace",
"sans-serif",
"serif",
"system-ui",
"ui-monospace",
"ui-rounded",
"ui-sans-serif",
"ui-serif"
]);
// The `font` size slot's keywords: `<absolute-size>` and `<relative-size>`.
const FONT_SIZE_KEYWORDS = new Set([
"large",
"larger",
"medium",
"small",
"smaller",
"x-large",
"x-small",
"xx-large",
"xx-small",
"xxx-large"
]);
// The `<easing-function>` spellings that are a keyword rather than a function.
const EASING_KEYWORDS = new Set([
"ease",
"ease-in",
"ease-in-out",
"ease-out",
"linear",
"step-end",
"step-start"
]);
// What `transition-behavior` accepts, the slot of a `transition` that is
// neither a time, an easing nor the property name.
const TRANSITION_BEHAVIORS = new Set(["allow-discrete", "normal"]);
// The linear gradients, whose flow a `<side-or-corner>` or angle states.
const LINEAR_GRADIENTS = new Set([
"linear-gradient",
"repeating-linear-gradient"
]);
// A size whose omitted second value is `auto`, not the first repeated.
const AUTO_SECOND_VALUE_PROPERTIES = new Set(["background-size", "mask-size"]);
// The direction each unprefixed linear gradient already starts from. A
// `-webkit-` one measures its angle the other way, so it keeps what it says.
const DEFAULT_GRADIENT_DIRECTIONS = new Set(["to bottom", "180deg", "0.5turn"]);
// A name CSS matches ASCII case-insensitively but spells with a capital ->
// that spelling, so lowercasing a name normalizes its case without printing
// `translatey` or `1q` for what everything else writes `translateY` and `1Q`.
const CANONICAL_NAMES = new Map([
["hz", "Hz"],
["khz", "kHz"],
["q", "Q"],
["rotatex", "rotateX"],
["rotatey", "rotateY"],
["rotatez", "rotateZ"],
["scalex", "scaleX"],
["scaley", "scaleY"],
["scalez", "scaleZ"],
["skewx", "skewX"],
["skewy", "skewY"],
["translatex", "translateX"],
["translatey", "translateY"],
["translatez", "translateZ"]
]);
// A transform along x only -> the pair spelling whose second component is the
// 0 the one-axis call already means.
const X_AXIS_TRANSFORMS = new Map([
["translatex", "translate"],
["skewx", "skew"]
]);
// Each gradient function -> the positions its last color stop already means, so
// writing one of them there says nothing (CSS Images 3 §3.4.3).
const GRADIENT_LAST_POSITIONS = new Map([
["conic-gradient", new Set(["100%", "360deg", "1turn"])],
["linear-gradient", new Set(["100%"])],
["radial-gradient", new Set(["100%"])],
["repeating-conic-gradient", new Set(["100%", "360deg", "1turn"])],
["repeating-linear-gradient", new Set(["100%"])],
["repeating-radial-gradient", new Set(["100%"])]
]);
// The properties whose value is a position, where each edge keyword names the
// percentage that axis resolves to.
const POSITION_PROPERTIES = new Set([
"-webkit-mask-position",
"background-position",
"mask-position",
"object-position",
"offset-anchor",
"offset-position",
"perspective-origin",
"scroll-snap-coordinate",
"scroll-snap-destination",
"transform-origin"
]);
// Each keyword one axis of a `<position>` accepts -> the percentage it resolves
// to. A keyword both maps carry (`center`) names whichever axis is still free,
// and every free axis is `50%` anyway.
const POSITION_X_KEYWORDS = new Map([
["center", "50%"],
["left", "0%"],
["right", "100%"]
]);
const POSITION_Y_KEYWORDS = new Map([
["bottom", "100%"],
["center", "50%"],
["top", "0%"]
]);
// The keywords one `<repeat-style>` axis can be: a pair only collapses where
// both halves are one of these.
const REPEAT_STYLE_KEYWORDS = new Set([
"no-repeat",
"repeat",
"round",
"space"
]);
// The properties whose value is a `<repeat-style>`, where one value already
// says what two equal ones do.
const REPEAT_STYLE_PROPERTIES = new Set([
"-webkit-mask",
"-webkit-mask-repeat",
"background",
"background-repeat",
"mask",
"mask-repeat"
]);
// Each property whose initial value is a keyword shorter than `initial` -> that
// keyword, which is the same declaration written in fewer bytes.
const INITIAL_VALUE_KEYWORDS = new Map([
["-moz-binding", "none"],
["-moz-border-bottom-colors", "none"],
["-moz-border-left-colors", "none"],
["-moz-border-right-colors", "none"],
["-moz-border-top-colors", "none"],
["-moz-context-properties", "none"],
["-moz-orient", "inline"],
["-moz-text-blink", "none"],
["-moz-user-focus", "none"],
["-moz-user-input", "auto"],
["-moz-window-dragging", "drag"],
["-ms-accelerator", "false"],
["-ms-block-progression", "tb"],
["-ms-content-zoom-chaining", "none"],
["-ms-content-zoom-snap-type", "none"],
["-ms-flow-from", "none"],
["-ms-flow-into", "none"],
["-ms-grid-columns", "none"],
["-ms-grid-rows", "none"],
["-ms-high-contrast-adjust", "auto"],
["-ms-hyphenate-limit-chars", "auto"],
["-ms-ime-align", "auto"],
["-ms-overflow-style", "auto"],
["-ms-scroll-limit-x-max", "auto"],
["-ms-scroll-limit-y-max", "auto"],
["-ms-scroll-rails", "railed"],
["-ms-scroll-snap-type", "none"],
["-ms-scroll-translation", "none"],
["-ms-text-autospace", "none"],
["-ms-user-select", "text"],
["-ms-wrap-flow", "auto"],
["-ms-wrap-through", "wrap"],
["-webkit-border-after-style", "none"],
["-webkit-border-before-style", "none"],
["-webkit-border-end-style", "none"],
["-webkit-border-start-style", "none"],
["-webkit-line-clamp", "none"],
["-webkit-mask-attachment", "scroll"],
["-webkit-mask-clip", "border"],
["-webkit-mask-image", "none"],
["-webkit-mask-repeat", "repeat"],
["-webkit-mask-repeat-x", "repeat"],
["-webkit-mask-repeat-y", "repeat"],
["-webkit-overflow-scrolling", "auto"],
["-webkit-user-select", "auto"],
["accent-color", "auto"],
["align-content", "normal"],
["align-items", "normal"],
["align-self", "auto"],
["align-tracks", "normal"],
["anchor-name", "none"],
["anchor-scope", "none"],
["animation-direction", "normal"],
["animation-fill-mode", "none"],
["animation-name", "none"],
["animation-range-end", "normal"],
["animation-range-start", "normal"],
["animation-timeline", "auto"],
["animation-timing-function", "ease"],
["animation-trigger", "none"],
["appearance", "none"],
["aspect-ratio", "auto"],
["backdrop-filter", "none"],
["background-attachment", "scroll"],
["background-blend-mode", "normal"],
["background-image", "none"],
["background-repeat", "repeat"],
["baseline-source", "auto"],
["block-size", "auto"],
["border-block-end-style", "none"],
["border-block-start-style", "none"],
["border-bottom-style", "none"],
["border-image-source", "none"],
["border-inline-end-style", "none"],
["border-inline-start-style", "none"],
["border-left-style", "none"],
["border-right-style", "none"],
["border-shape", "none"],
["border-top-style", "none"],
["bottom", "auto"],
["box-decoration-break", "slice"],
["box-direction", "normal"],
["box-lines", "single"],
["box-pack", "start"],
["box-shadow", "none"],
["break-after", "auto"],
["break-before", "auto"],
["break-inside", "auto"],
["caption-side", "top"],
["caret-animation", "auto"],
["caret-color", "auto"],
["caret-shape", "auto"],
["clear", "none"],
["clip", "auto"],
["clip-path", "none"],
["color-scheme", "normal"],
["column-count", "auto"],
["column-gap", "normal"],
["column-height", "auto"],
["column-rule-style", "none"],
["column-span", "none"],
["column-width", "auto"],
["column-wrap", "auto"],
["contain", "none"],
["contain-intrinsic-block-size", "none"],
["contain-intrinsic-height", "none"],
["contain-intrinsic-inline-size", "none"],
["contain-intrinsic-width", "none"],
["container-name", "none"],
["container-type", "normal"],
["content", "normal"],
["corner-bottom-left-shape", "round"],
["corner-bottom-right-shape", "round"],
["corner-end-end-shape", "round"],
["corner-end-start-shape", "round"],
["corner-start-end-shape", "round"],
["corner-start-start-shape", "round"],
["corner-top-left-shape", "round"],
["corner-top-right-shape", "round"],
["counter-increment", "none"],
["counter-reset", "none"],
["counter-set", "none"],
["cursor", "auto"],
["d", "none"],
["direction", "ltr"],
["display", "inline"],
["dominant-baseline", "auto"],
["empty-cells", "show"],
["field-sizing", "fixed"],
["filter", "none"],
["flex-basis", "auto"],
["flex-direction", "row"],
["flex-wrap", "nowrap"],
["float", "none"],
["font-feature-settings", "normal"],
["font-kerning", "auto"],
["font-language-override", "normal"],
["font-optical-sizing", "auto"],
["font-palette", "normal"],
["font-size-adjust", "none"],
["font-smooth", "auto"],
["font-stretch", "normal"],
["font-style", "normal"],
["font-synthesis-position", "none"],
["font-synthesis-small-caps", "auto"],
["font-synthesis-style", "auto"],
["font-synthesis-weight", "auto"],
["font-variant", "normal"],
["font-variant-alternates", "normal"],
["font-variant-caps", "normal"],
["font-variant-east-asian", "normal"],
["font-variant-emoji", "normal"],
["font-variant-ligatures", "normal"],
["font-variant-numeric", "normal"],
["font-variant-position", "normal"],
["font-variation-settings", "normal"],
["font-weight", "normal"],
["font-width", "normal"],
["forced-color-adjust", "auto"],
["frame-sizing", "auto"],
["grid-auto-columns", "auto"],
["grid-auto-flow", "row"],
["grid-auto-rows", "auto"],
["grid-column-end", "auto"],
["grid-column-start", "auto"],
["grid-row-end", "auto"],
["grid-row-start", "auto"],
["grid-template-areas", "none"],
["grid-template-columns", "none"],
["grid-template-rows", "none"],
["hanging-punctuation", "none"],
["height", "auto"],
["hyphenate-character", "auto"],
["hyphenate-limit-chars", "auto"],
["hyphens", "manual"],
["image-rendering", "auto"],
["ime-mode", "auto"],
["initial-letter", "normal"],
["initial-letter-align", "auto"],
["inline-size", "auto"],
["inset-block-end", "auto"],
["inset-block-start", "auto"],
["inset-inline-end", "auto"],
["inset-inline-start", "auto"],
["interactivity", "auto"],
["interest-delay-end", "normal"],
["interest-delay-start", "normal"],
["isolation", "auto"],
["justify-content", "normal"],
["justify-items", "legacy"],
["justify-self", "auto"],
["justify-tracks", "normal"],
["left", "auto"],
["letter-spacing", "normal"],
["line-break", "auto"],
["line-clamp", "none"],
["line-height", "normal"],
["link-parameters", "none"],
["list-style-image", "none"],
["margin-trim", "none"],
["marker-end", "none"],
["marker-mid", "none"],
["marker-start", "none"],
["mask-border-mode", "alpha"],
["mask-border-source", "none"],
["mask-border-width", "auto"],
["mask-composite", "add"],
["mask-image", "none"],
["mask-repeat", "repeat"],
["mask-size", "auto"],
["masonry-auto-flow", "pack"],
["math-shift", "normal"],
["math-style", "normal"],
["max-block-size", "none"],
["max-height", "none"],
["max-inline-size", "none"],
["max-lines", "none"],
["max-width", "none"],
["min-height", "auto"],
["min-width", "auto"],
["mix-blend-mode", "normal"],
["object-fit", "fill"],
["object-view-box", "none"],
["offset-anchor", "auto"],
["offset-path", "none"],
["offset-position", "normal"],
["offset-rotate", "auto"],
["outline-color", "auto"],
["outline-style", "none"],
["overflow-anchor", "auto"],
["overflow-block", "auto"],
["overflow-inline", "auto"],
["overflow-wrap", "normal"],
["overlay", "none"],
["overscroll-behavior", "auto"],
["overscroll-behavior-block", "auto"],
["overscroll-behavior-inline", "auto"],
["overscroll-behavior-x", "auto"],
["overscroll-behavior-y", "auto"],
["page", "auto"],
["page-break-after", "auto"],
["page-break-before", "auto"],
["page-break-inside", "auto"],
["paint-order", "normal"],
["path-length", "none"],
["perspective", "none"],
["pointer-events", "auto"],
["position", "static"],
["position-anchor", "normal"],
["position-area", "none"],
["position-try-fallbacks", "none"],
["position-try-order", "normal"],
["reading-flow", "normal"],
["resize", "none"],
["right", "auto"],
["rotate", "none"],
["row-gap", "normal"],
["ruby-overhang", "auto"],
["rx", "auto"],
["ry", "auto"],
["scale", "none"],
["scroll-behavior", "auto"],
["scroll-initial-target", "none"],
["scroll-marker-group", "none"],
["scroll-padding-block-end", "auto"],
["scroll-padding-block-start", "auto"],
["scroll-padding-bottom", "auto"],
["scroll-padding-inline-end", "auto"],
["scroll-padding-inline-start", "auto"],
["scroll-padding-left", "auto"],
["scroll-padding-right", "auto"],
["scroll-padding-top", "auto"],
["scroll-snap-align", "none"],
["scroll-snap-coordinate", "none"],
["scroll-snap-points-x", "none"],
["scroll-snap-points-y", "none"],
["scroll-snap-stop", "normal"],
["scroll-snap-type", "none"],
["scroll-snap-type-x", "none"],
["scroll-snap-type-y", "none"],
["scroll-target-group", "none"],
["scroll-timeline-axis", "block"],
["scroll-timeline-name", "none"],
["scrollbar-color", "auto"],
["scrollbar-gutter", "auto"],
["scrollbar-width", "auto"],
["shape-outside", "none"],
["shape-rendering", "auto"],
["stroke-dasharray", "none"],
["stroke-linecap", "butt"],
["stroke-linejoin", "miter"],
["table-layout", "auto"],
["text-align", "start"],
["text-align-last", "auto"],
["text-anchor", "start"],
["text-autospace", "normal"],
["text-box", "normal"],
["text-box-edge", "auto"],
["text-box-trim", "none"],
["text-combine-upright", "none"],
["text-decoration-line", "none"],
["text-decoration-skip-ink", "auto"],
["text-decoration-style", "solid"],
["text-decoration-thickness", "auto"],
["text-emphasis-position", "auto"],
["text-emphasis-style", "none"],
["text-fit", "none"],
["text-justify", "auto"],
["text-orientation", "mixed"],
["text-overflow", "clip"],
["text-rendering", "auto"],
["text-shadow", "none"],
["text-spacing-trim", "normal"],
["text-transform", "none"],
["text-underline-offset", "auto"],
["text-underline-position", "auto"],
["text-wrap", "wrap"],
["text-wrap-mode", "wrap"],
["text-wrap-style", "auto"],
["timeline-scope", "none"],
["timeline-trigger-activation-range-end", "normal"],
["timeline-trigger-activation-range-start", "normal"],
["timeline-trigger-active-range-end", "auto"],
["timeline-trigger-active-range-start", "auto"],
["timeline-trigger-name", "none"],
["timeline-trigger-source", "auto"],
["top", "auto"],
["touch-action", "auto"],
["transform", "none"],
["transform-style", "flat"],
["transition-behavior", "normal"],
["transition-property", "all"],
["transition-timing-function", "ease"],
["translate", "none"],
["trigger-scope", "none"],
["unicode-bidi", "normal"],
["user-select", "auto"],
["vector-effect", "none"],
["view-timeline-axis", "block"],
["view-timeline-inset", "auto"],
["view-timeline-name", "none"],
["view-transition-class", "none"],
["view-transition-name", "none"],
["view-transition-scope", "none"],
["white-space", "normal"],
["width", "auto"],
["will-change", "auto"],
["word-break", "normal"],
["word-spacing", "normal"],
["word-wrap", "normal"],
["z-index", "auto"]
]);
// Each named color a shorter spelling beats -> that spelling, so a name written
// where a color is unambiguous prints as the shortest text for the same value.
const COLOR_NAME_TO_SHORTEST = new Map([
["aliceblue", "#f0f8ff"],
["antiquewhite", "#faebd7"],
["aquamarine", "#7fffd4"],
["black", "#000"],
["blanchedalmond", "#ffebcd"],
["blueviolet", "#8a2be2"],
["burlywood", "#deb887"],
["cadetblue", "#5f9ea0"],
["chartreuse", "#7fff00"],
["chocolate", "#d2691e"],
["cornflowerblue", "#6495ed"],
["cornsilk", "#fff8dc"],
["darkblue", "#00008b"],
["darkcyan", "#008b8b"],
["darkgoldenrod", "#b8860b"],
["darkgray", "#a9a9a9"],
["darkgreen", "#006400"],
["darkgrey", "#a9a9a9"],
["darkkhaki", "#bdb76b"],
["darkmagenta", "#8b008b"],
["darkolivegreen", "#556b2f"],
["darkorange", "#ff8c00"],
["darkorchid", "#9932cc"],
["darksalmon", "#e9967a"],
["darkseagreen", "#8fbc8f"],
["darkslateblue", "#483d8b"],
["darkslategray", "#2f4f4f"],
["darkslategrey", "#2f4f4f"],
["darkturquoise", "#00ced1"],
["darkviolet", "#9400d3"],
["deeppink", "#ff1493"],
["deepskyblue", "#00bfff"],
["dodgerblue", "#1e90ff"],
["firebrick", "#b22222"],
["floralwhite", "#fffaf0"],
["forestgreen", "#228b22"],
["fuchsia", "#f0f"],
["gainsboro", "#dcdcdc"],
["ghostwhite", "#f8f8ff"],
["goldenrod", "#daa520"],
["greenyellow", "#adff2f"],
["honeydew", "#f0fff0"],
["indianred", "#cd5c5c"],
["lavender", "#e6e6fa"],
["lavenderblush", "#fff0f5"],
["lawngreen", "#7cfc00"],
["lemonchiffon", "#fffacd"],
["lightblue", "#add8e6"],
["lightcoral", "#f08080"],
["lightcyan", "#e0ffff"],
["lightgoldenrodyellow", "#fafad2"],
["lightgray", "#d3d3d3"],
["lightgreen", "#90ee90"],
["lightgrey", "#d3d3d3"],
["lightpink", "#ffb6c1"],
["lightsalmon", "#ffa07a"],
["lightseagreen", "#20b2aa"],
["lightskyblue", "#87cefa"],
["lightslategray", "#789"],
["lightslategrey", "#789"],
["lightsteelblue", "#b0c4de"],
["lightyellow", "#ffffe0"],
["limegreen", "#32cd32"],
["magenta", "#f0f"],
["mediumaquamarine", "#66cdaa"],
["mediumblue", "#0000cd"],
["mediumorchid", "#ba55d3"],
["mediumpurple", "#9370db"],
["mediumseagreen", "#3cb371"],
["mediumslateblue", "#7b68ee"],
["mediumspringgreen", "#00fa9a"],
["mediumturquoise", "#48d1cc"],
["mediumvioletred", "#c71585"],
["midnightblue", "#191970"],
["mintcream", "#f5fffa"],
["mistyrose", "#ffe4e1"],
["moccasin", "#ffe4b5"],
["navajowhite", "#ffdead"],
["olivedrab", "#6b8e23"],
["orangered", "#ff4500"],
["palegoldenrod", "#eee8aa"],
["palegreen", "#98fb98"],
["paleturquoise", "#afeeee"],
["palevioletred", "#db7093"],
["papayawhip", "#ffefd5"],
["peachpuff", "#ffdab9"],
["powderblue", "#b0e0e6"],
["rebeccapurple", "#639"],
["rosybrown", "#bc8f8f"],
["royalblue", "#4169e1"],
["saddlebrown", "#8b4513"],
["sandybrown", "#f4a460"],
["seagreen", "#2e8b57"],
["seashell", "#fff5ee"],
["slateblue", "#6a5acd"],
["slategray", "#708090"],
["slategrey", "#708090"],
["springgreen", "#00ff7f"],
["steelblue", "#4682b4"],
["turquoise", "#40e0d0"],
["white", "#fff"],
["whitesmoke", "#f5f5f5"],
["yellow", "#ff0"],
["yellowgreen", "#9acd32"]
]);
// The functions whose argument is a selector, so a `>` / `+` / `~` inside one
// is a combinator and needs no whitespace around it.
const SELECTOR_FUNCTIONS = new Set([
"cue",
"element",
"has",
"host",
"host-context",
"is",
"not",
"nth-child",
"nth-last-child",
"selector",
"slotted",
"where"
]);
// The functions every argument of which is an angle, so a zero one needs no
// unit wherever it stands.
const ZERO_ANGLE_FUNCTIONS = new Set([
"hue-rotate",
"rotate",
"rotatex",
"rotatey",
"rotatez",
"skew",
"skewx",
"skewy"
]);
// CSS Values 4's math functions: everything inside one is a math expression, so
// `*` and `/` there are operators, and the whitespace around them carries nothing.
const MATH_FUNCTIONS = new Set([
"abs",
"acos",
"asin",
"atan",
"atan2",
"calc",
"calc-size",
"clamp",
"cos",
"exp",
"hypot",
"log",
"max",
"min",
"mod",
"pow",
"rem",
"round",
"sign",
"sin",
"sqrt",
"tan"
]);
// How many `<calc-sum>` arguments each of them takes, off its own grammar. A
// function whose arguments are not all expressions (`round()` leads with a
// strategy, `calc-size()` with a basis) is absent, and absence is what the
// folding reads as "leave this one alone".
/** @type {Map<string, [number, number]>} */
const MATH_FUNCTION_ARITY = new Map([
["abs", [1, 1]],
["acos", [1, 1]],
["asin", [1, 1]],
["atan", [1, 1]],
["atan2", [2, 2]],
["calc", [1, 1]],
["clamp", [3, 3]],
["cos", [1, 1]],
["exp", [1, 1]],
["hypot", [1, Infinity]],
["log", [1, 2]],
["max", [1, Infinity]],
["min", [1, Infinity]],
["mod", [2, 2]],
["pow", [2, 2]],
["rem", [2, 2]],
["round", [2, 2]],
["sign", [1, 1]],
["sin", [1, 1]],
["sqrt", [1, 1]],
["tan", [1, 1]]
]);
// The optional keyword a math function may lead with, for the ones whose
// grammar offers a choice of them (`round( <rounding-strategy>?, … )`). Read
// off that production, so a strategy joining it needs no edit here.
/** @type {Map<string, string[]>} */
const MATH_FUNCTION_KEYWORDS = new Map([
["round", ["down", "nearest", "to-zero", "up"]]
]);
// Where a function the fold cannot read as a whole still takes a `<calc-sum>`,
// so that argument reduces on its own. Keyed by name to the argument positions.
/** @type {Map<string, number[]>} */
const MATH_FUNCTION_SUM_ARGUMENTS = new Map([["calc-size", [1]]]);
// A CSS-wide keyword is only valid as the whole value, so a box repeating one is
// invalid and already discarded — collapsing it would switch the declaration on.
const CSS_WIDE_KEYWORDS = new Set([
"inherit",
"initial",
"revert",
"revert-layer",
"unset"
]);
// `<easing-function>` argument lists that are exactly a shorter keyword, keyed
// by the arguments as `Number` prints them.
const CUBIC_BEZIER_KEYWORDS = new Map([
["0.25,0.1,0.25,1", "ease"],
["0,0,1,1", "linear"],
["0.42,0,1,1", "ease-in"],
["0,0,0.58,1", "ease-out"],
["0.42,0,0.58,1", "ease-in-out"]
]);
// The two `flex` values CSS Flexbox 7.1.1 gives a keyword spelling.
const FLEX_KEYWORDS = new Map([
["0 0 auto", "none"],
["1 1 auto", "auto"]
]);
// The `font-weight` keywords CSS Fonts 4 §2.2 defines as a number, which is what
// `getComputedStyle().fontWeight` reports either way.
const FONT_WEIGHT_NUMBERS = new Map([
["normal", "400"],
["bold", "700"]
]);
// Selectors 4 §3.3: the pseudo-elements engines must also accept with one colon,
// so their second colon carries nothing.
const LEGACY_PSEUDO_ELEMENTS = new Set([
"before",
"after",
"first-line",
"first-letter"
]);
// What may follow the `*` a compound selector implies: another simple selector
// in the same compound. A separator between them would be a descendant
// combinator instead, and `|` makes the `*` a namespace's, not a redundant one.
const COMPOUND_CONTINUATIONS = new Set([":", ".", "#", "["]);
// The pseudo-classes selecting a featureless element, which matches no type or
// universal selector — so an implied `*` before one is what makes the selector
// match nothing, and dropping it would bring the rule to life.
const FEATURELESS_PSEUDO_CLASSES = new Set(["host", "host-context"]);
// The properties whose zero length keeps its unit: those whose own grammar
// offers a bare number beside the length, so the unit is what picks the
// reading, and the two an engine reads its own way.
const ZERO_UNIT_KEEPING_PROPERTIES = new Set([
"border-image",
"border-image-outset",
"border-image-width",
"columns",
"flex",
"flex-basis",
"font",
"line-height",
"mask-border",
"mask-border-outset",
"mask-border-width",
"overflow-clip-margin",
"stroke-dasharray",
"stroke-dashoffset",
"stroke-width",
"tab-size"
]);
// The properties an engine takes no `calc()` in, so one stays as written
// rather than folding to the value it equals.
const CALC_REJECTING_PROPERTIES = new Set(["overflow-clip-margin"]);
// The range a `calc()` is clamped to where the literal outside it is invalid,
// keyed by property: `[unit, min, max]`.
/** @type {Map<string, [string, number, number]>} */
const CLAMPED_VALUE_RANGES = new Map([["font-style", ["deg", -90, 90]]]);
// At-rules whose empty block is inert, so dropping it changes nothing.
const DROPPABLE_WHEN_EMPTY_AT_RULES = new Set([
"media",
"supports",
"container"
]);
// At-rules whose block holds rules and whose prelude states a condition, so two
// adjacent blocks with the same prelude are the one block they resolve to.
const MERGEABLE_AT_RULES = new Set([
"container",
"document",
"layer",
"media",
"scope",
"starting-style",
"supports"
]);
// The math functions whose result steps with their arguments, so a value inside
// one keeps the unit and the digits it was written with.
const STEPPED_FUNCTIONS = new Set(["mod", "rem", "round"]);
// The units fixed against each other (CSS Values 4 §6.2, §8), as
// `unit -> [group, how many of the group's base unit one is]`. Two units in the
// same group convert into each other exactly when the ratio is binary-exact.
/** @type {Map<string, [string, number]>} */
const ABSOLUTE_UNIT_SCALE = new Map([
["px", ["length", 381]],
["pc", ["length", 6096]],
["pt", ["length", 508]],
["in", ["length", 36576]],
["cm", ["length", 14400]],
["mm", ["length", 1440]],
["q", ["length", 360]],
["ms", ["time", 1]],
["s", ["time", 1000]]
]);
// Each convertible group's reference unit, as `group -> [unit, scale]`. A sum
// counted in the group's base unit divides by the scale to get back to a unit
// that can be written down.
/** @type {Map<string, [string, number]>} */
const UNIT_GROUP_BASE = new Map([
["length", ["px", 381]],
["time", ["ms", 1]]
]);
// The units a conversion may emit. Every one is CSS 2.1's, so rewriting into it
// cannot outrun what an engine reading the stylesheet already parses.
const UNIT_CONVERSION_TARGETS = new Set([
"px",
"pc",
"pt",
"in",
"cm",
"mm",
"ms",
"s"
]);
// How each predefined color space is read back to sRGB: the matrix taking its
// linear-light components to linear-light sRGB, and the function that reads one
// stored component back to linear light. Both derived from the primaries,
// white point and transfer function CSS Color 4 §10 states.
/**
* A component already stored linearly.
* @param {number} c the stored component
* @returns {number} the same component
*/
const linearTransfer = (c) => c;
/**
* The sRGB transfer function, which Display P3 shares.
* @param {number} c the stored component
* @returns {number} the linear-light component
*/
const srgbTransfer = (c) => {
const abs = Math.abs(c);
const sign = c < 0 ? -1 : 1;
return abs <= 0.04045 ? c / 12.92 : sign * ((abs + 0.055) / 1.055) ** 2.4;
};
/**
* Adobe RGB (1998)'s pure gamma of 563/256.
* @param {number} c the stored component
* @returns {number} the linear-light component
*/
const a98Transfer = (c) => {
const sign = c < 0 ? -1 : 1;
return sign * Math.abs(c) ** (563 / 256);
};
/**
* ProPhoto RGB's gamma of 1.8, with the linear segment below 16/512.
* @param {number} c the stored component
* @returns {number} the linear-light component
*/
const prophotoTransfer = (c) => {
const abs = Math.abs(c);
const sign = c < 0 ? -1 : 1;
return abs <= 16 / 512 ? c / 16 : sign * abs ** 1.8;
};
/**
* Rec. 2020's transfer function, with the constants ITU-R BT.2020 states.
* @param {number} c the stored component
* @returns {number} the linear-light component
*/
const rec2020Transfer = (c) => {
const alpha = 1.09929682680944;
const beta = 0.018053968510807;
const abs = Math.abs(c);
const sign = c < 0 ? -1 : 1;
return abs < beta * 4.5
? c / 4.5
: sign * ((abs + alpha - 1) / alpha) ** (1 / 0.45);
};
// What a color read in one space passes through on its way to a byte: nothing at
// all, the sRGB transfer, or a matrix as well. `lib/css/syntax.js` reads how far
// its answer can sit from an engine's from this.
const ENCODED_ALREADY = 0;
const THROUGH_TRANSFER = 1;
const THROUGH_MATRIX = 2;
const ENGINE_TRANSFER_DIFFERS = 3;
/** @type {Map<string, { toSrgb: number[], transfer: (c: number) => number, conversion: number }>} */
const PREDEFINED_COLOR_SPACES = new Map([
[
"srgb",
{
toSrgb: [1, 0, 0, 0, 1, 0, 0, 0, 1],
transfer: srgbTransfer,
conversion: 0
}
],
[
"srgb-linear",
{
toSrgb: [1, 0, 0, 0, 1, 0, 0, 0, 1],
transfer: linearTransfer,
conversion: 1
}
],
[
"display-p3",
{
toSrgb: [
1.2249401762805596, -0.22494017628055984, 0, -0.04205695470968812,
1.042056954709688, -2.0816681711721685e-17, -0.019637554590334425,
-0.0786360455506318, 1.0982736001409665
],
transfer: srgbTransfer,
conversion: 2
}
],
[
"a98-rgb",
{
toSrgb: [
1.3983557439607786, -0.39835574396077855, 5.551115123125783e-17,
-1.4072944198861848e-16, 1, -2.0816681711721685e-17,
1.734723475976807e-17, -0.04292898929447317, 1.042928989294473
],
transfer: a98Transfer,
conversion: 3
}
],
[
"prophoto-rgb",
{
toSrgb: [
2.034380836302867, -0.7276360137172471, -0.3067448320015419,
-0.228825697964331, 1.2317426727787788, -0.0029169277200310345,
-0.008558858080647581, -0.15326675125999153, 1.161825549670178
],
transfer: prophotoTransfer,
conversion: 3
}
],
[
"rec2020",
{
toSrgb: [
1.6604910021084347, -0.5876411387885495, -0.07284986331988486,
-0.12455047452159063, 1.1328998971259596, -0.008349422604369508,
-0.018150763354905206, -0.10057889800800737, 1.1187296613629127
],
transfer: rec2020Transfer,
conversion: 2
}
],
[
"xyz",
{
toSrgb: [
3.2409699419045226, -1.537383177570094, -0.4986107602930034,
-0.9692436362808796, 1.8759675015077202, 0.04155505740717559,
0.05563007969699366, -0.20397695888897652, 1.0569715142428786
],
transfer: linearTransfer,
conversion: 2
}
],
[
"xyz-d65",
{
toSrgb: [
3.2409699419045226, -1.537383177570094, -0.4986107602930034,
-0.9692436362808796, 1.8759675015077202, 0.04155505740717559,
0.05563007969699366, -0.20397695888897652, 1.0569715142428786
],
transfer: linearTransfer,
conversion: 2
}
],
[
"xyz-d50",
{
toSrgb: [
3.1341359569958707, -1.6173863321612538, -0.4906619460083532,
-0.978795502912089, 1.9162545672595237, 0.03344273116131948,
0.07195537988411684, -0.22897682641583222, 1.4053860583241256
],
transfer: linearTransfer,
conversion: 2
}
]
]);
// Linear-light sRGB -> linear-light Display P3, the inverse of the matrix above
// it: a color outside sRGB keeps its gamut in a `color(display-p3 …)` fallback
// wherever the target reads one.
const LINEAR_SRGB_TO_P3 = [
0.8224619687143625, 0.17753803128563775, 3.3650564745655794e-18,
0.0331941988509616, 0.9668058011490385, 1.8324840583423322e-17,
0.017082630721120023, 0.07239744066396339, 0.9105199286149164
];
// The interpolation spaces a `color-mix()` or a relative color is read in, each
// as the pair taking linear-light sRGB to its components and back, and which
// component is an angle (`-1` for none). Every one derived from the primaries,
// matrices and definitions the generator states.
/**
* A 3x3 matrix, laid out row by row, times a column.
* @param {number[]} m the matrix
* @param {number[]} c the column
* @returns {number[]} the product
*/
const applyModel = (m, c) =>
[0, 3, 6].map((row) => m[row] * c[0] + m[row + 1] * c[1] + m[row + 2] * c[2]);
/**
* @param {number} c a linear component
* @returns {number} the same component
*/
const linearEncode = (c) => c;
/**
* @param {number} c a linear component
* @returns {number} the sRGB-encoded component
*/
const srgbEncode = (c) => {
const abs = Math.abs(c);
const sign = c < 0 ? -1 : 1;
return abs > 0.0031308
? sign * (1.055 * abs ** (1 / 2.4) - 0.055)
: 12.92 * c;
};
/**
* @param {number} c a linear component
* @returns {number} the Adobe RGB (1998) component
*/
const a98Encode = (c) => {
const sign = c < 0 ? -1 : 1;
return sign * Math.abs(c) ** (256 / 563);
};
/**
* @param {number} c a linear component
* @returns {number} the ProPhoto RGB component
*/
const prophotoEncode = (c) => {
const abs = Math.abs(c);
const sign = c < 0 ? -1 : 1;
return abs >= 1 / 512 ? sign * abs ** (1 / 1.8) : 16 * c;
};
/**
* @param {number} c a linear component
* @returns {number} the Rec. 2020 component
*/
const rec2020Encode = (c) => {
const alpha = 1.09929682680944;
const beta = 0.018053968510807;
const abs = Math.abs(c);
const sign = c < 0 ? -1 : 1;
return abs > beta ? sign * (alpha * abs ** 0.45 - (alpha - 1)) : 4.5 * c;
};
// The D50 white point Lab is defined against (CSS Color 4 §12), as XYZ.
const LAB_WHITE = [0.3457 / 0.3585, 1, (1 - 0.3457 - 0.3585) / 0.3585];
const LAB_EPSILON = 216 / 24389;
const LAB_KAPPA = 24389 / 27;
/**
* Linear-light sRGB -> CIE Lab, through XYZ at Lab's own white point.
* @param {number[]} c the linear-light components
* @returns {number[]} `[L, a, b]`, L in 0..100
*/
const toLab = (c) => {
const xyz = toXyzD50(c);
const f = xyz.map((value, at) => {
const t = value / LAB_WHITE[at];
return t > LAB_EPSILON ? Math.cbrt(t) : (LAB_KAPPA * t + 16) / 116;
});
return [116 * f[1] - 16, 500 * (f[0] - f[1]), 200 * (f[1] - f[2])];
};
/**
* CIE Lab -> linear-light sRGB.
* @param {number[]} c `[L, a, b]`
* @returns {number[]} the linear-light components
*/
const fromLab = (c) => {
const fy = (c[0] + 16) / 116;
const fx = c[1] / 500 + fy;
const fz = fy - c[2] / 200;
return fromXyzD50([
(fx ** 3 > LAB_EPSILON ? fx ** 3 : (116 * fx - 16) / LAB_KAPPA) *
LAB_WHITE[0],
(c[0] > LAB_KAPPA * LAB_EPSILON ? fy ** 3 : c[0] / LAB_KAPPA) *
LAB_WHITE[1],
(fz ** 3 > LAB_EPSILON ? fz ** 3 : (116 * fz - 16) / LAB_KAPPA) *
LAB_WHITE[2]
]);
};
/**
* Linear-light sRGB -> Oklab.
* @param {number[]} c the linear-light components
* @returns {number[]} `[L, a, b]`, L in 0..1
*/
const toOklab = (c) => applyModel(OKLAB_M, applyModel(LMS_M, c).map(Math.cbrt));
/**
* Oklab -> linear-light sRGB.
* @param {number[]} c `[L, a, b]`
* @returns {number[]} the linear-light components
*/
const fromOklab = (c) =>
applyModel(
LMS_I,
applyModel(OKLAB_I, c).map((value) => value ** 3)
);
/**
* A rectangular pair as chroma and hue, and back — the one relation `lch` has
* to `lab` and `oklch` to `oklab`.
* @param {number[]} c `[L, a, b]`
* @returns {number[]} `[L, C, H]`, H in degrees
*/
const toPolar = (c) => {
const chroma = Math.hypot(c[1], c[2]);
let hue = (Math.atan2(c[2], c[1]) * 180) / Math.PI;
if (hue < 0) hue += 360;
return [c[0], chroma, chroma === 0 ? 0 : hue];
};
/**
* @param {number[]} c `[L, C, H]`, H in degrees
* @returns {number[]} `[L, a, b]`
*/
const fromPolar = (c) => {
const hue = (c[2] * Math.PI) / 180;
return [c[0], c[1] * Math.cos(hue), c[1] * Math.sin(hue)];
};
/**
* @param {number[]} c the linear-light components
* @returns {number[]} `[L, C, H]`
*/
const toLch = (c) => toPolar(toLab(c));
/**
* @param {number[]} c `[L, C, H]`
* @returns {number[]} the linear-light components
*/
const fromLch = (c) => fromLab(fromPolar(c));
/**
* @param {number[]} c the linear-light components
* @returns {number[]} `[L, C, H]`
*/
const toOklch = (c) => toPolar(toOklab(c));
/**
* @param {number[]} c `[L, C, H]`
* @returns {number[]} the linear-light components
*/
const fromOklch = (c) => fromOklab(fromPolar(c));
/**
* Linear-light sRGB -> HSL (CSS Color 4 §7.1), through sRGB.
* @param {number[]} c the linear-light components
* @returns {number[]} `[H, S, L]`, H in degrees and the rest 0..1
*/
const toHsl = (c) => {
const [r, g, b] = c.map(srgbEncode);
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
const light = (min + max) / 2;
const range = max - min;
if (range === 0) return [0, 0, light];
let hue;
if (max === r) hue = ((g - b) / range) % 6;
else if (max === g) hue = (b - r) / range + 2;
else hue = (r - g) / range + 4;
hue *= 60;
if (hue < 0) hue += 360;
return [hue, range / (1 - Math.abs(2 * light - 1)), light];
};
/**
* HSL -> linear-light sRGB.
* @param {number[]} c `[H, S, L]`
* @returns {number[]} the linear-light components
*/
const fromHsl = (c) => {
let hue = c[0] % 360;
if (hue < 0) hue += 360;
const amount = c[1] * Math.min(c[2], 1 - c[2]);
return [0, 8, 4]
.map((n) => {
const k = (n + hue / 30) % 12;
return c[2] - amount * Math.max(-1, Math.min(k - 3, 9 - k, 1));
})
.map(srgbTransfer);
};
/**
* Linear-light sRGB -> HWB (CSS Color 4 §7.2).
* @param {number[]} c the linear-light components
* @returns {number[]} `[H, W, B]`
*/
const toHwb = (c) => {
const srgb = c.map(srgbEncode);
return [
toHsl(c)[0],
Math.min(srgb[0], srgb[1], srgb[2]),
1 - Math.max(srgb[0], srgb[1], srgb[2])
];
};
/**
* HWB -> linear-light sRGB.
* @param {number[]} c `[H, W, B]`
* @returns {number[]} the linear-light components
*/
const fromHwb = (c) => {
if (c[1] + c[2] >= 1) {
const gray = c[1] / (c[1] + c[2]);
return [gray, gray, gray].map(srgbTransfer);
}
return fromHsl([c[0], 1, 0.5]).map((value) =>
srgbTransfer(srgbEncode(value) * (1 - c[1] - c[2]) + c[1])
);
};
const SRGB_M = [1, 0, 0, 0, 1, 0, 0, 0, 1];
const SRGB_I = [1, 0, 0, 0, 1, 0, 0, 0, 1];
/** @type {(c: number[]) => number[]} */
const toSrgb = (c) => applyModel(SRGB_M, c).map(srgbEncode);
/** @type {(c: number[]) => number[]} */
const fromSrgb = (c) => applyModel(SRGB_I, c.map(srgbTransfer));
const SRGB_LINEAR_M = [1, 0, 0, 0, 1, 0, 0, 0, 1];
const SRGB_LINEAR_I = [1, 0, 0, 0, 1, 0, 0, 0, 1];
/** @type {(c: number[]) => number[]} */
const toSrgbLinear = (c) => applyModel(SRGB_LINEAR_M, c).map(linearEncode);
/** @type {(c: number[]) => number[]} */
const fromSrgbLinear = (c) => applyModel(SRGB_LINEAR_I, c.map(linearTransfer));
const DISPLAY_P3_M = [
0.8224619687143625, 0.17753803128563775, 3.3650564745655794e-18,
0.0331941988509616, 0.9668058011490385, 1.8324840583423322e-17,
0.017082630721120023, 0.07239744066396339, 0.9105199286149164
];
const DISPLAY_P3_I = [
1.2249401762805596, -0.22494017628055984, 0, -0.04205695470968812,
1.042056954709688, -2.0816681711721685e-17, -0.019637554590334425,
-0.0786360455506318, 1.0982736001409665
];
/** @type {(c: number[]) => number[]} */
const toDisplayP3 = (c) => applyModel(DISPLAY_P3_M, c).map(srgbEncode);
/** @type {(c: number[]) => number[]} */
const fromDisplayP3 = (c) => applyModel(DISPLAY_P3_I, c.map(srgbTransfer));
const A98_RGB_M = [
0.7151256068556245, 0.2848743931443755, -3.237737802690131e-17,
1.0063922760456419e-16, 1, 1.9959826532201272e-17, -7.752312519259058e-18,
0.04116194845011838, 0.9588380515498818
];
const A98_RGB_I = [
1.3983557439607786, -0.39835574396077855, 5.551115123125783e-17,
-1.4072944198861848e-16, 1, -2.0816681711721685e-17, 1.734723475976807e-17,
-0.04292898929447317, 1.042928989294473
];
/** @type {(c: number[]) => number[]} */
const toA98Rgb = (c) => applyModel(A98_RGB_M, c).map(a98Encode);
/** @type {(c: number[]) => number[]} */
const fromA98Rgb = (c) => applyModel(A98_RGB_I, c.map(a98Transfer));
const PROPHOTO_RGB_M = [
0.5292769842583223, 0.3301545636252504, 0.14056844993940584,
0.09836583745016964, 0.8734706333869527, 0.028163490634021324,
0.016875355289046535, 0.1176594475769436, 0.8654652433945142
];
const PROPHOTO_RGB_I = [
2.034380836302867, -0.7276360137172471, -0.3067448320015419,
-0.228825697964331, 1.2317426727787788, -0.0029169277200310345,
-0.008558858080647581, -0.15326675125999153, 1.161825549670178
];
/** @type {(c: number[]) => number[]} */
const toProphotoRgb = (c) => applyModel(PROPHOTO_RGB_M, c).map(prophotoEncode);
/** @type {(c: number[]) => number[]} */
const fromProphotoRgb = (c) =>
applyModel(PROPHOTO_RGB_I, c.map(prophotoTransfer));
const REC2020_M = [
0.6274038959346989, 0.32928303837788375, 0.04331306568741721,
0.06909728935823205, 0.9195403950754593, 0.011362315566309202,
0.016391438875150217, 0.08801330787722576, 0.8955952532476239
];
const REC2020_I = [
1.6604910021084347, -0.5876411387885495, -0.07284986331988486,
-0.12455047452159063, 1.1328998971259596, -0.008349422604369508,
-0.018150763354905206, -0.10057889800800737, 1.1187296613629127
];
/** @type {(c: number[]) => number[]} */
const toRec2020 = (c) => applyModel(REC2020_M, c).map(rec2020Encode);
/** @type {(c: number[]) => number[]} */
const fromRec2020 = (c) => applyModel(REC2020_I, c.map(rec2020Transfer));
const XYZ_M = [
0.41239079926595934, 0.357584339383878, 0.18048078840183424,
0.21263900587151027, 0.7151686787677561, 0.07219231536073371,
0.01933081871559181, 0.11919477979462595, 0.9505321522496607
];
const XYZ_I = [
3.2409699419045226, -1.537383177570094, -0.4986107602930034,
-0.9692436362808796, 1.8759675015077202, 0.04155505740717559,
0.05563007969699366, -0.20397695888897652, 1.0569715142428786
];
const XYZ_D50_M = [
0.436065749632219, 0.3851515490648008, 0.14307837223757391,
0.22249316329879926, 0.7168869742512141, 0.06061983440080464,
0.01392393331799153, 0.09708135172457436, 0.7140993556376494
];
const XYZ_D50_I = [
3.1341359569958707, -1.6173863321612538, -0.4906619460083532,
-0.978795502912089, 1.9162545672595237, 0.03344273116131948,
0.07195537988411684, -0.22897682641583222, 1.4053860583241256
];
/** @type {(c: number[]) => number[]} */
const toXyz = (c) => applyModel(XYZ_M, c);
/** @type {(c: number[]) => number[]} */
const fromXyz = (c) => applyModel(XYZ_I, c);
/** @type {(c: number[]) => number[]} */
const toXyzD50 = (c) => applyModel(XYZ_D50_M, c);
/** @type {(c: number[]) => number[]} */
const fromXyzD50 = (c) => applyModel(XYZ_D50_I, c);
const LMS_M = [
0.4122214708, 0.5363325363, 0.0514459929, 0.2119034982, 0.6806995451,
0.1073969566, 0.0883024619, 0.2817188376, 0.6299787005
];
const LMS_I = [
4.076741661347994, -3.3077115904081933, 0.23096992872942784,
-1.268438004092176, 2.6097574006633715, -0.34131939631021946,
-0.004196086541837046, -0.7034186144594494, 1.7076147009309446
];
const OKLAB_M = [
0.2104542553, 0.793617785, -0.0040720468, 1.9779984951, -2.428592205,
0.4505937099, 0.0259040371, 0.7827717662, -0.808675766
];
const OKLAB_I = [
0.9999999984505199, 0.39633779217376786, 0.2158037580607588,
1.0000000088817607, -0.10556134232365634, -0.0638541747717059,
1.000000054672411, -0.08948418209496577, -1.291485537864092
];
/**
* @param {number[]} c a color's components in Oklch
* @returns {boolean} true where an engine may read the hue as missing
*/
const uncertainOklchHue = (c) => Math.abs(c[1]) < 0.03;
// The space a hex and an `rgb()` state their components in.
const SRGB_SPACE = "srgb";
/** @typedef {{ to: (c: number[]) => number[], from: (c: number[]) => number[], hue: number, conversion: number, written: { open: string, scale: number[], percent: boolean[], feature: string }, uncertainHue: ((c: number[]) => boolean) | null }} ColorSpaceModel */
/** @type {Map<string, ColorSpaceModel>} */
const COLOR_SPACE_MODEL = new Map([
[
"srgb",
{
to: toSrgb,
from: fromSrgb,
hue: -1,
conversion: 0,
written: {
open: "color(srgb ",
scale: [1, 1, 1],
percent: [false, false, false],
feature: "colorFunction"
},
uncertainHue: null
}
],
[
"srgb-linear",
{
to: toSrgbLinear,
from: fromSrgbLinear,
hue: -1,
conversion: 1,
written: {
open: "color(srgb-linear ",
scale: [1, 1, 1],
percent: [false, false, false],
feature: "colorFunction"
},
uncertainHue: null
}
],
[
"display-p3",
{
to: toDisplayP3,
from: fromDisplayP3,
hue: -1,
conversion: 2,
written: {
open: "color(display-p3 ",
scale: [1, 1, 1],
percent: [false, false, false],
feature: "colorFunction"
},
uncertainHue: null
}
],
[
"a98-rgb",
{
to: toA98Rgb,
from: fromA98Rgb,
hue: -1,
conversion: 3,
written: {
open: "color(a98-rgb ",
scale: [1, 1, 1],
percent: [false, false, false],
feature: "colorFunction"
},
uncertainHue: null
}
],
[
"prophoto-rgb",
{
to: toProphotoRgb,
from: fromProphotoRgb,
hue: -1,
conversion: 3,
written: {
open: "color(prophoto-rgb ",
scale: [1, 1, 1],
percent: [false, false, false],
feature: "colorFunction"
},
uncertainHue: null
}
],
[
"rec2020",
{
to: toRec2020,
from: fromRec2020,
hue: -1,
conversion: 2,
written: {
open: "color(rec2020 ",
scale: [1, 1, 1],
percent: [false, false, false],
feature: "colorFunction"
},
uncertainHue: null
}
],
[
"xyz",
{
to: toXyz,
from: fromXyz,
hue: -1,
conversion: 2,
written: {
open: "color(xyz ",
scale: [1, 1, 1],
percent: [false, false, false],
feature: "colorFunction"
},
uncertainHue: null
}
],
[
"xyz-d65",
{
to: toXyz,
from: fromXyz,
hue: -1,
conversion: 2,
written: {
open: "color(xyz-d65 ",
scale: [1, 1, 1],
percent: [false, false, false],
feature: "colorFunction"
},
uncertainHue: null
}
],
[
"xyz-d50",
{
to: toXyzD50,
from: fromXyzD50,
hue: -1,
conversion: 2,
written: {
open: "color(xyz-d50 ",
scale: [1, 1, 1],
percent: [false, false, false],
feature: "colorFunction"
},
uncertainHue: null
}
],
[
"lab",
{
to: toLab,
from: fromLab,
hue: -1,
conversion: 2,
written: {
open: "lab(",
scale: [1, 1, 1],
percent: [false, false, false],
feature: "labColors"
},
uncertainHue: null
}
],
[
"lch",
{
to: toLch,
from: fromLch,
hue: 2,
conversion: 2,
written: {
open: "lch(",
scale: [1, 1, 1],
percent: [false, false, false],
feature: "labColors"
},
uncertainHue: null
}
],
[
"oklab",
{
to: toOklab,
from: fromOklab,
hue: -1,
conversion: 2,
written: {
open: "oklab(",
scale: [1, 1, 1],
percent: [false, false, false],
feature: "oklabColors"
},
uncertainHue: null
}
],
[
"oklch",
{
to: toOklch,
from: fromOklch,
hue: 2,
conversion: 2,
written: {
open: "oklch(",
scale: [1, 1, 1],
percent: [false, false, false],
feature: "oklabColors"
},
uncertainHue: uncertainOklchHue
}
],
[
"hsl",
{
to: toHsl,
from: fromHsl,
hue: 0,
conversion: 0,
written: {
open: "hsl(",
scale: [1, 100, 100],
percent: [false, true, true],
feature: ""
},
uncertainHue: null
}
],
[
"hwb",
{
to: toHwb,
from: fromHwb,
hue: 0,
conversion: 0,
written: {
open: "hwb(",
scale: [1, 100, 100],
percent: [false, true, true],
feature: "hwbColors"
},
uncertainHue: null
}
]
]);
// The named colors an engine may not read while reading the rest, so one says
// nothing about what another takes. Every other name is as old as naming one.
const LATER_COLOR_NAMES = new Set(["rebeccapurple", "transparent"]);
// Every named color as its packed `0xrrggbb` value — what a color a mix or a
// relative reference names resolves through. The two tables above cut this one
// down to the spellings worth rewriting; this one answers for every name.
/** @type {Map<string, number>} */
const COLOR_NAME_TO_RGB = new Map([
["aliceblue", 15792383],
["antiquewhite", 16444375],
["aqua", 65535],
["aquamarine", 8388564],
["azure", 15794175],
["beige", 16119260],
["bisque", 16770244],
["black", 0],
["blanchedalmond", 16772045],
["blue", 255],
["blueviolet", 9055202],
["brown", 10824234],
["burlywood", 14596231],
["cadetblue", 6266528],
["chartreuse", 8388352],
["chocolate", 13789470],
["coral", 16744272],
["cornflowerblue", 6591981],
["cornsilk", 16775388],
["crimson", 14423100],
["cyan", 65535],
["darkblue", 139],
["darkcyan", 35723],
["darkgoldenrod", 12092939],
["darkgray", 11119017],
["darkgreen", 25600],
["darkgrey", 11119017],
["darkkhaki", 12433259],
["darkmagenta", 9109643],
["darkolivegreen", 5597999],
["darkorange", 16747520],
["darkorchid", 10040012],
["darkred", 9109504],
["darksalmon", 15308410],
["darkseagreen", 9419919],
["darkslateblue", 4734347],
["darkslategray", 3100495],
["darkslategrey", 3100495],
["darkturquoise", 52945],
["darkviolet", 9699539],
["deeppink", 16716947],
["deepskyblue", 49151],
["dimgray", 6908265],
["dimgrey", 6908265],
["dodgerblue", 2003199],
["firebrick", 11674146],
["floralwhite", 16775920],
["forestgreen", 2263842],
["fuchsia", 16711935],
["gainsboro", 14474460],
["ghostwhite", 16316671],
["gold", 16766720],
["goldenrod", 14329120],
["gray", 8421504],
["green", 32768],
["greenyellow", 11403055],
["grey", 8421504],
["honeydew", 15794160],
["hotpink", 16738740],
["indianred", 13458524],
["indigo", 4915330],
["ivory", 16777200],
["khaki", 15787660],
["lavender", 15132410],
["lavenderblush", 16773365],
["lawngreen", 8190976],
["lemonchiffon", 16775885],
["lightblue", 11393254],
["lightcoral", 15761536],
["lightcyan", 14745599],
["lightgoldenrodyellow", 16448210],
["lightgray", 13882323],
["lightgreen", 9498256],
["lightgrey", 13882323],
["lightpink", 16758465],
["lightsalmon", 16752762],
["lightseagreen", 2142890],
["lightskyblue", 8900346],
["lightslategray", 7833753],
["lightslategrey", 7833753],
["lightsteelblue", 11584734],
["lightyellow", 16777184],
["lime", 65280],
["limegreen", 3329330],
["linen", 16445670],
["magenta", 16711935],
["maroon", 8388608],
["mediumaquamarine", 6737322],
["mediumblue", 205],
["mediumorchid", 12211667],
["mediumpurple", 9662683],
["mediumseagreen", 3978097],
["mediumslateblue", 8087790],
["mediumspringgreen", 64154],
["mediumturquoise", 4772300],
["mediumvioletred", 13047173],
["midnightblue", 1644912],
["mintcream", 16121850],
["mistyrose", 16770273],
["moccasin", 16770229],
["navajowhite", 16768685],
["navy", 128],
["oldlace", 16643558],
["olive", 8421376],
["olivedrab", 7048739],
["orange", 16753920],
["orangered", 16729344],
["orchid", 14315734],
["palegoldenrod", 15657130],
["palegreen", 10025880],
["paleturquoise", 11529966],
["palevioletred", 14381203],
["papayawhip", 16773077],
["peachpuff", 16767673],
["peru", 13468991],
["pink", 16761035],
["plum", 14524637],
["powderblue", 11591910],
["purple", 8388736],
["rebeccapurple", 6697881],
["red", 16711680],
["rosybrown", 12357519],
["royalblue", 4286945],
["saddlebrown", 9127187],
["salmon", 16416882],
["sandybrown", 16032864],
["seagreen", 3050327],
["seashell", 16774638],
["sienna", 10506797],
["silver", 12632256],
["skyblue", 8900331],
["slateblue", 6970061],
["slategray", 7372944],
["slategrey", 7372944],
["snow", 16775930],
["springgreen", 65407],
["steelblue", 4620980],
["tan", 13808780],
["teal", 32896],
["thistle", 14204888],
["tomato", 16737095],
["turquoise", 4251856],
["violet", 15631086],
["wheat", 16113331],
["white", 16777215],
["whitesmoke", 16119285],
["yellow", 16776960],
["yellowgreen", 10145074]
]);
// What a layered shorthand's position, size, origin and clip hold when nothing
// writes them, as `[x, y, size, origin, clip]`. A layer holding its own is a
// layer the shorthand says without them.
const LAYER_INITIALS = new Map([
["background", ["0%", "0%", "auto", "padding-box", "border-box"]],
["mask", ["0%", "0%", "auto", "border-box", "border-box"]]
]);
// What each slot of a family shorthand holds when nothing writes it. A slot
// holding its own initial says nothing beside the others.
const FAMILY_SLOT_INITIALS = new Map([
["border-block-end-color", "currentcolor"],
["border-block-end-style", "none"],
["border-block-end-width", "medium"],
["border-block-start-color", "currentcolor"],
["border-block-start-style", "none"],
["border-block-start-width", "medium"],
["border-bottom-color", "currentcolor"],
["border-bottom-style", "none"],
["border-bottom-width", "medium"],
["border-inline-end-color", "currentcolor"],
["border-inline-end-style", "none"],
["border-inline-end-width", "medium"],
["border-inline-start-color", "currentcolor"],
["border-inline-start-style", "none"],
["border-inline-start-width", "medium"],
["border-left-color", "currentcolor"],
["border-left-style", "none"],
["border-left-width", "medium"],
["border-right-color", "currentcolor"],
["border-right-style", "none"],
["border-right-width", "medium"],
["border-top-color", "currentcolor"],
["border-top-style", "none"],
["border-top-width", "medium"],
["column-rule-color", "currentcolor"],
["column-rule-style", "none"],
["column-rule-width", "medium"],
["flex-direction", "row"],
["flex-wrap", "nowrap"],
["list-style-image", "none"],
["list-style-position", "outside"],
["list-style-type", "disc"],
["outline-color", "auto"],
["outline-style", "none"],
["outline-width", "medium"],
["text-decoration-color", "currentcolor"],
["text-decoration-line", "none"],
["text-decoration-style", "solid"],
["text-decoration-thickness", "auto"],
["text-emphasis-color", "currentcolor"],
["text-emphasis-style", "none"],
["text-wrap-mode", "wrap"],
["text-wrap-style", "auto"]
]);
// The font stack `system-ui` names, for a target that does not read the keyword.
const SYSTEM_UI_STACK =
"system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Noto Sans,Ubuntu,Cantarell,Helvetica Neue";
// The angle units. Excluded from rounding: `rotate()` runs its argument through
// trig, which turns a truncated digit into a different computed matrix.
const ANGLE_UNITS = new Set(["deg", "grad", "rad", "turn"]);
// The constants a calculation may name (CSS Values 4 §10.7), as `name -> value`.
// `infinity` and `NaN` are named with none: no printed number spells either, so
// a calculation naming one is left as it stands.
/** @type {Map<string, number | null>} */
const CALC_CONSTANTS = new Map([
["e", Math.E],
["infinity", null],
["nan", null],
["pi", Math.PI]
]);
// A quarter turn in each unit that spells it exactly (CSS Values 4 §8.1), as
// `unit -> the count`. It is what a trig function's argument is read as degrees
// through, and the eighths of it are where sine and cosine are rational.
/** @type {Map<string, number>} */
const QUARTER_TURN_ANGLE = new Map([
["deg", 90],
["grad", 100],
["turn", 0.25]
]);
// Sine, cosine and tangent as `eighth turn from zero -> value`. The eighths
// where the value is irrational are absent — sine and cosine on the odd ones,
// tangent on the asymptotes. Cosine is sine a quarter turn along.
/** @type {Map<number, number>} */
const EIGHTH_TURN_SINE = new Map([
[0, 0],
[2, 1],
[4, 0],
[6, -1]
]);
/** @type {Map<number, number>} */
const EIGHTH_TURN_COSINE = new Map([
[0, 1],
[2, 0],
[4, -1],
[6, 0]
]);
/** @type {Map<number, number>} */
const EIGHTH_TURN_TANGENT = new Map([
[0, 0],
[1, 1],
[3, -1],
[4, 0],
[5, 1],
[7, -1]
]);
// What each inverse trig function answers, as `argument -> degrees`, by
// inverting the table above it over that function's principal branch. Every
// other argument is transcendental and leaves the call written out.
/** @type {Map<number, number>} */
const ARC_SINE_DEGREES = new Map([
[-1, -90],
[0, 0],
[1, 90]
]);
/** @type {Map<number, number>} */
const ARC_COSINE_DEGREES = new Map([
[-1, 180],
[0, 90],
[1, 0]
]);
/** @type {Map<number, number>} */
const ARC_TANGENT_DEGREES = new Map([
[-1, -45],
[0, 0],
[1, 45]
]);
// The reader that needs a table, built once here — `mathPrimitives` knows how to
// read an angle but not which units spell a quarter turn.
const readAngle = angleReader(QUARTER_TURN_ANGLE);
// The table a function that looks nothing up is handed.
/** @type {Map<number, number>} */
const NO_TABLE = new Map();
// What folding each math function comes down to, as
// `name -> { read, apply, result, table }`: how its arguments are read, which
// arithmetic runs, and the unit the answer carries. `read` and `apply` are the
// functions themselves, so `lib/css/syntax.js` drives the fold while naming
// neither a math function nor an arithmetic of its own.
/** @type {Map<string, { read: MathArgumentReader, apply: MathOperation, result: string, table: Map<number, number> }>} */
const MATH_FUNCTION_FOLD = new Map([
[
"abs",
{ read: readSameUnit, apply: absolute, result: "same", table: NO_TABLE }
],
[
"acos",
{
read: readNumber,
apply: statedAngle,
result: "deg",
table: ARC_COSINE_DEGREES
}
],
[
"asin",
{
read: readNumber,
apply: statedAngle,
result: "deg",
table: ARC_SINE_DEGREES
}
],
[
"atan",
{
read: readNumber,
apply: statedAngle,
result: "deg",
table: ARC_TANGENT_DEGREES
}
],
[
"atan2",
{ read: readSameUnit, apply: arcTangent2, result: "deg", table: NO_TABLE }
],
[
"clamp",
{ read: readSameUnit, apply: clamp, result: "same", table: NO_TABLE }
],
[
"cos",
{ read: readAngle, apply: cosine, result: "", table: EIGHTH_TURN_COSINE }
],
[
"exp",
{ read: readNumber, apply: exponential, result: "", table: NO_TABLE }
],
[
"hypot",
{ read: readSameUnit, apply: hypotenuse, result: "same", table: NO_TABLE }
],
["log", { read: readNumber, apply: logarithm, result: "", table: NO_TABLE }],
[
"max",
{ read: readSameUnit, apply: maximum, result: "same", table: NO_TABLE }
],
[
"min",
{ read: readSameUnit, apply: minimum, result: "same", table: NO_TABLE }
],
[
"mod",
{ read: readSameUnit, apply: modulus, result: "same", table: NO_TABLE }
],
["pow", { read: readNumber, apply: power, result: "", table: NO_TABLE }],
[
"rem",
{ read: readSameUnit, apply: remainder, result: "same", table: NO_TABLE }
],
[
"round",
{ read: readSameUnit, apply: round, result: "same", table: NO_TABLE }
],
["sign", { read: readSameUnit, apply: sign, result: "", table: NO_TABLE }],
[
"sin",
{ read: readAngle, apply: sine, result: "", table: EIGHTH_TURN_SINE }
],
[
"sqrt",
{ read: readNumber, apply: squareRoot, result: "", table: NO_TABLE }
],
[
"tan",
{ read: readAngle, apply: tangent, result: "", table: EIGHTH_TURN_TANGENT }
]
]);
// Properties whose grammar can reach an `<integer>`. Deliberately wide: a
// non-integer where an integer is expected is rounded rather than dropped
// (`z-index: calc(1.5)` computes to `2`), so this is read to refuse a rewrite,
// and one name too many costs only that rewrite.
const INTEGER_PROPERTIES = new Set([
"-ms-grid-columns",
"-ms-grid-rows",
"-ms-hyphenate-limit-chars",
"-ms-hyphenate-limit-lines",
"-webkit-line-clamp",
"animation",
"animation-timing-function",
"box-flex-group",
"box-ordinal-group",
"column-count",
"columns",
"counter-increment",
"counter-reset",
"counter-set",
"flex-line-count",
"font-feature-settings",
"grid",
"grid-area",
"grid-column",
"grid-column-end",
"grid-column-start",
"grid-row",
"grid-row-end",
"grid-row-start",
"grid-template",
"grid-template-columns",
"grid-template-rows",
"hyphenate-limit-chars",
"initial-letter",
"line-clamp",
"math-depth",
"max-lines",
"order",
"orphans",
"reading-order",
"tab-size",
"text-combine-upright",
"transition",
"transition-timing-function",
"widows",
"z-index"
]);
// The properties whose value is one `<number> | <percentage>`, where the
// percentage is the number hundredfold and the two compute to the same thing.
const ALPHA_VALUE_PROPERTIES = new Set(["opacity", "shape-image-threshold"]);
// The properties taking a `<ratio>`, whose second number of `1` is the one an
// omitted denominator means.
const RATIO_PROPERTIES = new Set(["aspect-ratio"]);
// The keywords of every property a `css/module` reads a scoped name out of,
// each mapped to how many times it may be spelled before the next one is the
// name (`Infinity` — never the name). Derived from each property's grammar.
const CSS_MODULES_KEYWORDS = new Map([
[
"animation",
new Map([
["alternate", 1],
["alternate-reverse", 1],
["auto", Infinity],
["backwards", 1],
["both", 1],
["ease", 1],
["ease-in", 1],
["ease-in-out", 1],
["ease-out", 1],
["forwards", 1],
["infinite", 1],
["inherit", Infinity],
["initial", Infinity],
["linear", 1],
["none", Infinity],
["normal", 1],
["paused", 1],
["reverse", 1],
["revert", Infinity],
["revert-layer", Infinity],
["running", 1],
["step-end", 1],
["step-start", 1],
["unset", Infinity]
])
],
[
"animation-name",
new Map([
["inherit", Infinity],
["initial", Infinity],
["none", Infinity],
["revert", Infinity],
["revert-layer", Infinity],
["unset", Infinity]
])
],
[
"container",
new Map([
["inherit", Infinity],
["initial", Infinity],
["inline-size", 1],
["none", Infinity],
["normal", 1],
["revert", Infinity],
["revert-layer", Infinity],
["scroll-state", 1],
["size", 1],
["unset", Infinity]
])
],
[
"container-name",
new Map([
["inherit", Infinity],
["initial", Infinity],
["none", Infinity],
["revert", Infinity],
["revert-layer", Infinity],
["unset", Infinity]
])
],
[
"list-style",
new Map([
["arabic-indic", 1],
["armenian", 1],
["bengali", 1],
["cambodian", 1],
["circle", 1],
["cjk-decimal", 1],
["cjk-earthly-branch", 1],
["cjk-heavenly-stem", 1],
["cjk-ideographic", 1],
["decimal", 1],
["decimal-leading-zero", 1],
["devanagari", 1],
["disc", 1],
["disclosure-closed", 1],
["disclosure-open", 1],
["ethiopic-numeric", 1],
["georgian", 1],
["gujarati", 1],
["gurmukhi", 1],
["hebrew", 1],
["hiragana", 1],
["hiragana-iroha", 1],
["inherit", Infinity],
["initial", Infinity],
["inside", 1],
["japanese-formal", 1],
["japanese-informal", 1],
["kannada", 1],
["katakana", 1],
["katakana-iroha", 1],
["khmer", 1],
["korean-hangul-formal", 1],
["korean-hanja-formal", 1],
["korean-hanja-informal", 1],
["lao", 1],
["lower-alpha", 1],
["lower-armenian", 1],
["lower-greek", 1],
["lower-latin", 1],
["lower-roman", 1],
["malayalam", 1],
["mongolian", 1],
["myanmar", 1],
["none", Infinity],
["oriya", 1],
["outside", 1],
["persian", 1],
["revert", Infinity],
["revert-layer", Infinity],
["simp-chinese-formal", 1],
["simp-chinese-informal", 1],
["square", 1],
["tamil", 1],
["telugu", 1],
["thai", 1],
["tibetan", 1],
["trad-chinese-formal", 1],
["trad-chinese-informal", 1],
["unset", Infinity],
["upper-alpha", 1],
["upper-armenian", 1],
["upper-latin", 1],
["upper-roman", 1]
])
],
[
"list-style-type",
new Map([
["arabic-indic", 1],
["armenian", 1],
["bengali", 1],
["cambodian", 1],
["circle", 1],
["cjk-decimal", 1],
["cjk-earthly-branch", 1],
["cjk-heavenly-stem", 1],
["cjk-ideographic", 1],
["decimal", 1],
["decimal-leading-zero", 1],
["devanagari", 1],
["disc", 1],
["disclosure-closed", 1],
["disclosure-open", 1],
["ethiopic-numeric", 1],
["georgian", 1],
["gujarati", 1],
["gurmukhi", 1],
["hebrew", 1],
["hiragana", 1],
["hiragana-iroha", 1],
["inherit", Infinity],
["initial", Infinity],
["japanese-formal", 1],
["japanese-informal", 1],
["kannada", 1],
["katakana", 1],
["katakana-iroha", 1],
["khmer", 1],
["korean-hangul-formal", 1],
["korean-hanja-formal", 1],
["korean-hanja-informal", 1],
["lao", 1],
["lower-alpha", 1],
["lower-armenian", 1],
["lower-greek", 1],
["lower-latin", 1],
["lower-roman", 1],
["malayalam", 1],
["mongolian", 1],
["myanmar", 1],
["none", Infinity],
["oriya", 1],
["persian", 1],
["revert", Infinity],
["revert-layer", Infinity],
["simp-chinese-formal", 1],
["simp-chinese-informal", 1],
["square", 1],
["tamil", 1],
["telugu", 1],
["thai", 1],
["tibetan", 1],
["trad-chinese-formal", 1],
["trad-chinese-informal", 1],
["unset", Infinity],
["upper-alpha", 1],
["upper-armenian", 1],
["upper-latin", 1],
["upper-roman", 1]
])
],
[
"system",
new Map([
["additive", 1],
["alphabetic", 1],
["arabic-indic", 1],
["armenian", 1],
["bengali", 1],
["cambodian", 1],
["circle", 1],
["cjk-decimal", 1],
["cjk-earthly-branch", 1],
["cjk-heavenly-stem", 1],
["cjk-ideographic", 1],
["cyclic", 1],
["decimal", 1],
["decimal-leading-zero", 1],
["devanagari", 1],
["disc", 1],
["disclosure-closed", 1],
["disclosure-open", 1],
["ethiopic-numeric", 1],
["extends", 1],
["fixed", 1],
["georgian", 1],
["gujarati", 1],
["gurmukhi", 1],
["hebrew", 1],
["hiragana", 1],
["hiragana-iroha", 1],
["japanese-formal", 1],
["japanese-informal", 1],
["kannada", 1],
["katakana", 1],
["katakana-iroha", 1],
["khmer", 1],
["korean-hangul-formal", 1],
["korean-hanja-formal", 1],
["korean-hanja-informal", 1],
["lao", 1],
["lower-alpha", 1],
["lower-armenian", 1],
["lower-greek", 1],
["lower-latin", 1],
["lower-roman", 1],
["malayalam", 1],
["mongolian", 1],
["myanmar", 1],
["numeric", 1],
["oriya", 1],
["persian", 1],
["simp-chinese-formal", 1],
["simp-chinese-informal", 1],
["square", 1],
["symbolic", 1],
["tamil", 1],
["telugu", 1],
["thai", 1],
["tibetan", 1],
["trad-chinese-formal", 1],
["trad-chinese-informal", 1],
["upper-alpha", 1],
["upper-armenian", 1],
["upper-latin", 1],
["upper-roman", 1]
])
],
[
"fallback",
new Map([
["arabic-indic", 1],
["armenian", 1],
["bengali", 1],
["cambodian", 1],
["circle", 1],
["cjk-decimal", 1],
["cjk-earthly-branch", 1],
["cjk-heavenly-stem", 1],
["cjk-ideographic", 1],
["decimal", 1],
["decimal-leading-zero", 1],
["devanagari", 1],
["disc", 1],
["disclosure-closed", 1],
["disclosure-open", 1],
["ethiopic-numeric", 1],
["georgian", 1],
["gujarati", 1],
["gurmukhi", 1],
["hebrew", 1],
["hiragana", 1],
["hiragana-iroha", 1],
["japanese-formal", 1],
["japanese-informal", 1],
["kannada", 1],
["katakana", 1],
["katakana-iroha", 1],
["khmer", 1],
["korean-hangul-formal", 1],
["korean-hanja-formal", 1],
["korean-hanja-informal", 1],
["lao", 1],
["lower-alpha", 1],
["lower-armenian", 1],
["lower-greek", 1],
["lower-latin", 1],
["lower-roman", 1],
["malayalam", 1],
["mongolian", 1],
["myanmar", 1],
["oriya", 1],
["persian", 1],
["simp-chinese-formal", 1],
["simp-chinese-informal", 1],
["square", 1],
["tamil", 1],
["telugu", 1],
["thai", 1],
["tibetan", 1],
["trad-chinese-formal", 1],
["trad-chinese-informal", 1],
["upper-alpha", 1],
["upper-armenian", 1],
["upper-latin", 1],
["upper-roman", 1]
])
],
[
"speak-as",
new Map([
["arabic-indic", 1],
["armenian", 1],
["auto", Infinity],
["bengali", 1],
["bullets", Infinity],
["cambodian", 1],
["circle", 1],
["cjk-decimal", 1],
["cjk-earthly-branch", 1],
["cjk-heavenly-stem", 1],
["cjk-ideographic", 1],
["decimal", 1],
["decimal-leading-zero", 1],
["devanagari", 1],
["disc", 1],
["disclosure-closed", 1],
["disclosure-open", 1],
["ethiopic-numeric", 1],
["georgian", 1],
["gujarati", 1],
["gurmukhi", 1],
["hebrew", 1],
["hiragana", 1],
["hiragana-iroha", 1],
["japanese-formal", 1],
["japanese-informal", 1],
["kannada", 1],
["katakana", 1],
["katakana-iroha", 1],
["khmer", 1],
["korean-hangul-formal", 1],
["korean-hanja-formal", 1],
["korean-hanja-informal", 1],
["lao", 1],
["lower-alpha", 1],
["lower-armenian", 1],
["lower-greek", 1],
["lower-latin", 1],
["lower-roman", 1],
["malayalam", 1],
["mongolian", 1],
["myanmar", 1],
["numbers", Infinity],
["oriya", 1],
["persian", 1],
["simp-chinese-formal", 1],
["simp-chinese-informal", 1],
["spell-out", Infinity],
["square", 1],
["tamil", 1],
["telugu", 1],
["thai", 1],
["tibetan", 1],
["trad-chinese-formal", 1],
["trad-chinese-informal", 1],
["upper-alpha", 1],
["upper-armenian", 1],
["upper-latin", 1],
["upper-roman", 1],
["words", Infinity]
])
],
[
"counter-reset",
new Map([
["inherit", Infinity],
["initial", Infinity],
["list-item", Infinity],
["none", 1],
["page", Infinity],
["pages", Infinity],
["revert", Infinity],
["revert-layer", Infinity],
["unset", Infinity]
])
],
[
"counter-increment",
new Map([
["inherit", Infinity],
["initial", Infinity],
["list-item", Infinity],
["none", 1],
["page", Infinity],
["pages", Infinity],
["revert", Infinity],
["revert-layer", Infinity],
["unset", Infinity]
])
],
[
"counter-set",
new Map([
["inherit", Infinity],
["initial", Infinity],
["list-item", Infinity],
["none", 1],
["page", Infinity],
["pages", Infinity],
["revert", Infinity],
["revert-layer", Infinity],
["unset", Infinity]
])
],
[
"view-transition-name",
new Map([
["auto", Infinity],
["inherit", Infinity],
["initial", Infinity],
["match-element", Infinity],
["none", Infinity],
["revert", Infinity],
["revert-layer", Infinity],
["unset", Infinity]
])
],
[
"view-transition-group",
new Map([
["contain", Infinity],
["inherit", Infinity],
["initial", Infinity],
["nearest", Infinity],
["normal", Infinity],
["revert", Infinity],
["revert-layer", Infinity],
["unset", Infinity]
])
],
[
"view-transition-class",
new Map([
["inherit", Infinity],
["initial", Infinity],
["none", Infinity],
["revert", Infinity],
["revert-layer", Infinity],
["unset", Infinity]
])
],
[
"grid",
new Map([
["auto", Infinity],
["auto-flow", 1],
["column", 1],
["dense", 1],
["inherit", Infinity],
["initial", Infinity],
["masonry", 1],
["max-content", Infinity],
["min-content", Infinity],
["none", 2],
["revert", Infinity],
["revert-layer", Infinity],
["row", 1],
["subgrid", 2],
["unset", Infinity]
])
],
[
"grid-area",
new Map([
["auto", Infinity],
["inherit", Infinity],
["initial", Infinity],
["revert", Infinity],
["revert-layer", Infinity],
["span", Infinity],
["unset", Infinity]
])
],
[
"grid-column",
new Map([
["auto", Infinity],
["inherit", Infinity],
["initial", Infinity],
["revert", Infinity],
["revert-layer", Infinity],
["span", Infinity],
["unset", Infinity]
])
],
[
"grid-column-end",
new Map([
["auto", Infinity],
["inherit", Infinity],
["initial", Infinity],
["revert", Infinity],
["revert-layer", Infinity],
["span", Infinity],
["unset", Infinity]
])
],
[
"grid-column-start",
new Map([
["auto", Infinity],
["inherit", Infinity],
["initial", Infinity],
["revert", Infinity],
["revert-layer", Infinity],
["span", Infinity],
["unset", Infinity]
])
],
[
"grid-row",
new Map([
["auto", Infinity],
["inherit", Infinity],
["initial", Infinity],
["revert", Infinity],
["revert-layer", Infinity],
["span", Infinity],
["unset", Infinity]
])
],
[
"grid-row-end",
new Map([
["auto", Infinity],
["inherit", Infinity],
["initial", Infinity],
["revert", Infinity],
["revert-layer", Infinity],
["span", Infinity],
["unset", Infinity]
])
],
[
"grid-row-start",
new Map([
["auto", Infinity],
["inherit", Infinity],
["initial", Infinity],
["revert", Infinity],
["revert-layer", Infinity],
["span", Infinity],
["unset", Infinity]
])
],
[
"grid-template",
new Map([
["auto", Infinity],
["inherit", Infinity],
["initial", Infinity],
["masonry", 1],
["max-content", Infinity],
["min-content", Infinity],
["none", 2],
["revert", Infinity],
["revert-layer", Infinity],
["subgrid", 2],
["unset", Infinity]
])
],
[
"grid-template-areas",
new Map([
["inherit", Infinity],
["initial", Infinity],
["none", 1],
["revert", Infinity],
["revert-layer", Infinity],
["unset", Infinity]
])
],
[
"grid-template-columns",
new Map([
["auto", Infinity],
["inherit", Infinity],
["initial", Infinity],
["masonry", 1],
["max-content", Infinity],
["min-content", Infinity],
["none", 1],
["revert", Infinity],
["revert-layer", Infinity],
["subgrid", 1],
["unset", Infinity]
])
],
[
"grid-template-rows",
new Map([
["auto", Infinity],
["inherit", Infinity],
["initial", Infinity],
["masonry", 1],
["max-content", Infinity],
["min-content", Infinity],
["none", 1],
["revert", Infinity],
["revert-layer", Infinity],
["subgrid", 1],
["unset", Infinity]
])
]
]);
// The parser option gating each of them.
const CSS_MODULES_KEYWORD_OPTIONS = new Map([
["animation", "animation"],
["animation-name", "animation"],
["container", "container"],
["container-name", "container"],
["list-style", "customIdents"],
["list-style-type", "customIdents"],
["system", "customIdents"],
["fallback", "customIdents"],
["speak-as", "customIdents"],
["counter-reset", "customIdents"],
["counter-increment", "customIdents"],
["counter-set", "customIdents"],
["view-transition-name", "customIdents"],
["view-transition-group", "customIdents"],
["view-transition-class", "customIdents"],
["grid", "grid"],
["grid-area", "grid"],
["grid-column", "grid"],
["grid-column-end", "grid"],
["grid-column-start", "grid"],
["grid-row", "grid"],
["grid-row-end", "grid"],
["grid-row-start", "grid"],
["grid-template", "grid"],
["grid-template-areas", "grid"],
["grid-template-columns", "grid"],
["grid-template-rows", "grid"]
]);
// The properties a negative value is valid on, so `calc(-5px)` may lose its
// parentheses there. Read to permit a rewrite, which is the opposite of
// `INTEGER_PROPERTIES` above: naming one property too many is a bug, naming one
// too few only costs a rewrite.
const NEGATIVE_ACCEPTING_PROPERTIES = new Set([
"animation-delay",
"background-position",
"background-position-x",
"background-position-y",
"bottom",
"inset",
"inset-block",
"inset-block-end",
"inset-block-start",
"inset-inline",
"inset-inline-end",
"inset-inline-start",
"left",
"letter-spacing",
"margin",
"margin-block",
"margin-block-end",
"margin-block-start",
"margin-bottom",
"margin-inline",
"margin-inline-end",
"margin-inline-start",
"margin-left",
"margin-right",
"margin-top",
"offset-distance",
"order",
"outline-offset",
"perspective-origin",
"right",
"rotate",
"scroll-margin",
"scroll-margin-block",
"scroll-margin-bottom",
"scroll-margin-inline",
"scroll-margin-left",
"scroll-margin-right",
"scroll-margin-top",
"stroke-dashoffset",
"text-indent",
"text-underline-offset",
"top",
"transform-origin",
"transition-delay",
"translate",
"vertical-align",
"word-spacing",
"z-index"
]);
// The functions whose every numeric argument is a length, so a zero inside one
// drops its unit the way a whole component's does. Read to permit a rewrite:
// any other numeric type would make the bare `0` mean something else, or make
// a dropped declaration valid.
const LENGTH_ONLY_FUNCTIONS = new Set([
"anchor",
"anchor-size",
"blur",
"circle",
"ellipse",
"fit-content",
"inset",
"perspective",
"polygon",
"rect",
"translate",
"translate3d",
"translatex",
"translatey",
"translatez",
"view",
"xywh"
]);
// Packed `0xrrggbb` -> the shortest named color with that value. Only names that
// can beat `#rrggbb`; anything longer would never be picked.
const RGB_TO_NAME = new Map([
[0x000080, "navy"],
[0x008000, "green"],
[0x008080, "teal"],
[0x4b0082, "indigo"],
[0x800000, "maroon"],
[0x800080, "purple"],
[0x808000, "olive"],
[0x808080, "gray"],
[0xa0522d, "sienna"],
[0xa52a2a, "brown"],
[0xc0c0c0, "silver"],
[0xcd853f, "peru"],
[0xd2b48c, "tan"],
[0xda70d6, "orchid"],
[0xdda0dd, "plum"],
[0xee82ee, "violet"],
[0xf0e68c, "khaki"],
[0xf0ffff, "azure"],
[0xf5deb3, "wheat"],
[0xf5f5dc, "beige"],
[0xfa8072, "salmon"],
[0xfaf0e6, "linen"],
[0xff0000, "red"],
[0xff6347, "tomato"],
[0xff7f50, "coral"],
[0xffa500, "orange"],
[0xffc0cb, "pink"],
[0xffd700, "gold"],
[0xffe4c4, "bisque"],
[0xfffafa, "snow"],
[0xfffff0, "ivory"]
]);
// Prefixed constructs the minifier reads back, one table per axis, as `name ->
// [prefix, windowList][]`. Versions are `major * 100000 + minor`; a target
// browser at version V needs the prefix when `prefixedFrom <= V < unprefixedFrom`
// (`NEVER` = never unprefixed). Non-standard-only constructs are absent.
// Every window list laid end to end as `browserSlot, prefixedFrom,
// unprefixedFrom` triples — the slot is the browser's place in
// `SUPPORT_BROWSERS`, so no name is restated. A spelling names its list by
// index, and two thirds of the lists are shared.
const PREFIX_WINDOWS = new Float64Array([
3, 2100000, 2900000, 0, 2500000, 2900000, 10, 1500000, 1600000, 9, 1400000,
1600000, 11, 700000, 900000, 8, 700000, 900000, 12, 100005, 200000, 6,
1000000, 1100000, 7, 1000000, 1100000, 3, 2100000, 2900000, 0, 2500000,
2900000, 11, 700000, 900000, 8, 700000, 900000, 12, 100005, 200000, 10,
1500000, 1600000, 9, 1400000, 1600000, 11, 800000, 1800000, 8, 800000,
1800000, 3, 300000, 4300000, 0, 1800000, 4300000, 10, 1500000, 3000000, 9,
1400000, 3000000, 11, 400000, 900000, 8, 300002, 900000, 12, 100000, 400000,
2, 200000, 4300000, 5, 500000, 1600000, 1, 500000, 1600000, 10, 1200000,
1500000, 9, 1200000, 1400000, 3, 300000, 4300000, 0, 1800000, 4300000, 10,
1500000, 3000000, 9, 1400000, 3000000, 11, 400000, 900000, 8, 300002, 900000,
12, 100000, 400000, 2, 400004, 4300000, 3, 300000, 4300000, 0, 1800000,
4300000, 10, 1500000, 3000000, 9, 1400000, 3000000, 11, 400000, 900000, 8,
400002, 900000, 12, 100000, 400000, 2, 200000, 4300000, 3, 300000, 4300000, 0,
1800000, 4300000, 10, 1500000, 3000000, 9, 1400000, 3000000, 11, 500000,
900000, 8, 400000, 900000, 12, 100000, 400000, 2, 400004, 4300000, 3, 300000,
4300000, 0, 1800000, 4300000, 10, 1500000, 3000000, 9, 1400000, 3000000, 11,
400000, 900000, 8, 200000, 900000, 12, 100000, 400000, 2, 400004, 4300000, 3,
100000, 8400000, 0, 1800000, 8400000, 4, 1200000, 8400000, 10, 1500000,
7000000, 9, 1400000, 6000000, 11, 300000, 1500004, 8, 100000, 1500004, 12,
100000, 1400000, 2, 400004, 8400000, 5, 100000, 8000000, 1, 400000, 8000000,
4, 1700000, 7900000, 11, 900000, 1800000, 8, 900000, 1800000, 3, 1200000,
3600000, 0, 1800000, 3600000, 10, 1500000, 2300000, 9, 1400000, 2400000, 11,
500001, 1500004, 8, 500000, 1500004, 12, 100000, 300000, 2, 300000, 3700000,
5, 1000000, 1600000, 1, 1000000, 1600000, 5, 100000, 400000, 11, 300000,
500000, 8, 100000, 500000, 3, 100000, 300000, 11, 300000, 500000, 8, 100000,
400002, 5, 300006, 400000, 10, 900005, 1000002, 3, 800000, 5700000, 0,
1800000, 5700000, 10, 1500000, 4400000, 9, 1400000, 4300000, 11, 500001,
1200001, 8, 500000, 1200002, 12, 100000, 700000, 2, 400004, 5700000, 3,
100000, 400000, 11, 300000, 500000, 8, 100000, 400002, 3, 700000, 1600000, 11,
300000, 600000, 8, 200000, 600000, 2, 200000, 400004, 5, 300005, 1500000, 1,
400000, 1500000, 10, 1000005, 1500000, 9, 1100000, 1400000, 5, 300000,
4100000, 1, 400000, 4100000, 3, 100000, 400000, 11, 300000, 500000, 8, 100000,
400002, 2, 200000, 400004, 3, 100000, 1e15, 0, 1800000, 1e15, 4, 1200000,
1e15, 10, 1500000, 1e15, 9, 1400000, 1e15, 11, 300000, 1e15, 8, 100000, 1e15,
12, 100000, 1e15, 2, 400004, 1e15, 5, 100000, 1e15, 1, 400000, 1e15, 3,
2200000, 13000000, 0, 2500000, 13000000, 4, 7900000, 13000000, 10, 1500000,
11500000, 9, 1400000, 8600000, 11, 700000, 1e15, 8, 700000, 1e15, 12, 100005,
2800000, 2, 400004, 13000000, 3, 100000, 6700000, 0, 1800000, 6700000, 10,
1500000, 5500000, 9, 1400000, 4800000, 11, 300000, 1e15, 8, 100000, 1e15, 12,
100000, 900000, 2, 400004, 6700000, 3, 100000, 1000000, 11, 300000, 500001, 8,
100000, 500000, 5, 300005, 400000, 3, 100000, 1000000, 11, 300000, 500001, 8,
100000, 600000, 2, 200000, 400000, 5, 100000, 2900000, 1, 400000, 2900000, 3,
2300000, 5500000, 0, 2500000, 5500000, 10, 1500000, 4200000, 9, 1400000,
4200000, 11, 700000, 900001, 8, 700000, 900003, 12, 100005, 600000, 2, 400004,
5500000, 3, 100000, 5000000, 0, 1800000, 5000000, 10, 1500000, 3700000, 9,
1400000, 3700000, 11, 300000, 900000, 8, 200000, 900000, 12, 100000, 500000,
2, 400004, 5000000, 5, 100005, 5200000, 1, 400000, 5200000, 5, 1700000,
5200000, 1, 1700000, 5200000, 11, 800000, 900000, 8, 800000, 900000, 3,
400000, 5000000, 11, 300001, 900000, 8, 300002, 900000, 10, 1500000, 3700000,
2, 200001, 500000, 12, 400000, 500000, 9, 1400000, 3700000, 5, 200000,
5200000, 3, 100000, 5000000, 0, 1800000, 5000000, 11, 300000, 900000, 8,
100000, 900000, 12, 100000, 500000, 2, 400004, 5000000, 10, 1500000, 3700000,
9, 1400000, 3700000, 5, 300005, 5200000, 1, 400000, 5200000, 3, 400000,
5000000, 0, 1800000, 5000000, 10, 1500000, 3700000, 9, 1400000, 3700000, 11,
300001, 900000, 8, 300002, 900000, 12, 100000, 500000, 2, 200001, 5000000, 5,
900000, 5200000, 1, 2200000, 5200000, 11, 300000, 900000, 8, 300002, 900000,
2, 200000, 5000000, 3, 400000, 5000000, 10, 1500000, 3700000, 12, 400000,
500000, 9, 1400000, 3700000, 3, 1800000, 5300000, 0, 1800000, 5300000, 10,
1500000, 4000000, 9, 1400000, 4100000, 11, 600000, 900001, 8, 600000, 900003,
12, 100000, 600000, 2, 400004, 5300000, 3, 2200000, 2900000, 0, 2500000,
2900000, 11, 700000, 900000, 8, 700000, 900000, 12, 100005, 200000, 10,
1500000, 1600000, 9, 1400000, 1600000, 3, 2200000, 2900000, 0, 2500000,
2900000, 11, 800000, 900000, 8, 800000, 900000, 12, 100005, 200000, 10,
1500000, 1600000, 9, 1400000, 1600000, 3, 1600000, 4800000, 0, 1800000,
4800000, 10, 1500000, 3500000, 9, 1400000, 3500000, 12, 100000, 500000, 5,
1500000, 3400000, 1, 1500000, 3400000, 3, 2900000, 3300000, 0, 2900000,
3300000, 10, 1600000, 2000000, 9, 1600000, 2000000, 11, 600000, 900001, 8,
600000, 1200000, 12, 100000, 200000, 5, 400000, 3400000, 1, 400000, 3400000,
3, 3100000, 3400000, 0, 3100000, 3400000, 10, 1800000, 2100000, 9, 1800000,
2100000, 11, 700000, 900001, 8, 700000, 900003, 2, 400004, 3700000, 4,
1200000, 7900000, 6, 1000000, 1e15, 7, 1000000, 1e15, 3, 600000, 10600000, 0,
1800000, 10600000, 4, 7900000, 10600000, 10, 1500000, 9200000, 9, 1400000,
7200000, 11, 500001, 1700000, 8, 500000, 1700000, 12, 100000, 2000000, 2,
400004, 10600000, 3, 1300000, 5500000, 0, 1800000, 5500000, 10, 1500000,
4200000, 9, 1400000, 4200000, 11, 500001, 1700000, 8, 400002, 1700000, 12,
100000, 600000, 2, 400004, 5500000, 5, 600000, 4300000, 1, 600000, 4300000, 4,
1200000, 7900000, 11, 900000, 1e15, 8, 900000, 1e15, 3, 100000, 5800000, 0,
1800000, 5800000, 10, 1500000, 4500000, 9, 1400000, 4300000, 11, 300000,
1100000, 8, 100000, 1100000, 12, 100000, 700000, 2, 400004, 5800000, 3,
600000, 1e15, 0, 1800000, 1e15, 4, 7900000, 1e15, 5, 6800000, 1e15, 1,
6800000, 1e15, 10, 1500000, 1e15, 9, 1400000, 1e15, 11, 500000, 1e15, 8,
400002, 1e15, 12, 100000, 1e15, 2, 400004, 1e15, 3, 800000, 6900000, 0,
1800000, 6900000, 10, 1500000, 5600000, 9, 1400000, 4800000, 11, 500001,
1200001, 8, 500000, 1200002, 12, 100000, 1000000, 2, 400004, 6900000, 3,
200000, 6900000, 0, 1800000, 6900000, 10, 1500000, 5600000, 9, 1400000,
4800000, 11, 300000, 1200001, 8, 300000, 1200002, 12, 100000, 1000000, 2,
200000, 8700000, 3, 100000, 12000000, 0, 1800000, 12000000, 4, 7900000,
12000000, 10, 1500000, 10600000, 9, 1400000, 8000000, 11, 300001, 1500004, 8,
200000, 1500004, 12, 100000, 2500000, 2, 200000, 12000000, 3, 100000, 1e15, 0,
1800000, 1e15, 4, 7900000, 1e15, 10, 1500000, 1e15, 9, 1400000, 1e15, 11,
300001, 1700002, 8, 200000, 1700002, 12, 100000, 1e15, 2, 400004, 1e15, 3,
100000, 12000000, 0, 1800000, 12000000, 4, 7900000, 12000000, 10, 1500000,
10600000, 9, 1400000, 8000000, 11, 400000, 1500004, 8, 300002, 1500004, 12,
100000, 2500000, 2, 200000, 12000000, 3, 100000, 12000000, 0, 1800000,
12000000, 4, 7900000, 12000000, 10, 1500000, 1e15, 9, 1400000, 8000000, 11,
400000, 1500004, 8, 300002, 1500004, 12, 100000, 2500000, 2, 200000, 12000000,
3, 400000, 12000000, 0, 1800000, 12000000, 4, 7900000, 12000000, 10, 1500000,
10600000, 9, 1400000, 8000000, 11, 400000, 1500004, 8, 200000, 1500004, 12,
100000, 2500000, 2, 400004, 12000000, 10, 1000006, 1500000, 9, 1100000,
1400000, 5, 100000, 300006, 5, 100000, 100005, 3, 1200000, 3600000, 0,
1800000, 3600000, 10, 1500000, 2300000, 9, 1400000, 2400000, 11, 400000,
900000, 8, 200000, 900000, 12, 100000, 300000, 2, 300000, 400004, 3, 1700000,
13600000, 0, 1800000, 13600000, 4, 7900000, 13600000, 10, 1500000, 12100000,
9, 1400000, 9000000, 11, 600000, 1500004, 8, 600000, 1500004, 12, 100000,
2900000, 2, 400004, 13600000, 3, 100000, 8400000, 0, 1800000, 8400000, 4,
7900000, 8400000, 10, 1500000, 7000000, 9, 1400000, 6000000, 11, 700000,
1800002, 8, 700000, 1800002, 2, 400004, 8400000, 11, 900000, 1100000, 8,
900000, 1100000, 11, 700001, 1000001, 8, 800000, 1000003, 5, 400000, 9100000,
1, 400000, 9100000, 5, 1200000, 4900000, 1, 1400000, 4900000, 4, 1200000,
7900000, 6, 1100000, 1e15, 7, 1100000, 1e15, 5, 600000, 3600000, 1, 600000,
3600000, 11, 800000, 1200001, 8, 800000, 1200002, 11, 700000, 1200001, 8,
700000, 1200002, 3, 2500000, 9900000, 0, 2500000, 9900000, 4, 7900000,
9900000, 10, 1500000, 8500000, 9, 1400000, 6800000, 12, 100005, 1800000, 2,
400004, 9900000, 3, 1200000, 4800000, 0, 1800000, 4800000, 10, 1500000,
3500000, 9, 1400000, 3500000, 11, 500001, 1400000, 8, 500000, 1400000, 12,
100000, 500000, 2, 400004, 4800000, 10, 900000, 1100000, 9, 1000000, 1200001,
4, 1200000, 7900000, 8, 100000, 1e15, 1, 1400000, 1e15, 5, 1400000, 1e15, 7,
1000000, 1200000, 4, 1200000, 1900000, 11, 900000, 1200001, 8, 900000,
1200002, 3, 100000, 3600000, 0, 1800000, 3600000, 10, 1500000, 2300000, 9,
1400000, 2400000, 11, 300001, 900000, 8, 300002, 900000, 12, 100000, 300000,
2, 200000, 400004, 5, 300005, 1600000, 1, 400000, 1600000, 6, 900000, 1000000,
7, 900000, 1000000, 3, 100000, 3600000, 0, 1800000, 3600000, 10, 1500000,
2300000, 9, 1400000, 2400000, 11, 200000, 900000, 8, 100000, 900000, 12,
100000, 300000, 2, 400004, 3700000, 3, 100000, 2600000, 0, 1800000, 2600000,
11, 300001, 900000, 8, 200000, 900000, 12, 100000, 100005, 2, 200000, 400004,
5, 400000, 1600000, 1, 400000, 1600000, 10, 1000001, 1200001, 9, 1000001,
1200001, 3, 100000, 2600000, 0, 1800000, 2600000, 11, 400000, 900000, 8,
200000, 900000, 12, 100000, 100005, 2, 200000, 400004, 10, 1100006, 1200001,
9, 1200000, 1200001, 10, 1000000, 1200001, 9, 1000001, 1200001, 3, 100000,
2600000, 0, 1800000, 2600000, 11, 300001, 900000, 8, 200000, 900000, 12,
100000, 100005, 3, 100000, 1e15, 0, 1800000, 1e15, 4, 1200000, 1e15, 10,
1500000, 1e15, 9, 1400000, 1e15, 11, 300000, 1e15, 8, 500000, 1e15, 12,
100000, 1e15, 2, 3700000, 1e15, 5, 100000, 13200000, 1, 400000, 13200000, 3,
100000, 5400000, 0, 1800000, 5400000, 4, 1200000, 7900000, 10, 1500000,
4100000, 9, 1400000, 4100000, 11, 300000, 1e15, 8, 300000, 1e15, 12, 100000,
600000, 2, 400004, 5400000, 5, 100000, 6900000, 1, 400000, 7900000, 3, 800000,
4800000, 0, 1800000, 4800000, 10, 1500000, 3500000, 9, 1400000, 3500000, 11,
500001, 1000001, 8, 500000, 1000003, 12, 100000, 500000, 2, 300000, 4800000,
3, 100000, 6500000, 0, 1800000, 6500000, 10, 1500000, 5200000, 9, 1400000,
4700000, 11, 300000, 900000, 8, 100000, 900000, 12, 100000, 900000, 2, 400004,
6500000, 5, 100000, 5000000, 1, 400000, 5000000, 3, 100000, 11000000, 0,
1800000, 11000000, 4, 7900000, 11000000, 10, 1500000, 9600000, 9, 1400000,
7400000, 11, 300000, 1500000, 8, 100000, 1500000, 12, 100000, 2100000, 2,
400004, 11000000, 3, 3200000, 3700000, 0, 3200000, 3700000, 10, 1900000,
2400000, 9, 1900000, 2400000, 12, 200000, 300000, 2, 400004, 3700000, 5,
1700000, 4900000, 1, 1700000, 4900000, 3, 100000, 8900000, 0, 1800000,
8900000, 4, 7900000, 8900000, 10, 1500000, 7500000, 9, 1400000, 6300000, 11,
300000, 1400001, 8, 100000, 1400005, 12, 100000, 1500000, 2, 400004, 8900000,
5, 400000, 8500000, 1, 400000, 8500000, 3, 1500000, 7100000, 0, 1800000,
7100000, 10, 1500000, 5800000, 9, 1400000, 5000000, 11, 600000, 1600004, 8,
1200000, 1600004, 12, 100000, 1000000, 2, 3700000, 7100000, 5, 900000,
6400000, 1, 900000, 6400000, 6, 1100000, 1e15, 7, 1100000, 1e15, 3, 1200000,
8800000, 0, 1800000, 8800000, 4, 7900000, 8800000, 10, 1500000, 7400000, 9,
1400000, 6300000, 11, 500000, 1400000, 8, 500000, 1400000, 12, 100000,
1500000, 2, 400004, 8800000, 5, 400000, 7800000, 1, 400000, 7900000, 3,
600000, 5700000, 0, 1800000, 5700000, 4, 1200000, 7900000, 10, 1500000,
4400000, 9, 1400000, 4300000, 11, 500000, 1000001, 8, 400002, 1000003, 12,
100000, 700000, 2, 200000, 5700000, 5, 1900000, 5100000, 1, 1900000, 5100000,
5, 100005, 7800000, 1, 400000, 7900000, 5, 100000, 6200000, 1, 400000,
6200000, 5, 400000, 8800000, 1, 400000, 8800000, 5, 100005, 1e15, 1, 400000,
1e15, 3, 100000, 4300000, 0, 1800000, 4300000, 10, 1500000, 3000000, 9,
1400000, 3000000, 11, 400000, 900000, 8, 400000, 900000, 12, 100000, 400000,
2, 400004, 4300000, 5, 300000, 9400000, 1, 400000, 9400000, 11, 700000,
1100000, 8, 700000, 1100000, 3, 2200000, 4600000, 0, 2500000, 4600000, 12,
100005, 500000, 2, 400004, 4600000, 10, 1500000, 3300000, 9, 1400000, 3300000,
5, 300000, 6600000, 1, 400000, 6600000, 11, 900000, 1100000, 8, 900000,
1100000, 3, 2200000, 4600000, 0, 2500000, 4600000, 10, 1500000, 3300000, 9,
1400000, 3300000, 12, 100005, 500000, 2, 400004, 4600000, 11, 900000, 1100000,
8, 900000, 1100000, 3, 2500000, 4600000, 0, 2500000, 4600000, 10, 1500000,
3300000, 9, 1400000, 3300000, 12, 100005, 500000, 2, 400004, 4600000, 3,
100000, 6800000, 0, 1800000, 6800000, 10, 1500000, 5500000, 9, 1400000,
4800000, 11, 400000, 1100000, 12, 100000, 1000000, 2, 400004, 6800000, 5,
100005, 2700000, 3, 100000, 6800000, 0, 1800000, 6800000, 10, 1500000,
5500000, 9, 1400000, 4800000, 12, 100000, 1000000, 2, 400004, 6800000, 3,
100000, 3700000, 0, 1800000, 3700000, 10, 1500000, 2300000, 9, 1400000,
2400000, 11, 300000, 900000, 12, 100000, 300000, 2, 400004, 3700000, 5,
100000, 2400000, 6, 800000, 1100000, 7, 800000, 1100000, 5, 2200000, 9400000,
1, 2200000, 9400000, 5, 2200000, 6600000, 1, 2200000, 6600000, 3, 1300000,
14800000, 0, 1800000, 14800000, 4, 7900000, 14800000, 10, 1500000, 13200000,
9, 1400000, 9900000, 11, 600000, 700000, 8, 600000, 700000, 12, 100000, 1e15,
2, 400004, 14800000, 5, 300006, 6500000, 1, 400000, 6500000, 3, 2500000,
4600000, 0, 2500000, 4600000, 11, 700000, 1100000, 8, 700000, 1100000, 12,
100005, 500000, 2, 400004, 4600000, 11, 700000, 1100000, 8, 700000, 1100000,
3, 2200000, 4600000, 0, 2500000, 4600000, 12, 100005, 500000, 2, 400004,
4600000, 11, 700000, 1100000, 8, 700000, 1100000, 3, 2500000, 4600000, 0,
2500000, 4600000, 12, 100005, 500000, 2, 400004, 4600000, 5, 100005, 8100000,
1, 400000, 8100000, 11, 700000, 1300000, 8, 700000, 1300000, 3, 1600000, 1e15,
0, 1800000, 1e15, 4, 7900000, 1e15, 10, 1500000, 1e15, 9, 1400000, 1e15, 12,
100000, 1e15, 3, 1600000, 4800000, 10, 1500000, 3500000, 11, 600000, 1100000,
8, 600000, 1100000, 5, 1000000, 5000000, 1, 1000000, 5000000, 5, 1700000,
5000000, 1, 1700000, 5000000, 11, 700000, 1100000, 8, 700000, 1100000, 3,
1600000, 4800000, 10, 1500000, 3500000, 11, 600000, 1100000, 8, 600000,
1100000, 3, 1600000, 4800000, 10, 1500000, 3500000, 5, 100000, 300000
]);
// Where each window list begins; the entry after it is where it ends.
const PREFIX_WINDOW_STARTS = new Int32Array([
0, 21, 27, 48, 54, 78, 84, 90, 114, 138, 162, 186, 213, 219, 228, 252, 258,
261, 267, 276, 279, 282, 306, 315, 327, 333, 339, 345, 357, 384, 390, 417,
441, 450, 453, 465, 471, 495, 519, 525, 531, 537, 558, 561, 585, 591, 615,
621, 642, 666, 687, 708, 723, 729, 750, 756, 777, 786, 813, 837, 843, 846,
852, 876, 909, 933, 957, 984, 1011, 1038, 1065, 1092, 1098, 1101, 1104, 1128,
1155, 1179, 1185, 1191, 1197, 1203, 1212, 1218, 1224, 1230, 1251, 1275, 1281,
1287, 1293, 1299, 1305, 1329, 1335, 1341, 1365, 1383, 1389, 1395, 1413, 1419,
1425, 1440, 1467, 1473, 1500, 1506, 1530, 1554, 1560, 1587, 1605, 1611, 1638,
1644, 1668, 1674, 1680, 1707, 1713, 1740, 1746, 1752, 1758, 1764, 1770, 1794,
1800, 1824, 1830, 1854, 1878, 1899, 1902, 1920, 1941, 1944, 1950, 1956, 1962,
1989, 1995, 2013, 2031, 2049, 2055, 2061, 2079, 2091, 2097, 2103, 2115, 2127,
2130
]);
/** @type {Map<string, [string, number][]>} */
const PREFIXED_PROPERTIES = new Map([
[
"align-content",
[
["-webkit-align-content", 0],
["-ms-flex-line-pack", 1]
]
],
[
"align-items",
[
["-webkit-align-items", 0],
["-ms-flex-align", 1]
]
],
[
"align-self",
[
["-webkit-align-self", 2],
["-ms-flex-item-align", 1]
]
],
["alt", [["-webkit-alt", 3]]],
[
"animation",
[
["-webkit-animation", 4],
["-moz-animation", 5],
["-o-animation", 6]
]
],
[
"animation-delay",
[
["-webkit-animation-delay", 7],
["-moz-animation-delay", 5],
["-o-animation-delay", 6]
]
],
[
"animation-direction",
[
["-webkit-animation-direction", 7],
["-moz-animation-direction", 5],
["-o-animation-direction", 6]
]
],
[
"animation-duration",
[
["-webkit-animation-duration", 8],
["-moz-animation-duration", 5],
["-o-animation-duration", 6]
]
],
[
"animation-fill-mode",
[
["-webkit-animation-fill-mode", 9],
["-moz-animation-fill-mode", 5],
["-o-animation-fill-mode", 6]
]
],
[
"animation-iteration-count",
[
["-webkit-animation-iteration-count", 7],
["-moz-animation-iteration-count", 5],
["-o-animation-iteration-count", 6]
]
],
[
"animation-name",
[
["-webkit-animation-name", 7],
["-moz-animation-name", 5],
["-o-animation-name", 6]
]
],
[
"animation-play-state",
[
["-webkit-animation-play-state", 10],
["-moz-animation-play-state", 5],
["-o-animation-play-state", 6]
]
],
[
"animation-timing-function",
[
["-webkit-animation-timing-function", 7],
["-moz-animation-timing-function", 5],
["-o-animation-timing-function", 6]
]
],
[
"appearance",
[
["-webkit-appearance", 11],
["-moz-appearance", 12]
]
],
["backdrop-filter", [["-webkit-backdrop-filter", 13]]],
[
"backface-visibility",
[
["-webkit-backface-visibility", 14],
["-moz-backface-visibility", 15]
]
],
[
"background-clip",
[
["-moz-background-clip", 16],
["-webkit-background-clip", 17]
]
],
["background-origin", [["-moz-background-origin", 16]]],
[
"background-size",
[
["-webkit-background-size", 18],
["-moz-background-size", 19],
["-o-background-size", 20]
]
],
["block-size", [["-webkit-logical-height", 21]]],
[
"border-bottom-left-radius",
[
["-webkit-border-bottom-left-radius", 22],
["-moz-border-radius-bottomleft", 16]
]
],
[
"border-bottom-right-radius",
[
["-webkit-border-bottom-right-radius", 22],
["-moz-border-radius-bottomright", 16]
]
],
[
"border-image",
[
["-webkit-border-image", 23],
["-moz-border-image", 24],
["-o-border-image", 25]
]
],
["border-inline-end-color", [["-moz-border-end-color", 26]]],
["border-inline-end-style", [["-moz-border-end-style", 26]]],
["border-inline-end-width", [["-moz-border-end-width", 26]]],
["border-inline-start-color", [["-moz-border-start-color", 26]]],
["border-inline-start-style", [["-moz-border-start-style", 26]]],
[
"border-radius",
[
["-webkit-border-radius", 27],
["-moz-border-radius", 16]
]
],
[
"border-top-left-radius",
[
["-webkit-border-top-left-radius", 22],
["-moz-border-radius-topleft", 16]
]
],
[
"border-top-right-radius",
[
["-webkit-border-top-right-radius", 22],
["-moz-border-radius-topright", 16]
]
],
[
"box-align",
[
["-webkit-box-align", 28],
["-moz-box-align", 29]
]
],
["box-decoration-break", [["-webkit-box-decoration-break", 30]]],
[
"box-direction",
[
["-webkit-box-direction", 28],
["-moz-box-direction", 29]
]
],
[
"box-flex",
[
["-webkit-box-flex", 28],
["-moz-box-flex", 29]
]
],
["box-flex-group", [["-webkit-box-flex-group", 31]]],
["box-lines", [["-webkit-box-lines", 31]]],
[
"box-ordinal-group",
[
["-webkit-box-ordinal-group", 28],
["-moz-box-ordinal-group", 29]
]
],
[
"box-orient",
[
["-webkit-box-orient", 28],
["-moz-box-orient", 29]
]
],
[
"box-pack",
[
["-webkit-box-pack", 28],
["-moz-box-pack", 29]
]
],
[
"box-shadow",
[
["-webkit-box-shadow", 32],
["-moz-box-shadow", 33]
]
],
[
"box-sizing",
[
["-webkit-box-sizing", 34],
["-moz-box-sizing", 35]
]
],
["clip-path", [["-webkit-clip-path", 36]]],
[
"column-count",
[
["-webkit-column-count", 37],
["-moz-column-count", 38]
]
],
[
"column-fill",
[
["-moz-column-fill", 39],
["-webkit-column-fill", 40]
]
],
[
"column-gap",
[
["-webkit-column-gap", 41],
["-moz-column-gap", 42]
]
],
[
"column-rule",
[
["-webkit-column-rule", 43],
["-moz-column-rule", 44]
]
],
[
"column-rule-color",
[
["-webkit-column-rule-color", 43],
["-moz-column-rule-color", 44]
]
],
[
"column-rule-style",
[
["-webkit-column-rule-style", 43],
["-moz-column-rule-style", 44]
]
],
[
"column-rule-width",
[
["-webkit-column-rule-width", 43],
["-moz-column-rule-width", 44]
]
],
["column-span", [["-webkit-column-span", 45]]],
[
"column-width",
[
["-webkit-column-width", 43],
["-moz-column-width", 38]
]
],
[
"columns",
[
["-moz-columns", 46],
["-webkit-columns", 47]
]
],
["filter", [["-webkit-filter", 48]]],
[
"flex",
[
["-webkit-flex", 2],
["-ms-flex", 1]
]
],
[
"flex-basis",
[
["-webkit-flex-basis", 49],
["-ms-flex-preferred-size", 1]
]
],
[
"flex-direction",
[
["-webkit-flex-direction", 2],
["-ms-flex-direction", 1]
]
],
[
"flex-flow",
[
["-webkit-flex-flow", 2],
["-ms-flex-flow", 1]
]
],
[
"flex-grow",
[
["-webkit-flex-grow", 49],
["-ms-flex-positive", 1]
]
],
[
"flex-shrink",
[
["-webkit-flex-shrink", 50],
["-ms-flex-negative", 1]
]
],
[
"flex-wrap",
[
["-webkit-flex-wrap", 0],
["-ms-flex-wrap", 1]
]
],
[
"font-feature-settings",
[
["-webkit-font-feature-settings", 51],
["-moz-font-feature-settings", 52]
]
],
["font-kerning", [["-webkit-font-kerning", 53]]],
["font-language-override", [["-moz-font-language-override", 54]]],
["font-variant-ligatures", [["-webkit-font-variant-ligatures", 55]]],
["forced-color-adjust", [["-ms-high-contrast-adjust", 56]]],
["hyphenate-character", [["-webkit-hyphenate-character", 57]]],
[
"hyphens",
[
["-webkit-hyphens", 58],
["-ms-hyphens", 56],
["-moz-hyphens", 59]
]
],
["ime-mode", [["-ms-ime-mode", 60]]],
["initial-letter", [["-webkit-initial-letter", 61]]],
["inline-size", [["-webkit-logical-width", 21]]],
[
"justify-content",
[
["-webkit-justify-content", 2],
["-ms-flex-pack", 1]
]
],
["line-break", [["-webkit-line-break", 62]]],
["line-clamp", [["-webkit-line-clamp", 63]]],
["margin-block-end", [["-webkit-margin-after", 64]]],
["margin-block-start", [["-webkit-margin-before", 64]]],
[
"margin-inline-end",
[
["-webkit-margin-end", 65],
["-moz-margin-end", 26]
]
],
[
"margin-inline-start",
[
["-webkit-margin-start", 65],
["-moz-margin-start", 26]
]
],
["mask", [["-webkit-mask", 66]]],
["mask-border", [["-webkit-mask-box-image", 67]]],
["mask-border-outset", [["-webkit-mask-box-image-outset", 67]]],
["mask-border-repeat", [["-webkit-mask-box-image-repeat", 67]]],
["mask-border-slice", [["-webkit-mask-box-image-slice", 67]]],
["mask-border-source", [["-webkit-mask-box-image-source", 67]]],
["mask-border-width", [["-webkit-mask-box-image-width", 67]]],
["mask-clip", [["-webkit-mask-clip", 68]]],
["mask-image", [["-webkit-mask-image", 69]]],
["mask-origin", [["-webkit-mask-origin", 68]]],
["mask-position", [["-webkit-mask-position", 66]]],
["mask-repeat", [["-webkit-mask-repeat", 66]]],
["mask-size", [["-webkit-mask-size", 70]]],
["max-block-size", [["-webkit-max-logical-height", 21]]],
["max-inline-size", [["-webkit-max-logical-width", 21]]],
["min-block-size", [["-webkit-min-logical-height", 21]]],
["min-inline-size", [["-webkit-min-logical-width", 21]]],
["object-fit", [["-o-object-fit", 71]]],
["object-position", [["-o-object-position", 71]]],
[
"order",
[
["-webkit-order", 2],
["-ms-flex-order", 1]
]
],
["outline", [["-moz-outline", 72]]],
["outline-color", [["-moz-outline-color", 73]]],
["outline-style", [["-moz-outline-style", 73]]],
["outline-width", [["-moz-outline-width", 73]]],
[
"padding-inline-end",
[
["-webkit-padding-end", 65],
["-moz-padding-end", 26]
]
],
[
"padding-inline-start",
[
["-webkit-padding-start", 65],
["-moz-padding-start", 26]
]
],
[
"perspective",
[
["-webkit-perspective", 74],
["-moz-perspective", 15]
]
],
[
"perspective-origin",
[
["-webkit-perspective-origin", 74],
["-moz-perspective-origin", 15]
]
],
["print-color-adjust", [["-webkit-print-color-adjust", 75]]],
["ruby-position", [["-webkit-ruby-position", 76]]],
[
"scroll-snap-type",
[
["-ms-scroll-snap-type", 56],
["-webkit-scroll-snap-type", 77]
]
],
["shape-image-threshold", [["-webkit-shape-image-threshold", 78]]],
["shape-margin", [["-webkit-shape-margin", 78]]],
["shape-outside", [["-webkit-shape-outside", 78]]],
[
"tab-size",
[
["-moz-tab-size", 79],
["-o-tab-size", 25]
]
],
["text-align-last", [["-moz-text-align-last", 80]]],
["text-combine-upright", [["-ms-text-combine-horizontal", 81]]],
[
"text-decoration-color",
[
["-moz-text-decoration-color", 82],
["-webkit-text-decoration-color", 83]
]
],
[
"text-decoration-line",
[
["-moz-text-decoration-line", 82],
["-webkit-text-decoration-line", 83]
]
],
["text-decoration-skip", [["-webkit-text-decoration-skip", 84]]],
[
"text-decoration-style",
[
["-moz-text-decoration-style", 82],
["-webkit-text-decoration-style", 83]
]
],
["text-emphasis", [["-webkit-text-emphasis", 85]]],
["text-emphasis-color", [["-webkit-text-emphasis-color", 85]]],
["text-emphasis-position", [["-webkit-text-emphasis-position", 85]]],
["text-emphasis-style", [["-webkit-text-emphasis-style", 85]]],
["text-orientation", [["-webkit-text-orientation", 86]]],
["text-overflow", [["-o-text-overflow", 87]]],
[
"text-size-adjust",
[
["-webkit-text-size-adjust", 88],
["-moz-text-size-adjust", 89],
["-ms-text-size-adjust", 90]
]
],
["text-underline-position", [["-webkit-text-underline-position", 91]]],
["touch-action", [["-ms-touch-action", 1]]],
[
"transform",
[
["-webkit-transform", 92],
["-moz-transform", 93],
["-ms-transform", 94],
["-o-transform", 25]
]
],
[
"transform-origin",
[
["-webkit-transform-origin", 95],
["-moz-transform-origin", 93],
["-ms-transform-origin", 94],
["-o-transform-origin", 25]
]
],
[
"transform-style",
[
["-webkit-transform-style", 74],
["-moz-transform-style", 15]
]
],
[
"transition",
[
["-webkit-transition", 96],
["-moz-transition", 97],
["-o-transition", 98]
]
],
[
"transition-delay",
[
["-webkit-transition-delay", 99],
["-moz-transition-delay", 97],
["-o-transition-delay", 100]
]
],
[
"transition-duration",
[
["-webkit-transition-duration", 96],
["-moz-transition-duration", 97],
["-o-transition-duration", 101]
]
],
[
"transition-property",
[
["-webkit-transition-property", 102],
["-moz-transition-property", 97],
["-o-transition-property", 100]
]
],
[
"transition-timing-function",
[
["-webkit-transition-timing-function", 102],
["-moz-transition-timing-function", 97],
["-o-transition-timing-function", 100]
]
],
[
"user-modify",
[
["-webkit-user-modify", 103],
["-moz-user-modify", 104]
]
],
[
"user-select",
[
["-webkit-user-select", 105],
["-ms-user-select", 56],
["-moz-user-select", 106]
]
],
["writing-mode", [["-webkit-writing-mode", 107]]]
]);
/** @type {Map<string, [string, number][]>} */
const PREFIXED_SELECTORS = new Map([
[
"any-link",
[
["-webkit-any-link", 108],
["-moz-any-link", 109]
]
],
["autofill", [["-webkit-autofill", 110]]],
[
"backdrop",
[
["-webkit-backdrop", 111],
["-ms-backdrop", 81]
]
],
["dir", [["-moz-dir", 112]]],
[
"file-selector-button",
[
["-webkit-file-upload-button", 113],
["-ms-browse", 56]
]
],
["focus-visible", [["-moz-focusring", 114]]],
[
"fullscreen",
[
["-webkit-full-screen", 115],
["-moz-full-screen", 116],
["-ms-fullscreen", 117]
]
],
[
"is",
[
["-webkit-any", 118],
["-moz-any", 119]
]
],
[
"placeholder",
[
["-webkit-input-placeholder", 120],
["-ms-input-placeholder", 60],
["-moz-placeholder", 121]
]
],
["read-only", [["-moz-read-only", 122]]],
["read-write", [["-moz-read-write", 122]]],
["selection", [["-moz-selection", 123]]],
["user-invalid", [["-moz-ui-invalid", 124]]],
["user-valid", [["-moz-ui-valid", 124]]]
]);
/** @type {Map<string, [string, number][]>} */
const PREFIXED_AT_RULES = new Map([
["document", [["-moz-document", 125]]],
[
"keyframes",
[
["-webkit-keyframes", 126],
["-moz-keyframes", 5],
["-o-keyframes", 6]
]
]
]);
// The version a browser that never shipped a construct is given below, and the
// one a spelling still prefixed today is unprefixed at. Finite and a plain
// number, so both version tables hold numbers alone; far past any real version,
// and past the one Safari TP is read as.
const NEVER = 1e15;
// The browsers every support profile below covers, in the order it states them.
// A selection has an ability when every browser in it is named here and at or
// past the version its profile row gives.
/** @type {string[]} */
const SUPPORT_BROWSERS = [
"and_chr",
"and_ff",
"android",
"chrome",
"edge",
"firefox",
"ie",
"ie_mob",
"ios_saf",
"op_mob",
"opera",
"safari",
"samsung"
];
// The versions themselves, rows of `SUPPORT_BROWSERS.length` laid end to end,
// one row per distinct profile: a construct names the row it reads rather than
// carrying its own copy of it. `NEVER` is a browser that never shipped it.
const SUPPORT_PROFILES = new Float64Array([
6200000, 4900000, 6200000, 6200000, 7900000, 4900000, 1e15, 1e15, 900003,
4700000, 4900000, 1000000, 800000, 7200000, 8300000, 7200000, 7200000,
7900000, 8300000, 1e15, 1e15, 1200002, 5100000, 6000000, 1200001, 1100000,
11500000, 7900000, 11500000, 11500000, 11500000, 7000000, 1e15, 1e15, 1500000,
7700000, 10100000, 1500000, 2300000, 5600000, 9200000, 5600000, 5600000,
7900000, 9200000, 1e15, 1e15, 1100000, 4300000, 4300000, 1100000, 600000,
8800000, 7900000, 8800000, 8800000, 8800000, 7800000, 1e15, 1e15, 1400000,
6300000, 7400000, 1400000, 1500000, 1e15, 11400000, 1e15, 1e15, 1e15,
11400000, 1e15, 1e15, 900000, 1e15, 1e15, 900000, 1e15, 8800000, 8400000,
8800000, 8800000, 8800000, 8400000, 1e15, 1e15, 900000, 1e15, 7400000, 900000,
1500000, 12000000, 4900000, 12000000, 12000000, 12000000, 4900000, 1e15, 1e15,
1600004, 8000000, 10600000, 1600004, 2500000, 1e15, 1e15, 1e15, 1e15, 1e15,
1e15, 1e15, 1e15, 1e15, 1e15, 1e15, 1e15, 1e15, 12000000, 11700000, 12000000,
12000000, 12000000, 11700000, 1e15, 1e15, 1700002, 8000000, 10600000, 1700002,
2500000, 5700000, 600000, 5700000, 5700000, 7900000, 600000, 1e15, 1e15,
2600002, 4300000, 4400000, 2600002, 700000, 8700000, 7900000, 8700000,
8700000, 8700000, 7000000, 1e15, 1e15, 2600002, 6200000, 7300000, 2600002,
1400000, 11100000, 11300000, 11100000, 11100000, 11100000, 11300000, 1e15,
1e15, 1500000, 7500000, 9700000, 1500000, 2200000, 11100000, 11300000,
11100000, 11100000, 11100000, 11300000, 1e15, 1e15, 1600002, 7500000, 9700000,
1600002, 2200000, 10100000, 9600000, 10100000, 10100000, 10100000, 9600000,
1e15, 1e15, 1500000, 7000000, 8700000, 1500000, 1900000, 12300000, 12000000,
12300000, 12300000, 12300000, 12000000, 1e15, 1e15, 1700005, 8200000,
10900000, 1700005, 2700000, 11100000, 11300000, 11100000, 11100000, 11100000,
11300000, 1e15, 1e15, 1500004, 7500000, 9700000, 1500004, 2200000, 8700000,
6600000, 8700000, 8700000, 8700000, 6600000, 1e15, 1e15, 1400005, 6200000,
7300000, 1400001, 1400000, 10400000, 10200000, 10400000, 10400000, 10400000,
10200000, 1e15, 1e15, 1600004, 7100000, 9000000, 1600004, 2000000, 6800000,
6100000, 6800000, 6800000, 7900000, 6100000, 1e15, 1e15, 1300004, 4800000,
5500000, 1300001, 1000000, 5900000, 4500000, 5900000, 5900000, 7900000,
4500000, 1e15, 1e15, 1100000, 4300000, 4600000, 1100000, 700000, 1800000,
400000, 400004, 100000, 1200000, 100005, 900000, 900000, 300002, 1000001,
700000, 400000, 100000, 3700000, 4700000, 3700000, 3700000, 7900000, 4700000,
1e15, 1e15, 1500004, 2400000, 2400000, 1500004, 300000, 1800000, 400000,
400004, 100000, 1200000, 100005, 900000, 900000, 300000, 1000001, 700000,
400000, 100000, 13300000, 1e15, 13300000, 13300000, 13300000, 1e15, 1e15,
1e15, 2700000, 8800000, 11800000, 2700000, 2900000, 2600000, 5500000, 400004,
2600000, 7900000, 5500000, 1e15, 1e15, 700000, 1400000, 1500000, 700000,
100005, 13100000, 14300000, 13100000, 13100000, 13100000, 14300000, 1e15,
1e15, 1800004, 8700000, 11600000, 1800004, 2900000, 8900000, 8200000, 8900000,
8900000, 8900000, 8200000, 1e15, 1e15, 1400005, 6300000, 7500000, 1400001,
1500000, 1800000, 400000, 3700000, 100000, 1200000, 100000, 900000, 900000,
100000, 1000001, 700000, 100000, 100000, 1800000, 400000, 400004, 100000,
1200000, 100000, 900000, 900000, 100000, 1000001, 700000, 100000, 100000,
12100000, 1e15, 12100000, 12100000, 12100000, 1e15, 1e15, 1e15, 1700004,
8100000, 10700000, 1700004, 2500000, 10500000, 14900000, 10500000, 10500000,
10500000, 14900000, 1e15, 1e15, 1700002, 7200000, 9100000, 1700002, 2000000,
8600000, 6800000, 8600000, 8600000, 8600000, 6800000, 1e15, 1e15, 1100003,
6100000, 7200000, 1100001, 1400000, 7300000, 7900000, 7300000, 7300000,
7900000, 7200000, 1e15, 1e15, 1300004, 5200000, 6000000, 1300001, 1100000,
13500000, 1e15, 13500000, 13500000, 13500000, 1e15, 1e15, 1e15, 2700000,
8900000, 12000000, 2700000, 2900000, 5700000, 5100000, 5700000, 5700000,
7900000, 5100000, 1e15, 1e15, 1000003, 4300000, 4400000, 1000001, 700000,
1800000, 6200000, 3700000, 100000, 1200000, 6200000, 900000, 900000, 1e15,
1400000, 900005, 100001, 100000, 5000000, 6300000, 5000000, 5000000, 7900000,
6300000, 1e15, 1e15, 1000000, 3700000, 3700000, 1000000, 500000, 8900000,
13100000, 8900000, 8900000, 8900000, 13100000, 1e15, 1e15, 1800002, 6300000,
7500000, 1800002, 1500000, 10900000, 14400000, 10900000, 10900000, 10900000,
14400000, 1e15, 1e15, 1800000, 7400000, 9500000, 1800000, 2100000, 1800000,
400000, 400004, 100000, 1200000, 100000, 400000, 400000, 100000, 1000001,
500000, 100000, 100000, 12500000, 14400000, 12500000, 12500000, 12500000,
14400000, 1e15, 1e15, 1800000, 8300000, 11100000, 1800000, 2700000, 12500000,
14700000, 12500000, 12500000, 12500000, 14700000, 1e15, 1e15, 1800002,
8300000, 11100000, 1800002, 2700000, 6500000, 5000000, 6500000, 6500000,
7900000, 5000000, 1e15, 1e15, 900000, 4700000, 5200000, 900000, 900000,
11000000, 8600000, 11000000, 11000000, 11000000, 8600000, 1e15, 1e15, 1500000,
7400000, 9600000, 1500000, 2100000, 15200000, 15000000, 15200000, 15200000,
15200000, 15000000, 1e15, 1e15, 1500004, 1e15, 13600000, 1500004, 1e15,
1800000, 400000, 200000, 100000, 1200000, 100000, 900000, 900000, 200000,
1000001, 900000, 300001, 100000, 1800000, 400000, 3700000, 1000000, 7900000,
400000, 1e15, 1e15, 500000, 1000001, 1000000, 500000, 100000, 5400000,
6300000, 5400000, 5400000, 7900000, 6300000, 1e15, 1e15, 1000000, 4100000,
4100000, 1000000, 600000, 1800000, 400000, 200000, 100000, 1200000, 100000,
900000, 900000, 200000, 1000001, 900005, 300001, 100000, 1800000, 11600000,
400004, 1800000, 1200000, 11600000, 800000, 800000, 600000, 1000001, 900002,
600000, 100000, 1800000, 400000, 400004, 400000, 1200000, 300000, 700000,
700000, 400000, 1000001, 900005, 300001, 100000, 1800000, 400000, 200000,
100000, 1200000, 300005, 900000, 900000, 200000, 1000001, 900005, 300001,
100000, 1800000, 400000, 400004, 100000, 1200000, 100000, 800000, 800000,
100000, 1000001, 700000, 100000, 100000, 8600000, 8500000, 8600000, 8600000,
8600000, 8500000, 1e15, 1e15, 1500004, 6100000, 7200000, 1500004, 1400000,
6000000, 5200000, 6000000, 6000000, 7900000, 5200000, 1e15, 1e15, 1000003,
4400000, 4700000, 1000001, 800000, 7100000, 6400000, 7100000, 7100000,
1200000, 6400000, 1e15, 1e15, 1600004, 5000000, 5800000, 1600004, 1000000,
2500000, 1e15, 400004, 2300000, 7900000, 1e15, 1e15, 1e15, 700000, 1400000,
1500000, 700000, 100005, 10500000, 12100000, 10500000, 10500000, 10500000,
12100000, 1e15, 1e15, 1500004, 7200000, 9100000, 1500004, 2000000, 1e15,
13600000, 1e15, 1e15, 1e15, 13600000, 1e15, 1e15, 1e15, 1e15, 1e15, 1e15,
1e15, 5400000, 1e15, 5400000, 5400000, 7900000, 1e15, 1e15, 1e15, 1e15,
4100000, 4100000, 1e15, 600000, 1800000, 400000, 400004, 100000, 1200000,
100000, 400000, 400000, 100000, 1000001, 400000, 200000, 100000, 1800000,
1600000, 200002, 1000000, 1300000, 2900000, 1e15, 1e15, 500000, 1100000,
1100000, 500001, 100000, 1800000, 400000, 400004, 100000, 1200000, 200000,
1000000, 1000000, 100000, 1000001, 900000, 300000, 100000, 1800000, 400000,
3700000, 1000000, 1200000, 400000, 1000000, 1000000, 500000, 1000001, 1000000,
500000, 100000, 1800000, 400000, 400004, 100000, 1200000, 100000, 800000,
800000, 200000, 1000001, 800000, 300001, 100000, 1800000, 400000, 400004,
100000, 1200000, 100000, 900000, 900000, 200000, 1000001, 900005, 300001,
100000, 1800000, 1e15, 400004, 600000, 1200000, 1e15, 800000, 800000, 400002,
1000001, 900002, 500000, 100000, 1800000, 400000, 100005, 100000, 1200000,
100000, 300000, 300000, 300002, 1400000, 300005, 100000, 100000, 10500000,
10300000, 10500000, 10500000, 10500000, 10300000, 1e15, 1e15, 1500006,
7200000, 9100000, 1500006, 2000000, 1800000, 400000, 400004, 100000, 1200000,
300005, 900000, 900000, 200000, 1000001, 900005, 300001, 100000, 1800000,
400000, 400004, 400000, 1200000, 300005, 900000, 900000, 200000, 1000001,
900000, 300001, 100000, 1800000, 400000, 200000, 400000, 1200000, 300005,
900000, 900000, 200000, 1000001, 900005, 300001, 100000, 1800000, 400000,
400004, 200000, 1200000, 100005, 900000, 900000, 200000, 1000001, 900005,
300001, 100000, 13300000, 13600000, 13300000, 13300000, 13300000, 13600000,
1e15, 1e15, 2600005, 8800000, 11800000, 2600005, 2900000, 11000000, 1e15,
11000000, 11000000, 11000000, 15300000, 1e15, 1e15, 1300004, 7400000, 9600000,
1300001, 2100000, 4700000, 5100000, 4700000, 4700000, 7900000, 5100000, 1e15,
1e15, 900000, 3400000, 3400000, 900000, 500000, 11400000, 12500000, 11400000,
11400000, 11400000, 12500000, 1e15, 1e15, 1700000, 7600000, 10000000, 1700000,
2300000, 1800000, 7900000, 400004, 100000, 1300000, 7800000, 1e15, 1e15,
300002, 1000001, 900000, 400000, 100000, 1800000, 400000, 400004, 1000000,
1200000, 400000, 1000000, 1000000, 500000, 1000001, 1000000, 500000, 100000,
1800000, 400000, 3700000, 100000, 1200000, 100000, 900000, 900000, 100000,
1400000, 900005, 100000, 100000, 2700000, 3200000, 400004, 2700000, 7900000,
3200000, 1e15, 1e15, 700000, 1500000, 1500000, 700000, 100005, 12500000,
12600000, 12500000, 12500000, 12500000, 12600000, 1e15, 1e15, 1e15, 8300000,
11100000, 1700004, 2700000, 1800000, 400000, 200000, 100000, 1200000, 100000,
900000, 900000, 200000, 1000001, 900005, 100003, 100000, 11900000, 8800000,
11900000, 11900000, 11900000, 8800000, 1e15, 1e15, 1600005, 7900000, 10500000,
1600005, 2500000, 1800000, 400000, 400004, 100000, 1200000, 100000, 400000,
400000, 100000, 1000001, 300005, 100000, 100000
]);
/** @type {Map<string, number>} */
const SUPPORTED_FROM = new Map([
["colorHexAlpha", 0],
["gradientDoublePosition", 1],
["displayTwoValues", 2],
["systemUiFont", 3],
["isSelector", 4],
["langArgumentList", 5],
["notSelectorList", 6],
["whereSelector", 4],
["dirSelector", 7],
["customMedia", 8],
["nesting", 9],
["textDecorationColorStyle", 10],
["textDecorationThickness", 11],
["colorFunction", 12],
["colorMix", 13],
["hwbColors", 14],
["lightDark", 15],
["labColors", 12],
["oklabColors", 16],
["insetShorthand", 17],
["mediaQueryRange", 18],
["overflowTwoValues", 19],
["placeShorthand", 20]
]);
// When each browser first read a pseudo-class or pseudo-element, by the spelling
// a selector carries. A pseudo missing here is one no target is known to read,
// so it never joins a selector list.
/** @type {Map<string, number>} */
const SELECTOR_SUPPORTED_FROM = new Map([
["::after", 21],
["::backdrop", 22],
["::before", 23],
["::checkmark", 24],
["::cue", 25],
["::cue", 25],
["::details-content", 26],
["::file-selector-button", 27],
["::first-letter", 28],
["::first-line", 29],
["::grammar-error", 30],
["::highlight", 31],
["::marker", 32],
["::part", 33],
["::picker", 34],
["::picker-icon", 24],
["::placeholder", 35],
["::selection", 36],
["::slotted", 37],
["::spelling-error", 30],
["::target-text", 38],
["::view-transition", 39],
["::view-transition-group", 39],
["::view-transition-image-pair", 39],
["::view-transition-new", 39],
["::view-transition-old", 39],
[":active", 40],
[":active-view-transition", 41],
[":active-view-transition-type", 42],
[":any-link", 43],
[":autofill", 44],
[":buffering", 45],
[":checked", 46],
[":default", 47],
[":defined", 48],
[":dir", 7],
[":disabled", 46],
[":empty", 49],
[":enabled", 46],
[":first", 50],
[":first-child", 51],
[":first-of-type", 52],
[":focus", 53],
[":focus-visible", 54],
[":focus-within", 55],
[":fullscreen", 56],
[":future", 57],
[":has", 58],
[":has-slotted", 59],
[":host", 48],
[":host", 48],
[":host-context", 60],
[":hover", 61],
[":in-range", 62],
[":indeterminate", 63],
[":invalid", 64],
[":is", 4],
[":lang", 65],
[":last-child", 66],
[":last-of-type", 52],
[":left", 67],
[":link", 68],
[":modal", 69],
[":muted", 45],
[":not", 49],
[":nth-child", 70],
[":nth-last-child", 71],
[":nth-last-of-type", 72],
[":nth-of-type", 52],
[":only-child", 73],
[":only-of-type", 52],
[":open", 74],
[":optional", 64],
[":out-of-range", 62],
[":past", 57],
[":paused", 45],
[":picture-in-picture", 75],
[":placeholder-shown", 76],
[":playing", 45],
[":popover-open", 77],
[":read-only", 78],
[":read-write", 78],
[":required", 79],
[":right", 67],
[":root", 80],
[":scope", 81],
[":seeking", 45],
[":stalled", 45],
[":state", 82],
[":target", 83],
[":user-invalid", 84],
[":user-valid", 84],
[":valid", 64],
[":visited", 85],
[":volume-locked", 45],
[":where", 4]
]);
// The vendor spellings of a property's own keyword values, as `property ->
// keyword -> [spelling, [browserslistBrowser, from, to][]][]` — `display:flex`
// was `display:-webkit-flex`, and `width:max-content` `width:-moz-max-content`.
// Only keywords the property's syntax names are here, so a function whose older
// spelling read its arguments differently is not.
/** @type {Map<string, Map<string, [string, number][]>>} */
const PREFIXED_VALUES = new Map([
[
"block-size",
new Map([
[
"fit-content",
[
["-moz-fit-content", 127],
["-webkit-fit-content", 128]
]
],
[
"max-content",
[
["-moz-max-content", 129],
["-webkit-max-content", 130]
]
],
[
"min-content",
[
["-moz-min-content", 129],
["-webkit-min-content", 131]
]
]
])
],
[
"cursor",
new Map([
[
"grab",
[
["-webkit-grab", 132],
["-moz-grab", 133]
]
],
["grabbing", [["-webkit-grabbing", 134]]],
[
"zoom-in",
[
["-webkit-zoom-in", 135],
["-moz-zoom-in", 136]
]
],
[
"zoom-out",
[
["-webkit-zoom-out", 135],
["-moz-zoom-out", 136]
]
]
])
],
[
"display",
new Map([
[
"flex",
[
["-webkit-flex", 0],
["-ms-flexbox", 137]
]
],
[
"inline-flex",
[
["-webkit-inline-flex", 0],
["-ms-inline-flexbox", 137]
]
]
])
],
[
"flex-basis",
new Map([
["fit-content", [["-moz-fit-content", 138]]],
["max-content", [["-moz-max-content", 139]]],
["min-content", [["-moz-min-content", 139]]]
])
],
[
"height",
new Map([
[
"fit-content",
[
["-moz-fit-content", 127],
["-webkit-fit-content", 128]
]
],
[
"max-content",
[
["-moz-max-content", 129],
["-webkit-max-content", 130]
]
],
[
"min-content",
[
["-moz-min-content", 129],
["-webkit-min-content", 131]
]
]
])
],
[
"image-rendering",
new Map([
[
"crisp-edges",
[
["-webkit-optimize-contrast", 140],
["-moz-crisp-edges", 141]
]
]
])
],
[
"inline-size",
new Map([
[
"fit-content",
[
["-moz-fit-content", 127],
["-webkit-fit-content", 128]
]
],
[
"max-content",
[
["-moz-max-content", 129],
["-webkit-max-content", 130]
]
],
[
"min-content",
[
["-moz-min-content", 129],
["-webkit-min-content", 131]
]
]
])
],
[
"max-block-size",
new Map([
[
"fit-content",
[
["-webkit-fit-content", 142],
["-moz-fit-content", 127]
]
],
[
"max-content",
[
["-moz-max-content", 129],
["-webkit-max-content", 143]
]
],
[
"min-content",
[
["-moz-min-content", 129],
["-webkit-min-content", 144]
]
]
])
],
[
"max-height",
new Map([
[
"fit-content",
[
["-webkit-fit-content", 142],
["-moz-fit-content", 127]
]
],
[
"max-content",
[
["-moz-max-content", 129],
["-webkit-max-content", 143]
]
],
[
"min-content",
[
["-moz-min-content", 129],
["-webkit-min-content", 144]
]
]
])
],
[
"max-inline-size",
new Map([
[
"fit-content",
[
["-webkit-fit-content", 142],
["-moz-fit-content", 127]
]
],
[
"max-content",
[
["-moz-max-content", 129],
["-webkit-max-content", 143]
]
],
[
"min-content",
[
["-moz-min-content", 129],
["-webkit-min-content", 144]
]
]
])
],
[
"max-width",
new Map([
[
"fit-content",
[
["-webkit-fit-content", 142],
["-moz-fit-content", 127]
]
],
[
"max-content",
[
["-moz-max-content", 129],
["-webkit-max-content", 143]
]
],
[
"min-content",
[
["-moz-min-content", 129],
["-webkit-min-content", 144]
]
]
])
],
[
"min-block-size",
new Map([
[
"fit-content",
[
["-moz-fit-content", 127],
["-webkit-fit-content", 128]
]
],
[
"max-content",
[
["-moz-max-content", 129],
["-webkit-max-content", 130]
]
],
[
"min-content",
[
["-moz-min-content", 129],
["-webkit-min-content", 131]
]
]
])
],
[
"min-height",
new Map([
[
"fit-content",
[
["-moz-fit-content", 127],
["-webkit-fit-content", 128]
]
],
[
"max-content",
[
["-moz-max-content", 129],
["-webkit-max-content", 130]
]
],
[
"min-content",
[
["-moz-min-content", 129],
["-webkit-min-content", 131]
]
]
])
],
[
"min-inline-size",
new Map([
[
"fit-content",
[
["-moz-fit-content", 127],
["-webkit-fit-content", 128]
]
],
[
"max-content",
[
["-moz-max-content", 129],
["-webkit-max-content", 130]
]
],
[
"min-content",
[
["-moz-min-content", 129],
["-webkit-min-content", 131]
]
]
])
],
[
"min-width",
new Map([
[
"fit-content",
[
["-moz-fit-content", 127],
["-webkit-fit-content", 128]
]
],
[
"max-content",
[
["-moz-max-content", 129],
["-webkit-max-content", 130]
]
],
[
"min-content",
[
["-moz-min-content", 129],
["-webkit-min-content", 131]
]
]
])
],
["overflow", new Map([["clip", [["-moz-hidden-unscrollable", 145]]]])],
["overflow-block", new Map([["clip", [["-moz-hidden-unscrollable", 145]]]])],
["overflow-inline", new Map([["clip", [["-moz-hidden-unscrollable", 145]]]])],
["overflow-x", new Map([["clip", [["-moz-hidden-unscrollable", 145]]]])],
["overflow-y", new Map([["clip", [["-moz-hidden-unscrollable", 145]]]])],
["position", new Map([["sticky", [["-webkit-sticky", 146]]]])],
["text-align", new Map([["match-parent", [["-webkit-match-parent", 147]]]])],
[
"unicode-bidi",
new Map([
[
"isolate",
[
["-webkit-isolate", 148],
["-moz-isolate", 149]
]
],
[
"isolate-override",
[
["-moz-isolate-override", 150],
["-webkit-isolate-override", 151]
]
],
[
"plaintext",
[
["-moz-plaintext", 149],
["-webkit-plaintext", 152]
]
]
])
],
["white-space", new Map([["pre-wrap", [["-moz-pre-wrap", 153]]]])],
[
"width",
new Map([
[
"fit-content",
[
["-moz-fit-content", 127],
["-webkit-fit-content", 128]
]
],
[
"max-content",
[
["-moz-max-content", 129],
["-webkit-max-content", 130]
]
],
[
"min-content",
[
["-moz-min-content", 129],
["-webkit-min-content", 131]
]
]
])
]
]);
// The keywords a vendor spelling reads in place of the standard ones, as
// `spelling -> standard -> legacy` — IE 10's `-ms-flex-pack` reads
// `space-around` as `distribute`. Each map is the older property's whole
// grammar, so a value naming anything it does not is one that property cannot
// read and no copy is written.
/** @type {Map<string, Map<string, string>>} */
const PREFIXED_SPELLING_KEYWORDS = new Map([
[
"-ms-flex-align",
new Map([
["flex-start", "start"],
["flex-end", "end"],
["center", "center"],
["baseline", "baseline"],
["stretch", "stretch"]
])
],
[
"-ms-flex-item-align",
new Map([
["auto", "auto"],
["flex-start", "start"],
["flex-end", "end"],
["center", "center"],
["baseline", "baseline"],
["stretch", "stretch"]
])
],
[
"-ms-flex-line-pack",
new Map([
["flex-start", "start"],
["flex-end", "end"],
["center", "center"],
["space-between", "justify"],
["space-around", "distribute"],
["stretch", "stretch"]
])
],
[
"-ms-flex-pack",
new Map([
["flex-start", "start"],
["flex-end", "end"],
["center", "center"],
["space-between", "justify"],
["space-around", "distribute"]
])
],
[
"-webkit-ruby-position",
new Map([
["over", "before"],
["under", "after"]
])
],
[
"-webkit-text-orientation",
new Map([
["mixed", "vertical-right"],
["upright", "upright"],
["sideways", "sideways"]
])
]
]);
module.exports.ABSOLUTE_UNIT_SCALE = ABSOLUTE_UNIT_SCALE;
module.exports.ALPHA_VALUE_PROPERTIES = ALPHA_VALUE_PROPERTIES;
module.exports.ANGLE_UNITS = ANGLE_UNITS;
module.exports.ARC_COSINE_DEGREES = ARC_COSINE_DEGREES;
module.exports.ARC_SINE_DEGREES = ARC_SINE_DEGREES;
module.exports.ARC_TANGENT_DEGREES = ARC_TANGENT_DEGREES;
module.exports.AUTO_SECOND_VALUE_PROPERTIES = AUTO_SECOND_VALUE_PROPERTIES;
module.exports.BOX_FAMILY_PREFIX = BOX_FAMILY_PREFIX;
module.exports.BOX_LONGHANDS = BOX_LONGHANDS;
module.exports.BOX_SHORTHANDS = BOX_SHORTHANDS;
module.exports.CALC_CONSTANTS = CALC_CONSTANTS;
module.exports.CALC_REJECTING_PROPERTIES = CALC_REJECTING_PROPERTIES;
module.exports.CANONICAL_NAMES = CANONICAL_NAMES;
module.exports.CLAMPED_VALUE_RANGES = CLAMPED_VALUE_RANGES;
module.exports.COLOR_ARGUMENT_FUNCTIONS = COLOR_ARGUMENT_FUNCTIONS;
module.exports.COLOR_FUNCTIONS = COLOR_FUNCTIONS;
module.exports.COLOR_KEYWORDS = COLOR_KEYWORDS;
module.exports.COLOR_NAME_TO_RGB = COLOR_NAME_TO_RGB;
module.exports.COLOR_NAME_TO_SHORTEST = COLOR_NAME_TO_SHORTEST;
module.exports.COLOR_ONLY_PROPERTIES = COLOR_ONLY_PROPERTIES;
module.exports.COLOR_SPACE_MODEL = COLOR_SPACE_MODEL;
module.exports.COMPOUND_CONTINUATIONS = COMPOUND_CONTINUATIONS;
module.exports.CSS_MODULES_KEYWORDS = CSS_MODULES_KEYWORDS;
module.exports.CSS_MODULES_KEYWORD_OPTIONS = CSS_MODULES_KEYWORD_OPTIONS;
module.exports.CSS_WIDE_KEYWORDS = CSS_WIDE_KEYWORDS;
module.exports.CUBIC_BEZIER_KEYWORDS = CUBIC_BEZIER_KEYWORDS;
module.exports.CUSTOM_IDENT_LIST_PROPERTIES = CUSTOM_IDENT_LIST_PROPERTIES;
module.exports.DEFAULT_GRADIENT_DIRECTIONS = DEFAULT_GRADIENT_DIRECTIONS;
module.exports.DISPLAY_SHORT_FORMS = DISPLAY_SHORT_FORMS;
module.exports.DROPPABLE_WHEN_EMPTY_AT_RULES = DROPPABLE_WHEN_EMPTY_AT_RULES;
module.exports.EASING_KEYWORDS = EASING_KEYWORDS;
module.exports.EIGHTH_TURN_COSINE = EIGHTH_TURN_COSINE;
module.exports.EIGHTH_TURN_SINE = EIGHTH_TURN_SINE;
module.exports.EIGHTH_TURN_TANGENT = EIGHTH_TURN_TANGENT;
module.exports.ENCODED_ALREADY = ENCODED_ALREADY;
module.exports.ENGINE_TRANSFER_DIFFERS = ENGINE_TRANSFER_DIFFERS;
module.exports.FAMILY_LIST_PROPERTIES = FAMILY_LIST_PROPERTIES;
module.exports.FAMILY_LONGHANDS = FAMILY_LONGHANDS;
module.exports.FAMILY_SLOT_CLASSES = FAMILY_SLOT_CLASSES;
module.exports.FAMILY_SLOT_INITIALS = FAMILY_SLOT_INITIALS;
module.exports.FAMILY_SLOT_KEYWORDS = FAMILY_SLOT_KEYWORDS;
module.exports.FEATURELESS_PSEUDO_CLASSES = FEATURELESS_PSEUDO_CLASSES;
module.exports.FILTER_FUNCTION_OMITTED = FILTER_FUNCTION_OMITTED;
module.exports.FLEX_KEYWORDS = FLEX_KEYWORDS;
module.exports.FONT_SIZE_KEYWORDS = FONT_SIZE_KEYWORDS;
module.exports.FONT_STRETCH_PERCENTAGES = FONT_STRETCH_PERCENTAGES;
module.exports.FONT_WEIGHT_NUMBERS = FONT_WEIGHT_NUMBERS;
module.exports.GENERIC_FONT_FAMILIES = GENERIC_FONT_FAMILIES;
module.exports.GRADIENT_LAST_POSITIONS = GRADIENT_LAST_POSITIONS;
module.exports.INITIAL_VALUE_KEYWORDS = INITIAL_VALUE_KEYWORDS;
module.exports.INTEGER_PROPERTIES = INTEGER_PROPERTIES;
module.exports.KEYWORD_ONLY_PROPERTIES = KEYWORD_ONLY_PROPERTIES;
module.exports.LATER_COLOR_NAMES = LATER_COLOR_NAMES;
module.exports.LAYER_INITIALS = LAYER_INITIALS;
module.exports.LEGACY_PSEUDO_ELEMENTS = LEGACY_PSEUDO_ELEMENTS;
module.exports.LENGTH_ONLY_FUNCTIONS = LENGTH_ONLY_FUNCTIONS;
module.exports.LINEAR_GRADIENTS = LINEAR_GRADIENTS;
module.exports.LINEAR_SRGB_TO_P3 = LINEAR_SRGB_TO_P3;
module.exports.MATH_FUNCTIONS = MATH_FUNCTIONS;
module.exports.MATH_FUNCTION_ARITY = MATH_FUNCTION_ARITY;
module.exports.MATH_FUNCTION_FOLD = MATH_FUNCTION_FOLD;
module.exports.MATH_FUNCTION_KEYWORDS = MATH_FUNCTION_KEYWORDS;
module.exports.MATH_FUNCTION_SUM_ARGUMENTS = MATH_FUNCTION_SUM_ARGUMENTS;
module.exports.MERGEABLE_AT_RULES = MERGEABLE_AT_RULES;
module.exports.MERGE_LONGHANDS = MERGE_LONGHANDS;
module.exports.NEGATIVE_ACCEPTING_PROPERTIES = NEGATIVE_ACCEPTING_PROPERTIES;
module.exports.NEVER = NEVER;
module.exports.NTH_NAMED_EQUIVALENTS = NTH_NAMED_EQUIVALENTS;
module.exports.NTH_PSEUDO_FUNCTIONS = NTH_PSEUDO_FUNCTIONS;
module.exports.OMITTABLE_INITIAL_KEYWORDS = OMITTABLE_INITIAL_KEYWORDS;
module.exports.ONE_VALUE_PAIR_SHORTHANDS = ONE_VALUE_PAIR_SHORTHANDS;
module.exports.ORDERED_LONGHANDS = ORDERED_LONGHANDS;
module.exports.PAIR_LONGHANDS = PAIR_LONGHANDS;
module.exports.PLACE_SHORTHANDS = PLACE_SHORTHANDS;
module.exports.POSITION_PROPERTIES = POSITION_PROPERTIES;
module.exports.POSITION_X_KEYWORDS = POSITION_X_KEYWORDS;
module.exports.POSITION_Y_KEYWORDS = POSITION_Y_KEYWORDS;
module.exports.PREDEFINED_COLOR_SPACES = PREDEFINED_COLOR_SPACES;
module.exports.PREFIXED_AT_RULES = PREFIXED_AT_RULES;
module.exports.PREFIXED_PROPERTIES = PREFIXED_PROPERTIES;
module.exports.PREFIXED_SELECTORS = PREFIXED_SELECTORS;
module.exports.PREFIXED_SPELLING_KEYWORDS = PREFIXED_SPELLING_KEYWORDS;
module.exports.PREFIXED_VALUES = PREFIXED_VALUES;
module.exports.PREFIX_WINDOWS = PREFIX_WINDOWS;
module.exports.PREFIX_WINDOW_STARTS = PREFIX_WINDOW_STARTS;
module.exports.QUARTER_TURN_ANGLE = QUARTER_TURN_ANGLE;
module.exports.RATIO_PROPERTIES = RATIO_PROPERTIES;
module.exports.REPEAT_STYLE_KEYWORDS = REPEAT_STYLE_KEYWORDS;
module.exports.REPEAT_STYLE_PROPERTIES = REPEAT_STYLE_PROPERTIES;
module.exports.RGB_TO_NAME = RGB_TO_NAME;
module.exports.SELECTOR_FUNCTIONS = SELECTOR_FUNCTIONS;
module.exports.SELECTOR_SUPPORTED_FROM = SELECTOR_SUPPORTED_FROM;
module.exports.SHADOW_PROPERTIES = SHADOW_PROPERTIES;
module.exports.SHORTHAND_INITIAL_KEYWORDS = SHORTHAND_INITIAL_KEYWORDS;
module.exports.SHORTHAND_LONGHANDS = SHORTHAND_LONGHANDS;
module.exports.SLASH_BOX_SHORTHANDS = SLASH_BOX_SHORTHANDS;
module.exports.SLASH_LONGHANDS = SLASH_LONGHANDS;
module.exports.SRGB_SPACE = SRGB_SPACE;
module.exports.STEPPED_FUNCTIONS = STEPPED_FUNCTIONS;
module.exports.SUBSTITUTION_FUNCTIONS = SUBSTITUTION_FUNCTIONS;
module.exports.SUPPORTED_FROM = SUPPORTED_FROM;
module.exports.SUPPORT_BROWSERS = SUPPORT_BROWSERS;
module.exports.SUPPORT_PROFILES = SUPPORT_PROFILES;
module.exports.SYSTEM_UI_STACK = SYSTEM_UI_STACK;
module.exports.THROUGH_MATRIX = THROUGH_MATRIX;
module.exports.THROUGH_TRANSFER = THROUGH_TRANSFER;
module.exports.TRANSITION_BEHAVIORS = TRANSITION_BEHAVIORS;
module.exports.UNIT_CONVERSION_TARGETS = UNIT_CONVERSION_TARGETS;
module.exports.UNIT_GROUP_BASE = UNIT_GROUP_BASE;
module.exports.UNSHARED_LONGHAND_KEYWORDS = UNSHARED_LONGHAND_KEYWORDS;
module.exports.X_AXIS_TRANSFORMS = X_AXIS_TRANSFORMS;
module.exports.ZERO_ANGLE_FUNCTIONS = ZERO_ANGLE_FUNCTIONS;
module.exports.ZERO_UNIT_KEEPING_PROPERTIES = ZERO_UNIT_KEEPING_PROPERTIES;
// The arithmetic the printer's own evaluator needs. Sorted after the tables:
// `import/order` orders exports by case, uppercase first.
module.exports.foldAdd = foldAdd;
module.exports.foldDivide = foldDivide;
module.exports.foldMultiply = foldMultiply;