@tbela99/css-parser
Version:
CSS parser for node and the browser
18,813 lines • 709 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.CSSParser = {}));
})(this, (function (exports) { 'use strict';
var ValidationLevel;
(function (ValidationLevel) {
ValidationLevel[ValidationLevel["Valid"] = 0] = "Valid";
ValidationLevel[ValidationLevel["Drop"] = 1] = "Drop";
ValidationLevel[ValidationLevel["Lenient"] = 2] = "Lenient"; /* preserve unknown at-rules, declarations and pseudo-classes */
})(ValidationLevel || (ValidationLevel = {}));
exports.EnumToken = void 0;
(function (EnumToken) {
EnumToken[EnumToken["CommentTokenType"] = 0] = "CommentTokenType";
EnumToken[EnumToken["CDOCOMMTokenType"] = 1] = "CDOCOMMTokenType";
EnumToken[EnumToken["StyleSheetNodeType"] = 2] = "StyleSheetNodeType";
EnumToken[EnumToken["AtRuleNodeType"] = 3] = "AtRuleNodeType";
EnumToken[EnumToken["RuleNodeType"] = 4] = "RuleNodeType";
EnumToken[EnumToken["DeclarationNodeType"] = 5] = "DeclarationNodeType";
EnumToken[EnumToken["LiteralTokenType"] = 6] = "LiteralTokenType";
EnumToken[EnumToken["IdenTokenType"] = 7] = "IdenTokenType";
EnumToken[EnumToken["DashedIdenTokenType"] = 8] = "DashedIdenTokenType";
EnumToken[EnumToken["CommaTokenType"] = 9] = "CommaTokenType";
EnumToken[EnumToken["ColonTokenType"] = 10] = "ColonTokenType";
EnumToken[EnumToken["SemiColonTokenType"] = 11] = "SemiColonTokenType";
EnumToken[EnumToken["NumberTokenType"] = 12] = "NumberTokenType";
EnumToken[EnumToken["AtRuleTokenType"] = 13] = "AtRuleTokenType";
EnumToken[EnumToken["PercentageTokenType"] = 14] = "PercentageTokenType";
EnumToken[EnumToken["FunctionTokenType"] = 15] = "FunctionTokenType";
EnumToken[EnumToken["TimelineFunctionTokenType"] = 16] = "TimelineFunctionTokenType";
EnumToken[EnumToken["TimingFunctionTokenType"] = 17] = "TimingFunctionTokenType";
EnumToken[EnumToken["UrlFunctionTokenType"] = 18] = "UrlFunctionTokenType";
EnumToken[EnumToken["ImageFunctionTokenType"] = 19] = "ImageFunctionTokenType";
EnumToken[EnumToken["StringTokenType"] = 20] = "StringTokenType";
EnumToken[EnumToken["UnclosedStringTokenType"] = 21] = "UnclosedStringTokenType";
EnumToken[EnumToken["DimensionTokenType"] = 22] = "DimensionTokenType";
EnumToken[EnumToken["LengthTokenType"] = 23] = "LengthTokenType";
EnumToken[EnumToken["AngleTokenType"] = 24] = "AngleTokenType";
EnumToken[EnumToken["TimeTokenType"] = 25] = "TimeTokenType";
EnumToken[EnumToken["FrequencyTokenType"] = 26] = "FrequencyTokenType";
EnumToken[EnumToken["ResolutionTokenType"] = 27] = "ResolutionTokenType";
EnumToken[EnumToken["HashTokenType"] = 28] = "HashTokenType";
EnumToken[EnumToken["BlockStartTokenType"] = 29] = "BlockStartTokenType";
EnumToken[EnumToken["BlockEndTokenType"] = 30] = "BlockEndTokenType";
EnumToken[EnumToken["AttrStartTokenType"] = 31] = "AttrStartTokenType";
EnumToken[EnumToken["AttrEndTokenType"] = 32] = "AttrEndTokenType";
EnumToken[EnumToken["StartParensTokenType"] = 33] = "StartParensTokenType";
EnumToken[EnumToken["EndParensTokenType"] = 34] = "EndParensTokenType";
EnumToken[EnumToken["ParensTokenType"] = 35] = "ParensTokenType";
EnumToken[EnumToken["WhitespaceTokenType"] = 36] = "WhitespaceTokenType";
EnumToken[EnumToken["IncludeMatchTokenType"] = 37] = "IncludeMatchTokenType";
EnumToken[EnumToken["DashMatchTokenType"] = 38] = "DashMatchTokenType";
EnumToken[EnumToken["EqualMatchTokenType"] = 39] = "EqualMatchTokenType";
EnumToken[EnumToken["LtTokenType"] = 40] = "LtTokenType";
EnumToken[EnumToken["LteTokenType"] = 41] = "LteTokenType";
EnumToken[EnumToken["GtTokenType"] = 42] = "GtTokenType";
EnumToken[EnumToken["GteTokenType"] = 43] = "GteTokenType";
EnumToken[EnumToken["PseudoClassTokenType"] = 44] = "PseudoClassTokenType";
EnumToken[EnumToken["PseudoClassFuncTokenType"] = 45] = "PseudoClassFuncTokenType";
EnumToken[EnumToken["DelimTokenType"] = 46] = "DelimTokenType";
EnumToken[EnumToken["UrlTokenTokenType"] = 47] = "UrlTokenTokenType";
EnumToken[EnumToken["EOFTokenType"] = 48] = "EOFTokenType";
EnumToken[EnumToken["ImportantTokenType"] = 49] = "ImportantTokenType";
EnumToken[EnumToken["ColorTokenType"] = 50] = "ColorTokenType";
EnumToken[EnumToken["AttrTokenType"] = 51] = "AttrTokenType";
EnumToken[EnumToken["BadCommentTokenType"] = 52] = "BadCommentTokenType";
EnumToken[EnumToken["BadCdoTokenType"] = 53] = "BadCdoTokenType";
EnumToken[EnumToken["BadUrlTokenType"] = 54] = "BadUrlTokenType";
EnumToken[EnumToken["BadStringTokenType"] = 55] = "BadStringTokenType";
EnumToken[EnumToken["BinaryExpressionTokenType"] = 56] = "BinaryExpressionTokenType";
EnumToken[EnumToken["UnaryExpressionTokenType"] = 57] = "UnaryExpressionTokenType";
EnumToken[EnumToken["FlexTokenType"] = 58] = "FlexTokenType";
/* catch all */
EnumToken[EnumToken["ListToken"] = 59] = "ListToken";
/* arithmetic tokens */
EnumToken[EnumToken["Add"] = 60] = "Add";
EnumToken[EnumToken["Mul"] = 61] = "Mul";
EnumToken[EnumToken["Div"] = 62] = "Div";
EnumToken[EnumToken["Sub"] = 63] = "Sub";
/* new tokens */
EnumToken[EnumToken["ColumnCombinatorTokenType"] = 64] = "ColumnCombinatorTokenType";
EnumToken[EnumToken["ContainMatchTokenType"] = 65] = "ContainMatchTokenType";
EnumToken[EnumToken["StartMatchTokenType"] = 66] = "StartMatchTokenType";
EnumToken[EnumToken["EndMatchTokenType"] = 67] = "EndMatchTokenType";
EnumToken[EnumToken["MatchExpressionTokenType"] = 68] = "MatchExpressionTokenType";
EnumToken[EnumToken["NameSpaceAttributeTokenType"] = 69] = "NameSpaceAttributeTokenType";
EnumToken[EnumToken["FractionTokenType"] = 70] = "FractionTokenType";
EnumToken[EnumToken["IdenListTokenType"] = 71] = "IdenListTokenType";
EnumToken[EnumToken["GridTemplateFuncTokenType"] = 72] = "GridTemplateFuncTokenType";
EnumToken[EnumToken["KeyFrameRuleNodeType"] = 73] = "KeyFrameRuleNodeType";
EnumToken[EnumToken["ClassSelectorTokenType"] = 74] = "ClassSelectorTokenType";
EnumToken[EnumToken["UniversalSelectorTokenType"] = 75] = "UniversalSelectorTokenType";
EnumToken[EnumToken["ChildCombinatorTokenType"] = 76] = "ChildCombinatorTokenType";
EnumToken[EnumToken["DescendantCombinatorTokenType"] = 77] = "DescendantCombinatorTokenType";
EnumToken[EnumToken["NextSiblingCombinatorTokenType"] = 78] = "NextSiblingCombinatorTokenType";
EnumToken[EnumToken["SubsequentSiblingCombinatorTokenType"] = 79] = "SubsequentSiblingCombinatorTokenType";
EnumToken[EnumToken["NestingSelectorTokenType"] = 80] = "NestingSelectorTokenType";
EnumToken[EnumToken["InvalidRuleTokenType"] = 81] = "InvalidRuleTokenType";
EnumToken[EnumToken["InvalidClassSelectorTokenType"] = 82] = "InvalidClassSelectorTokenType";
EnumToken[EnumToken["InvalidAttrTokenType"] = 83] = "InvalidAttrTokenType";
EnumToken[EnumToken["InvalidAtRuleTokenType"] = 84] = "InvalidAtRuleTokenType";
EnumToken[EnumToken["MediaQueryConditionTokenType"] = 85] = "MediaQueryConditionTokenType";
EnumToken[EnumToken["MediaFeatureTokenType"] = 86] = "MediaFeatureTokenType";
EnumToken[EnumToken["MediaFeatureOnlyTokenType"] = 87] = "MediaFeatureOnlyTokenType";
EnumToken[EnumToken["MediaFeatureNotTokenType"] = 88] = "MediaFeatureNotTokenType";
EnumToken[EnumToken["MediaFeatureAndTokenType"] = 89] = "MediaFeatureAndTokenType";
EnumToken[EnumToken["MediaFeatureOrTokenType"] = 90] = "MediaFeatureOrTokenType";
EnumToken[EnumToken["PseudoPageTokenType"] = 91] = "PseudoPageTokenType";
EnumToken[EnumToken["PseudoElementTokenType"] = 92] = "PseudoElementTokenType";
/* aliases */
EnumToken[EnumToken["Time"] = 25] = "Time";
EnumToken[EnumToken["Iden"] = 7] = "Iden";
EnumToken[EnumToken["EOF"] = 48] = "EOF";
EnumToken[EnumToken["Hash"] = 28] = "Hash";
EnumToken[EnumToken["Flex"] = 58] = "Flex";
EnumToken[EnumToken["Angle"] = 24] = "Angle";
EnumToken[EnumToken["Color"] = 50] = "Color";
EnumToken[EnumToken["Comma"] = 9] = "Comma";
EnumToken[EnumToken["String"] = 20] = "String";
EnumToken[EnumToken["Length"] = 23] = "Length";
EnumToken[EnumToken["Number"] = 12] = "Number";
EnumToken[EnumToken["Perc"] = 14] = "Perc";
EnumToken[EnumToken["Literal"] = 6] = "Literal";
EnumToken[EnumToken["Comment"] = 0] = "Comment";
EnumToken[EnumToken["UrlFunc"] = 18] = "UrlFunc";
EnumToken[EnumToken["Dimension"] = 22] = "Dimension";
EnumToken[EnumToken["Frequency"] = 26] = "Frequency";
EnumToken[EnumToken["Resolution"] = 27] = "Resolution";
EnumToken[EnumToken["Whitespace"] = 36] = "Whitespace";
EnumToken[EnumToken["IdenList"] = 71] = "IdenList";
EnumToken[EnumToken["DashedIden"] = 8] = "DashedIden";
EnumToken[EnumToken["GridTemplateFunc"] = 72] = "GridTemplateFunc";
EnumToken[EnumToken["ImageFunc"] = 19] = "ImageFunc";
EnumToken[EnumToken["CommentNodeType"] = 0] = "CommentNodeType";
EnumToken[EnumToken["CDOCOMMNodeType"] = 1] = "CDOCOMMNodeType";
EnumToken[EnumToken["TimingFunction"] = 17] = "TimingFunction";
EnumToken[EnumToken["TimelineFunction"] = 16] = "TimelineFunction";
})(exports.EnumToken || (exports.EnumToken = {}));
const funcLike = [
exports.EnumToken.ParensTokenType,
exports.EnumToken.FunctionTokenType,
exports.EnumToken.UrlFunctionTokenType,
exports.EnumToken.StartParensTokenType,
exports.EnumToken.ImageFunctionTokenType,
exports.EnumToken.TimingFunctionTokenType,
exports.EnumToken.TimingFunctionTokenType,
exports.EnumToken.PseudoClassFuncTokenType,
exports.EnumToken.GridTemplateFuncTokenType
];
// from https://www.w3.org/TR/css-color-4/multiply-matrices.js
/**
* Simple matrix (and vector) multiplication
* Warning: No error handling for incompatible dimensions!
* @author Lea Verou 2020 MIT License
*/
// A is m x n. B is n x p. product is m x p.
function multiplyMatrices(A, B) {
let m = A.length;
if (!Array.isArray(A[0])) {
// A is vector, convert to [[a, b, c, ...]]
A = [A];
}
if (!Array.isArray(B[0])) {
// B is vector, convert to [[a], [b], [c], ...]]
B = B.map((x) => [x]);
}
let p = B[0].length;
let B_cols = B[0].map((_, i) => B.map((x) => x[i])); // transpose B
let product = A.map((row) => B_cols.map((col) => {
if (!Array.isArray(row)) {
return col.reduce((a, c) => a + c * row, 0);
}
return row.reduce((a, c, i) => a + c * (col[i] || 0), 0);
}));
if (m === 1) {
product = product[0]; // Avoid [[a, b, c, ...]]
}
if (p === 1) {
return product.map((x) => x[0]); // Avoid [[a], [b], [c], ...]]
}
return product;
}
const colorRange = {
lab: {
l: [0, 100],
a: [-125, 125],
b: [-125, 125]
},
lch: {
l: [0, 100],
c: [0, 150],
h: [0, 360]
},
oklab: {
l: [0, 1],
a: [-0.4, .4],
b: [-0.4, 0.4]
},
oklch: {
l: [0, 1],
a: [0, .4],
b: [0, 0.4]
}
};
const colorFuncColorSpace = ['srgb', 'srgb-linear', 'display-p3', 'prophoto-rgb', 'a98-rgb', 'rec2020', 'xyz', 'xyz-d65', 'xyz-d50'];
({ typ: exports.EnumToken.IdenTokenType});
const D50 = [0.3457 / 0.3585, 1.00000, (1.0 - 0.3457 - 0.3585) / 0.3585];
const k = Math.pow(29, 3) / Math.pow(3, 3);
const e = Math.pow(6, 3) / Math.pow(29, 3);
// color module v4
const systemColors = new Set(['ActiveText', 'ButtonBorder', 'ButtonFace', 'ButtonText', 'Canvas', 'CanvasText', 'Field', 'FieldText', 'GrayText', 'Highlight', 'HighlightText', 'LinkText', 'Mark', 'MarkText', 'VisitedText'].map(m => m.toLowerCase()));
// deprecated
const deprecatedSystemColors = new Set(['ActiveBorder', 'ActiveCaption', 'AppWorkspace', 'Background', 'ButtonFace', 'ButtonHighlight', 'ButtonShadow', 'ButtonText', 'CaptionText', 'GrayText', 'Highlight', 'HighlightText', 'InactiveBorder', 'InactiveCaption', 'InactiveCaptionText', 'InfoBackground', 'InfoText', 'Menu', 'MenuText', 'Scrollbar', 'ThreeDDarkShadow', 'ThreeDFace', 'ThreeDHighlight', 'ThreeDLightShadow', 'ThreeDShadow', 'Window', 'WindowFrame', 'WindowText'].map(t => t.toLowerCase()));
// name to color
const COLORS_NAMES = Object.seal({
'aliceblue': '#f0f8ff',
'antiquewhite': '#faebd7',
'aqua': '#00ffff',
'aquamarine': '#7fffd4',
'azure': '#f0ffff',
'beige': '#f5f5dc',
'bisque': '#ffe4c4',
'black': '#000000',
'blanchedalmond': '#ffebcd',
'blue': '#0000ff',
'blueviolet': '#8a2be2',
'brown': '#a52a2a',
'burlywood': '#deb887',
'cadetblue': '#5f9ea0',
'chartreuse': '#7fff00',
'chocolate': '#d2691e',
'coral': '#ff7f50',
'cornflowerblue': '#6495ed',
'cornsilk': '#fff8dc',
'crimson': '#dc143c',
'cyan': '#00ffff',
'darkblue': '#00008b',
'darkcyan': '#008b8b',
'darkgoldenrod': '#b8860b',
'darkgray': '#a9a9a9',
'darkgrey': '#a9a9a9',
'darkgreen': '#006400',
'darkkhaki': '#bdb76b',
'darkmagenta': '#8b008b',
'darkolivegreen': '#556b2f',
'darkorange': '#ff8c00',
'darkorchid': '#9932cc',
'darkred': '#8b0000',
'darksalmon': '#e9967a',
'darkseagreen': '#8fbc8f',
'darkslateblue': '#483d8b',
'darkslategray': '#2f4f4f',
'darkslategrey': '#2f4f4f',
'darkturquoise': '#00ced1',
'darkviolet': '#9400d3',
'deeppink': '#ff1493',
'deepskyblue': '#00bfff',
'dimgray': '#696969',
'dimgrey': '#696969',
'dodgerblue': '#1e90ff',
'firebrick': '#b22222',
'floralwhite': '#fffaf0',
'forestgreen': '#228b22',
'fuchsia': '#ff00ff',
'gainsboro': '#dcdcdc',
'ghostwhite': '#f8f8ff',
'gold': '#ffd700',
'goldenrod': '#daa520',
'gray': '#808080',
'grey': '#808080',
'green': '#008000',
'greenyellow': '#adff2f',
'honeydew': '#f0fff0',
'hotpink': '#ff69b4',
'indianred': '#cd5c5c',
'indigo': '#4b0082',
'ivory': '#fffff0',
'khaki': '#f0e68c',
'lavender': '#e6e6fa',
'lavenderblush': '#fff0f5',
'lawngreen': '#7cfc00',
'lemonchiffon': '#fffacd',
'lightblue': '#add8e6',
'lightcoral': '#f08080',
'lightcyan': '#e0ffff',
'lightgoldenrodyellow': '#fafad2',
'lightgray': '#d3d3d3',
'lightgrey': '#d3d3d3',
'lightgreen': '#90ee90',
'lightpink': '#ffb6c1',
'lightsalmon': '#ffa07a',
'lightseagreen': '#20b2aa',
'lightskyblue': '#87cefa',
'lightslategray': '#778899',
'lightslategrey': '#778899',
'lightsteelblue': '#b0c4de',
'lightyellow': '#ffffe0',
'lime': '#00ff00',
'limegreen': '#32cd32',
'linen': '#faf0e6',
'magenta': '#ff00ff',
'maroon': '#800000',
'mediumaquamarine': '#66cdaa',
'mediumblue': '#0000cd',
'mediumorchid': '#ba55d3',
'mediumpurple': '#9370d8',
'mediumseagreen': '#3cb371',
'mediumslateblue': '#7b68ee',
'mediumspringgreen': '#00fa9a',
'mediumturquoise': '#48d1cc',
'mediumvioletred': '#c71585',
'midnightblue': '#191970',
'mintcream': '#f5fffa',
'mistyrose': '#ffe4e1',
'moccasin': '#ffe4b5',
'navajowhite': '#ffdead',
'navy': '#000080',
'oldlace': '#fdf5e6',
'olive': '#808000',
'olivedrab': '#6b8e23',
'orange': '#ffa500',
'orangered': '#ff4500',
'orchid': '#da70d6',
'palegoldenrod': '#eee8aa',
'palegreen': '#98fb98',
'paleturquoise': '#afeeee',
'palevioletred': '#d87093',
'papayawhip': '#ffefd5',
'peachpuff': '#ffdab9',
'peru': '#cd853f',
'pink': '#ffc0cb',
'plum': '#dda0dd',
'powderblue': '#b0e0e6',
'purple': '#800080',
'red': '#ff0000',
'rosybrown': '#bc8f8f',
'royalblue': '#4169e1',
'saddlebrown': '#8b4513',
'salmon': '#fa8072',
'sandybrown': '#f4a460',
'seagreen': '#2e8b57',
'seashell': '#fff5ee',
'sienna': '#a0522d',
'silver': '#c0c0c0',
'skyblue': '#87ceeb',
'slateblue': '#6a5acd',
'slategray': '#708090',
'slategrey': '#708090',
'snow': '#fffafa',
'springgreen': '#00ff7f',
'steelblue': '#4682b4',
'tan': '#d2b48c',
'teal': '#008080',
'thistle': '#d8bfd8',
'tomato': '#ff6347',
'turquoise': '#40e0d0',
'violet': '#ee82ee',
'wheat': '#f5deb3',
'white': '#ffffff',
'whitesmoke': '#f5f5f5',
'yellow': '#ffff00',
'yellowgreen': '#9acd32',
'rebeccapurple': '#663399',
'transparent': '#00000000'
});
// color to name
const NAMES_COLORS = Object.seal(Object.entries(COLORS_NAMES).reduce((acc, [key, value]) => {
acc[value] = key;
return acc;
}, Object.create(null)));
function toHexString(acc, value) {
return acc + value.toString(16).padStart(2, '0');
}
function reduceHexValue(value) {
const named_color = NAMES_COLORS[expandHexValue(value)];
if (value.length == 7) {
if (value[1] == value[2] &&
value[3] == value[4] &&
value[5] == value[6]) {
value = `#${value[1]}${value[3]}${value[5]}`;
}
}
else if (value.length == 9) {
if (value[1] == value[2] &&
value[3] == value[4] &&
value[5] == value[6] &&
value[7] == value[8]) {
value = `#${value[1]}${value[3]}${value[5]}${value[7]}`;
}
}
return named_color != null && named_color.length <= value.length ? named_color : value;
}
function expandHexValue(value) {
if (value.length == 4) {
return `#${value[1]}${value[1]}${value[2]}${value[2]}${value[3]}${value[3]}`;
}
if (value.length == 5) {
return `#${value[1]}${value[1]}${value[2]}${value[2]}${value[3]}${value[3]}${value[4]}${value[4]}`;
}
return value;
}
function rgb2hex(token) {
let value = '#';
let t;
// @ts-ignore
const components = getComponents(token);
// @ts-ignore
for (let i = 0; i < 3; i++) {
// @ts-ignore
t = components[i];
// @ts-ignore
value += (t.typ == exports.EnumToken.Iden && t.val == 'none' ? '0' : Math.round(getNumber(t) * (t.typ == exports.EnumToken.PercentageTokenType ? 255 : 1))).toString(16).padStart(2, '0');
}
// @ts-ignore
if (components.length == 4) {
// @ts-ignore
t = components[3];
// @ts-ignore
const v = (t.typ == exports.EnumToken.IdenTokenType && t.val == 'none') ? 1 : getNumber(t);
// @ts-ignore
if (v < 1) {
// @ts-ignore
value += Math.round(255 * getNumber(t)).toString(16).padStart(2, '0');
}
}
return value;
}
function hsl2hex(token) {
return `${hsl2rgb(token).reduce(toHexString, '#')}`;
}
function hwb2hex(token) {
return `${hwb2rgb(token).reduce(toHexString, '#')}`;
}
function cmyk2hex(token) {
return `#${cmyk2rgb(token).reduce(toHexString, '')}`;
}
function oklab2hex(token) {
return `${oklab2rgb(token).reduce(toHexString, '#')}`;
}
function oklch2hex(token) {
return `${oklch2rgb(token).reduce(toHexString, '#')}`;
}
function lab2hex(token) {
return `${lab2rgb(token).reduce(toHexString, '#')}`;
}
function lch2hex(token) {
return `${lch2rgb(token).reduce(toHexString, '#')}`;
}
function srgb2hexvalues(r, g, b, alpha) {
return [r, g, b].concat(alpha == null || alpha == 1 ? [] : [alpha]).reduce((acc, value) => acc + minmax(Math.round(255 * value), 0, 255).toString(16).padStart(2, '0'), '#');
}
function getComponents(token) {
if (token.kin == 'hex' || token.kin == 'lit') {
const value = expandHexValue(token.kin == 'lit' ? COLORS_NAMES[token.val.toLowerCase()] : token.val);
// @ts-ignore
return value.slice(1).match(/([a-fA-F0-9]{2})/g).map((t) => {
return { typ: exports.EnumToken.Number, val: parseInt(t, 16).toString() };
});
}
return token.chi
.filter((t) => ![exports.EnumToken.LiteralTokenType, exports.EnumToken.CommentTokenType, exports.EnumToken.CommaTokenType, exports.EnumToken.WhitespaceTokenType].includes(t.typ));
}
function XYZ_to_lin_sRGB(x, y, z) {
// convert XYZ to linear-light sRGB
const M = [
[12831 / 3959, -329 / 214, -1974 / 3959],
[-851781 / 878810, 1648619 / 878810, 36519 / 878810],
[705 / 12673, -2585 / 12673, 705 / 667],
];
const XYZ = [x, y, z]; // convert to XYZ
return multiplyMatrices(M, XYZ).map((v) => v);
}
function XYZ_D50_to_D65(x, y, z) {
// Bradford chromatic adaptation from D50 to D65
const M = [
[0.9554734527042182, -0.023098536874261423, 0.0632593086610217],
[-0.028369706963208136, 1.0099954580058226, 0.021041398966943008],
[0.012314001688319899, -0.020507696433477912, 1.3303659366080753]
];
const XYZ = [x, y, z];
return multiplyMatrices(M, XYZ); //.map((v: number) => v);
}
function srgb2xyz(r, g, b, alpha) {
[r, g, b] = srgb2lsrgbvalues(r, g, b);
const rgb = [
0.436065742824811 * r +
0.3851514688337912 * g +
0.14307845442264197 * b,
0.22249319175623702 * r +
0.7168870538238823 * g +
0.06061979053616537 * b,
0.013923904500943465 * r +
0.09708128566574634 * g +
0.7140993584005155 * b
];
if (alpha != null && alpha != 1) {
rgb.push(alpha);
}
return rgb;
}
function hex2lch(token) {
// @ts-ignore
return lab2lchvalues(...hex2lab(token));
}
function rgb2lch(token) {
// @ts-ignore
return lab2lchvalues(...rgb2lab(token));
}
function hsl2lch(token) {
// @ts-ignore
return lab2lchvalues(...hsl2lab(token));
}
function hwb2lch(token) {
// @ts-ignore
return lab2lchvalues(...hwb2lab(token));
}
function lab2lch(token) {
// @ts-ignore
return lab2lchvalues(...getLABComponents(token));
}
function srgb2lch(r, g, blue, alpha) {
// @ts-ignore
return lab2lchvalues(...srgb2lab(r, g, blue, alpha));
}
function oklab2lch(token) {
// @ts-ignore
return lab2lchvalues(...oklab2lab(token));
}
function oklch2lch(token) {
// @ts-ignore
return lab2lchvalues(...oklch2lab(token));
}
function lab2lchvalues(l, a, b, alpha = null) {
let c = Math.sqrt(a * a + b * b);
let h = Math.atan2(b, a) * 180 / Math.PI;
if (h < 0) {
h += 360;
}
if (c < .0001) {
c = h = 0;
}
return alpha == null ? [l, c, h] : [l, c, h, alpha];
}
function xyz2lchvalues(x, y, z, alpha) {
// @ts-ignore(
const lch = lab2lchvalues(...xyz2lab(x, y, z));
return alpha == null || alpha == 1 ? lch : lch.concat(alpha);
}
function getLCHComponents(token) {
const components = getComponents(token);
// @ts-ignore
let t = components[0];
// @ts-ignore
const l = getNumber(t) * (t.typ == exports.EnumToken.PercentageTokenType ? 100 : 1);
// @ts-ignore
t = components[1];
// @ts-ignore
const c = getNumber(t) * (t.typ == exports.EnumToken.PercentageTokenType ? 150 : 1);
// @ts-ignore
t = components[2];
// @ts-ignore
const h = getAngle(t) * 360;
// @ts-ignore
t = components[3];
// @ts-ignore
const alpha = t == null ? 1 : getNumber(t);
return alpha == null ? [l, c, h] : [l, c, h, alpha];
}
function hex2oklch(token) {
// @ts-ignore
return lab2lchvalues(...hex2oklab(token));
}
function rgb2oklch(token) {
// @ts-ignore
return lab2lchvalues(...rgb2oklab(token));
}
function hsl2oklch(token) {
// @ts-ignore
return lab2lchvalues(...hsl2oklab(token));
}
function hwb2oklch(token) {
// @ts-ignore
return lab2lchvalues(...hwb2oklab(token));
}
function lab2oklch(token) {
// @ts-ignore
return lab2lchvalues(...lab2oklab(token));
}
function lch2oklch(token) {
// @ts-ignore
return lab2lchvalues(...lch2oklab(token));
}
function oklab2oklch(token) {
// @ts-ignore
return lab2lchvalues(...getOKLABComponents(token));
}
function srgb2oklch(r, g, blue, alpha) {
// @ts-ignore
return lab2lchvalues(...srgb2oklab(r, g, blue, alpha));
}
function getOKLCHComponents(token) {
const components = getComponents(token);
// @ts-ignore
let t = components[0];
// @ts-ignore
const l = getNumber(t);
// @ts-ignore
t = components[1];
// @ts-ignore
const c = getNumber(t) * (t.typ == exports.EnumToken.PercentageTokenType ? .4 : 1);
// @ts-ignore
t = components[2];
// @ts-ignore
const h = getAngle(t) * 360;
// @ts-ignore
t = components[3];
// @ts-ignore
const alpha = t == null || (t.typ == exports.EnumToken.IdenTokenType && t.val == 'none') ? 1 : getNumber(t);
return [l, c, h, alpha];
}
function hex2oklab(token) {
// @ts-ignore
return srgb2oklab(...hex2srgb(token));
}
function rgb2oklab(token) {
// @ts-ignore
return srgb2oklab(...rgb2srgb(token));
}
function hsl2oklab(token) {
// @ts-ignore
return srgb2oklab(...hsl2srgb(token));
}
function hwb2oklab(token) {
// @ts-ignore
return srgb2oklab(...hwb2srgb(token));
}
function lab2oklab(token) {
// @ts-ignore
return srgb2oklab(...lab2srgb(token));
}
function lch2oklab(token) {
// @ts-ignore
return srgb2oklab(...lch2srgb(token));
}
function oklch2oklab(token) {
// @ts-ignore
return lch2labvalues(...getOKLCHComponents(token));
}
function srgb2oklab(r, g, blue, alpha) {
[r, g, blue] = srgb2lsrgbvalues(r, g, blue);
let L = Math.cbrt(0.41222147079999993 * r + 0.5363325363 * g + 0.0514459929 * blue);
let M = Math.cbrt(0.2119034981999999 * r + 0.6806995450999999 * g + 0.1073969566 * blue);
let S = Math.cbrt(0.08830246189999998 * r + 0.2817188376 * g + 0.6299787005000002 * blue);
const l = 0.2104542553 * L + 0.793617785 * M - 0.0040720468 * S;
const a = r == g && g == blue ? 0 : 1.9779984951 * L - 2.428592205 * M + 0.4505937099 * S;
const b = r == g && g == blue ? 0 : 0.0259040371 * L + 0.7827717662 * M - 0.808675766 * S;
return alpha == null ? [l, a, b] : [l, a, b, alpha];
}
function getOKLABComponents(token) {
const components = getComponents(token);
// @ts-ignore
let t = components[0];
// @ts-ignore
const l = getNumber(t);
// @ts-ignore
t = components[1];
// @ts-ignore
const a = getNumber(t) * (t.typ == exports.EnumToken.PercentageTokenType ? .4 : 1);
// @ts-ignore
t = components[2];
// @ts-ignore
const b = getNumber(t) * (t.typ == exports.EnumToken.PercentageTokenType ? .4 : 1);
// @ts-ignore
t = components[3];
// @ts-ignore
const alpha = t == null || (t.typ == exports.EnumToken.IdenTokenType && t.val == 'none') ? 1 : getNumber(t);
const rgb = [l, a, b];
if (alpha != 1 && alpha != null) {
rgb.push(alpha);
}
return rgb;
}
function OKLab_to_XYZ(l, a, b, alpha = null) {
// Given OKLab, convert to XYZ relative to D65
const LMStoXYZ = [
[1.2268798758459243, -0.5578149944602171, 0.2813910456659647],
[-0.0405757452148008, 1.1122868032803170, -0.0717110580655164],
[-0.0763729366746601, -0.4214933324022432, 1.5869240198367816]
];
const OKLabtoLMS = [
[1.0000000000000000, 0.3963377773761749, 0.2158037573099136],
[1.0000000000000000, -0.1055613458156586, -0.0638541728258133],
[1.0000000000000000, -0.0894841775298119, -1.2914855480194092]
];
const LMSnl = multiplyMatrices(OKLabtoLMS, [l, a, b]);
const xyz = multiplyMatrices(LMStoXYZ, LMSnl.map((c) => c ** 3));
if (alpha != null) {
xyz.push(alpha);
}
return xyz;
}
// from https://www.w3.org/TR/css-color-4/#color-conversion-code
function OKLab_to_sRGB(l, a, b) {
let L = Math.pow(l * 0.99999999845051981432 +
0.39633779217376785678 * a +
0.21580375806075880339 * b, 3);
let M = Math.pow(l * 1.0000000088817607767 -
0.1055613423236563494 * a -
0.063854174771705903402 * b, 3);
let S = Math.pow(l * 1.0000000546724109177 -
0.089484182094965759684 * a -
1.2914855378640917399 * b, 3);
return lsrgb2srgbvalues(
/* r: */
4.076741661347994 * L -
3.307711590408193 * M +
0.230969928729428 * S,
/* g: */
-1.2684380040921763 * L +
2.6097574006633715 * M -
0.3413193963102197 * S,
/* b: */
-0.004196086541837188 * L -
0.7034186144594493 * M +
1.7076147009309444 * S);
}
/*
*/
function xyzd502lch(x, y, z, alpha) {
// @ts-ignore
const [l, a, b] = xyz2lab(...XYZ_D50_to_D65(x, y, z));
// L in range [0,100]. For use in CSS, add a percent
return lab2lchvalues(l, a, b, alpha);
}
function XYZ_D65_to_D50(x, y, z) {
// Bradford chromatic adaptation from D65 to D50
// The matrix below is the result of three operations:
// - convert from XYZ to retinal cone domain
// - scale components from one reference white to another
// - convert back to XYZ
// see https://github.com/LeaVerou/color.js/pull/354/files
var M = [
[1.0479297925449969, 0.022946870601609652, -0.05019226628920524],
[0.02962780877005599, 0.9904344267538799, -0.017073799063418826],
[-0.009243040646204504, 0.015055191490298152, 0.7518742814281371]
];
return multiplyMatrices(M, [x, y, z]);
}
function xyzd502srgb(x, y, z) {
// @ts-ignore
return lsrgb2srgbvalues(
/* r: */
x * 3.1341359569958707 -
y * 1.6173863321612538 -
0.4906619460083532 * z,
/* g: */
x * -0.978795502912089 +
y * 1.916254567259524 +
0.03344273116131949 * z,
/* b: */
x * 0.07195537988411677 -
y * 0.2289768264158322 +
1.405386058324125 * z);
}
// L: 0% = 0.0, 100% = 100.0
// for a and b: -100% = -125, 100% = 125
function hex2lab(token) {
// @ts-ignore
return srgb2lab(...hex2srgb(token));
}
function rgb2lab(token) {
// @ts-ignore
return srgb2lab(...rgb2srgb(token));
}
function hsl2lab(token) {
// @ts-ignore
return srgb2lab(...hsl2srgb(token));
}
function hwb2lab(token) {
// @ts-ignore
return srgb2lab(...hwb2srgb(token));
}
function lch2lab(token) {
// @ts-ignore
return lch2labvalues(...getLCHComponents(token));
}
function oklab2lab(token) {
// @ts-ignore
return xyz2lab(...OKLab_to_XYZ(...getOKLABComponents(token)));
}
function oklch2lab(token) {
// @ts-ignore
return srgb2lab(...oklch2srgb(token));
}
function srgb2lab(r, g, b, a) {
// @ts-ignore */
const result = xyz2lab(...srgb2xyz(r, g, b));
// Fixes achromatic RGB colors having a _slight_ chroma due to floating-point errors
// and approximated computations in sRGB <-> CIELab.
// See: https://github.com/d3/d3-color/pull/46
if (r === b && b === g) {
result[1] = result[2] = 0;
}
if (a != null) {
result.push(a);
}
return result;
}
function xyz2lab(x, y, z, a = null) {
// Assuming XYZ is relative to D50, convert to CIE Lab
// from CIE standard, which now defines these as a rational fraction
// var e = 216/24389; // 6^3/29^3
// var k = 24389/27; // 29^3/3^3
// compute xyz, which is XYZ scaled relative to reference white
const xyz = [x, y, z].map((value, i) => value / D50[i]);
// now compute f
const f = xyz.map((value) => value > e ? Math.cbrt(value) : (k * value + 16) / 116);
const result = [
(116 * f[1]) - 16, // L
500 * (f[0] - f[1]), // a
200 * (f[1] - f[2]) // b
];
// L in range [0,100]. For use in CSS, add a percent
if (a != null && a != 1) {
result.push(a);
}
return result;
}
function lch2labvalues(l, c, h, a = null) {
// l, c * Math.cos(360 * h * Math.PI / 180), c * Math.sin(360 * h * Math.PI / 180
const result = [l, c * Math.cos(h * Math.PI / 180), c * Math.sin(h * Math.PI / 180)];
if (a != null) {
result.push(a);
}
return result;
}
function getLABComponents(token) {
const components = getComponents(token);
// @ts-ignore
let t = components[0];
// @ts-ignore
const l = getNumber(t) * (t.typ == exports.EnumToken.PercentageTokenType ? 100 : 1);
// @ts-ignore
t = components[1];
// @ts-ignore
const a = getNumber(t) * (t.typ == exports.EnumToken.PercentageTokenType ? 125 : 1);
// @ts-ignore
t = components[2];
// @ts-ignore
const b = getNumber(t) * (t.typ == exports.EnumToken.PercentageTokenType ? 125 : 1);
// @ts-ignore
t = components[3];
// @ts-ignore
const alpha = t == null ? 1 : getNumber(t);
const result = [l, a, b];
if (alpha != null && alpha != 1) {
result.push(alpha);
}
return result;
}
// from https://www.w3.org/TR/css-color-4/#color-conversion-code
// D50 LAB
function Lab_to_sRGB(l, a, b) {
// @ts-ignore
return xyzd502srgb(...Lab_to_XYZ(l, a, b));
}
// from https://www.w3.org/TR/css-color-4/#color-conversion-code
function Lab_to_XYZ(l, a, b) {
// Convert Lab to D50-adapted XYZ
// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
const k = 24389 / 27; // 29^3/3^3
const e = 216 / 24389; // 6^3/29^3
const f = [];
// compute f, starting with the luminance-related term
f[1] = (l + 16) / 116;
f[0] = a / 500 + f[1];
f[2] = f[1] - b / 200;
// compute xyz
const xyz = [
Math.pow(f[0], 3) > e ? Math.pow(f[0], 3) : (116 * f[0] - 16) / k,
l > k * e ? Math.pow((l + 16) / 116, 3) : l / k,
Math.pow(f[2], 3) > e ? Math.pow(f[2], 3) : (116 * f[2] - 16) / k
];
// Compute XYZ by scaling xyz by reference white
return xyz.map((value, i) => value * D50[i]);
}
// from https://www.w3.org/TR/css-color-4/#color-conversion-code
// srgb-linear -> srgb
// 0 <= r, g, b <= 1
function srgbvalues(token) {
switch (token.kin) {
case 'lit':
case 'hex':
return hex2srgb(token);
case 'rgb':
case 'rgba':
return rgb2srgb(token);
case 'hsl':
case 'hsla':
return hsl2srgb(token);
case 'hwb':
return hwb2srgb(token);
case 'lab':
return lab2srgb(token);
case 'lch':
return lch2srgb(token);
case 'oklab':
return oklab2srgb(token);
case 'oklch':
return oklch2srgb(token);
case 'color':
return color2srgbvalues(token);
}
return null;
}
function rgb2srgb(token) {
return getComponents(token).map((t, index) => index == 3 ? ((t.typ == exports.EnumToken.IdenTokenType && t.val == 'none') ? 1 : getNumber(t)) : (t.typ == exports.EnumToken.PercentageTokenType ? 255 : 1) * getNumber(t) / 255);
}
function hex2srgb(token) {
const value = expandHexValue(token.kin == 'lit' ? COLORS_NAMES[token.val.toLowerCase()] : token.val);
const rgb = [];
for (let i = 1; i < value.length; i += 2) {
rgb.push(parseInt(value.slice(i, i + 2), 16) / 255);
}
return rgb;
}
function xyz2srgb(x, y, z) {
// @ts-ignore
return lsrgb2srgbvalues(...XYZ_to_lin_sRGB(x, y, z));
}
function hwb2srgb(token) {
const { h: hue, s: white, l: black, a: alpha } = hslvalues(token);
const rgb = hsl2srgbvalues(hue, 1, .5);
for (let i = 0; i < 3; i++) {
rgb[i] *= (1 - white - black);
rgb[i] = rgb[i] + white;
}
if (alpha != null && alpha != 1) {
rgb.push(alpha);
}
return rgb;
}
function hsl2srgb(token) {
let { h, s, l, a } = hslvalues(token);
return hsl2srgbvalues(h, s, l, a);
}
function cmyk2srgb(token) {
const components = getComponents(token);
// @ts-ignore
let t = components[0];
// @ts-ignore
const c = getNumber(t);
// @ts-ignore
t = components[1];
// @ts-ignore
const m = getNumber(t);
// @ts-ignore
t = components[2];
// @ts-ignore
const y = getNumber(t);
// @ts-ignore
t = components[3];
// @ts-ignore
const k = getNumber(t);
const rgb = [
1 - Math.min(1, c * (1 - k) + k),
1 - Math.min(1, m * (1 - k) + k),
1 - Math.min(1, y * (1 - k) + k)
];
// @ts-ignore
if (token.chi.length >= 9) {
// @ts-ignore
t = token.chi[8];
// @ts-ignore
rgb.push(getNumber(t));
}
return rgb;
}
function oklab2srgb(token) {
const [l, a, b, alpha] = getOKLABComponents(token);
const rgb = OKLab_to_sRGB(l, a, b);
if (alpha != null && alpha != 1) {
rgb.push(alpha);
}
return rgb;
}
function oklch2srgb(token) {
const [l, c, h, alpha] = getOKLCHComponents(token);
// @ts-ignore
const rgb = OKLab_to_sRGB(...lch2labvalues(l, c, h));
if (alpha != 1) {
rgb.push(alpha);
}
return rgb;
}
function hslvalues(token) {
const components = getComponents(token);
let t;
// @ts-ignore
let h = getAngle(components[0]);
// @ts-ignore
t = components[1];
// @ts-ignore
let s = getNumber(t);
// @ts-ignore
t = components[2];
// @ts-ignore
let l = getNumber(t);
let a = null;
if (token.chi?.length == 4) {
// @ts-ignore
t = token.chi[3];
// @ts-ignore
a = getNumber(t);
}
return a == null ? { h, s, l } : { h, s, l, a };
}
function hsl2srgbvalues(h, s, l, a = null) {
let v = l <= .5 ? l * (1.0 + s) : l + s - l * s;
let r = l;
let g = l;
let b = l;
if (v > 0) {
let m = l + l - v;
let sv = (v - m) / v;
h *= 6.0;
let sextant = Math.floor(h);
let fract = h - sextant;
let vsf = v * sv * fract;
let mid1 = m + vsf;
let mid2 = v - vsf;
switch (sextant) {
case 0:
r = v;
g = mid1;
b = m;
break;
case 1:
r = mid2;
g = v;
b = m;
break;
case 2:
r = m;
g = v;
b = mid1;
break;
case 3:
r = m;
g = mid2;
b = v;
break;
case 4:
r = mid1;
g = m;
b = v;
break;
case 5:
r = v;
g = m;
b = mid2;
break;
}
}
const values = [r, g, b];
if (a != null && a != 1) {
values.push(a);
}
return values;
}
function lab2srgb(token) {
const [l, a, b, alpha] = getLABComponents(token);
const rgb = Lab_to_sRGB(l, a, b);
if (alpha != null && alpha != 1) {
rgb.push(alpha);
}
return rgb;
}
function lch2srgb(token) {
// @ts-ignore
const [l, a, b, alpha] = lch2labvalues(...getLCHComponents(token));
// https://www.w3.org/TR/css-color-4/#lab-to-lch
const rgb = Lab_to_sRGB(l, a, b);
if (alpha != 1) {
rgb.push(alpha);
}
return rgb;
}
// sRGB -> lRGB
function srgb2lsrgbvalues(r, g, b, a = null) {
// convert an array of linear-light sRGB values in the range 0.0-1.0
// to gamma corrected form
// https://en.wikipedia.org/wiki/SRGB
// Extended transfer function:
// For negative values, linear portion extends on reflection
// of axis, then uses reflected pow below that
const rgb = [r, g, b].map((val) => {
const abs = Math.abs(val);
if (abs <= 0.04045) {
return val / 12.92;
}
return (Math.sign(val) || 1) * Math.pow((abs + 0.055) / 1.055, 2.4);
});
if (a != 1 && a != null) {
rgb.push(a);
}
return rgb;
}
function lsrgb2srgbvalues(r, g, b, alpha) {
// convert an array of linear-light sRGB values in the range 0.0-1.0
// to gamma corrected form
// https://en.wikipedia.org/wiki/SRGB
// Extended transfer function:
// For negative values, linear portion extends on reflection
// of axis, then uses reflected pow below that
const rgb = [r, g, b].map((val) => {
let abs = Math.abs(val);
if (Math.abs(val) > 0.0031308) {
return (Math.sign(val) || 1) * (1.055 * Math.pow(abs, 1 / 2.4) - 0.055);
}
return 12.92 * val;
});
if (alpha != 1 && alpha != null) {
rgb.push(alpha);
}
return rgb;
}
function srgb2rgb(value) {
return minmax(Math.round(value * 255), 0, 255);
}
function hex2rgb(token) {
const value = expandHexValue(token.kin == 'lit' ? COLORS_NAMES[token.val.toLowerCase()] : token.val);
const rgb = [];
for (let i = 1; i < value.length; i += 2) {
rgb.push(parseInt(value.slice(i, i + 2), 16));
}
return rgb;
}
function hwb2rgb(token) {
return hwb2srgb(token).map(srgb2rgb);
}
function hsl2rgb(token) {
let { h, s, l, a } = hslvalues(token);
return hsl2srgbvalues(h, s, l, a).map((t) => minmax(Math.round(t * 255), 0, 255));
}
function cmyk2rgb(token) {
return cmyk2srgb(token).map(srgb2rgb);
}
function oklab2rgb(token) {
return oklab2srgb(token).map(srgb2rgb);
}
function oklch2rgb(token) {
return oklch2srgb(token).map(srgb2rgb);
}
function lab2rgb(token) {
return lab2srgb(token).map(srgb2rgb);
}
function lch2rgb(token) {
return lch2srgb(token).map(srgb2rgb);
}
function hwb2hsv(h, w, b, a) {
// @ts-ignore
return [h, 1 - w / (1 - b), 1 - b, a];
}
// https://gist.github.com/defims/0ca2ef8832833186ed396a2f8a204117#file-annotated-js
function hsl2hsv(h, s, l, a = null) {
s *= l < .5 ? l : 1 - l;
const result = [
//Range should be between 0 - 1
h, //Hue stays the same
2 * s / (l + s), //Saturation
l + s //Value
];
if (a != null) {
result.push(a);
}
return result;
}
function hex2hsl(token) {
// @ts-ignore
return rgb2hslvalues(...hex2rgb(token));
}
function rgb2hsl(token) {
const chi = getComponents(token);
// @ts-ignore
let t = chi[0];
// @ts-ignore
let r = getNumber(t);
// @ts-ignore
t = chi[1];
// @ts-ignore
let g = getNumber(t);
// @ts-ignore
t = chi[2];
// @ts-ignore
let b = getNumber(t);
// @ts-ignore
t = chi[3];
// @ts-ignore
let a = null;
if (t != null && !(t.typ == exports.EnumToken.IdenTokenType && t.val == 'none')) {
// @ts-ignore
a = getNumber(t) / 255;
}
const values = [r, g, b];
if (a != null && a != 1) {
values.push(a);
}
// @ts-ignore
return rgb2hslvalues(...values);
}
// https://gist.github.com/defims/0ca2ef8832833186ed396a2f8a204117#file-annotated-js
function hsv2hsl(h, s, v, a) {
const result = [
//[hue, saturation, lightness]
//Range should be between 0 - 1
h, //Hue stays the same
//Saturation is very different between the two color spaces
//If (2-sat)*val < 1 set it to sat*val/((2-sat)*val)
//Otherwise sat*val/(2-(2-sat)*val)
//Conditional is not operating with hue, it is reassigned!
s * v / ((h = (2 - s) * v) < 1 ? h : 2 - h),
h / 2, //Lightness is (2-sat)*val/2
];
if (a != null) {
result.push(a);
}
return result;
}
function hwb2hsl(token) {
// @ts-ignore
return hsv2hsl(...hwb2hsv(...Object.values(hslvalues(token))));
}
function lab2hsl(token) {
// @ts-ignore
return rgb2hslvalues(...lab2rgb(token));
}
function lch2hsl(token) {
// @ts-ignore
return rgb2hslvalues(...lch2rgb(token));
}
function oklab2hsl(token) {
// @ts-ignore
return rgb2hslvalues(...oklab2rgb(token));
}
function oklch2hsl(token) {
// @ts-ignore
return rgb2hslvalues(...oklch2rgb(token));
}
function rgb2hslvalues(r, g, b, a = null) {
return srgb2hsl(r / 255, g / 255, b / 255, a);
}
function srgb2hsl(r, g, b, a = null) {
let max = Math.max(r, g, b);
let min = Math.min(r, g, b);
let h = 0;
let s = 0;
let l = (max + min) / 2;
if (max != min) {
let d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
}
h /= 6;
}
const hsl = [h, s, l];
if (a != null && a < 1) {
// @ts-ignore
return hsl.concat([a]);
}
// @ts-ignore
return hsl;
}
function rgb2hwb(token) {
// @ts-ignore
return srgb2hwb(...getComponents(token).map((t, index) => {
if (index == 3 && t.typ == exports.EnumToken.IdenTokenType && t.val == 'none') {
return 1;
}
return getNumber(t) / 255;
}));
}
function hsl2hwb(token) {
// @ts-ignore
return hsl2hwbvalues(...getComponents(token).map((t, index) => {
if (index == 3 && (t.typ == exports.EnumToken.IdenTokenType && t.val == 'none')) {
return 1;
}
if (index == 0) {
return getAngle(t);
}
return getNumber(t);
}));
}
function lab2hwb(token) {
// @ts-ignore
return srgb2hwb(...lab2srgb(token));
}
function lch2hwb(token) {
// @ts-ignore
return srgb2hwb(...lch2srgb(token));
}
function oklab2hwb(token) {
// @ts-ignore
return srgb2hwb(...oklab2srgb(token));
}
function oklch2hwb(token) {
// @ts-ignore
return srgb2hwb(...oklch2srgb(token));
}
function rgb2hue(r, g, b, fallback = 0) {
let value = rgb2value(r, g, b);
let whiteness = rgb2whiteness(r, g, b);
let delta = value - whiteness;
if (delta > 0) {
// calculate segment
let segment = value === r ? (g - b) / delta : (value === g
? (b - r) / delta
: (r - g) / delta);
// calculate shift
let shift = value === r ? segment < 0
? 360 / 60
: 0 / 60 : (value === g
? 120 / 60
: 240 / 60);
// calculate hue
return (segment + shift) * 60;
}
return fallback;
}
function rgb2value(r, g, b) {
return Math.max(r, g, b);
}
function rgb2whiteness(r, g, b) {
return Math.min(r, g, b);
}
function srgb2hwb(r, g, b, a = null, fallback = 0) {
r *= 100;
g *= 100;
b *= 100;
let hue = rgb2hue(r, g, b, fallback);
let whiteness = rgb2whiteness(r, g, b);
let value = Math.round(rgb2value(r, g, b));
let blackness = 100 - value;
const result = [hue / 360, whiteness / 100, blackness / 100];
if (a != null) {
result.push(a);
}
return result;
}
function hsv2hwb(h, s, v, a = null) {
const result = [h, (1 - s) * v, 1 - v];
if (a != null) {
result.push(a);
}
return result;
}
function hsl2hwbvalues(h, s, l, a = null) {
// @ts-ignore
return hsv2hwb(...hsl2hsv(h, s, l, a));
}
function prophotorgb2srgbvalues(r, g, b, a = null) {
// @ts-ignore
return xyzd502srgb(...prophotorgb2xyz50(r, g, b, a));
}
function srgb2prophotorgbvalues(r, g, b, a) {
// @ts-ignore
return xyz50_to_prophotorgb(...XYZ_D65_to_D50(...srgb2xyz(r, g, b, a)));
}
function prophotorgb2lin_ProPhoto(r, g, b, a = null) {
return [r, g, b].map(v => {
let abs = Math.abs(v);
if (abs >= 16 / 512) {
return Math.sign(v) * Math.pow(abs, 1.8);
}
return v / 16;
}).concat(a == null || a == 1 ? [] : [a]);
}
function prophotorgb2xyz50(r, g, b, a = null) {
[r, g, b, a] = prophotorgb2lin_ProPhoto(r, g, b, a);
const xyz = [
0.7977666449006423 * r +
0.1351812974005331 * g +
0.0313477341283922 * b,
0.2880748288194013 * r +
0.7118352342418731 * g +
0.0000899369387256 * b,
0.8251046025104602 * b
];
return xyz.concat(a == null || a == 1 ? [] : [a]);
}
function xyz50_to_prophotorgb(x, y, z, a) {
// @ts-ignore
return gam_prophotorgb(...[
x * 1.3457868816471585 -
y * 0.2555720873797946 -
0.0511018649755453 * z,
x * -0.5446307051249019 +
y * 1.5082477428451466 +
0.0205274474364214 * z,
1.2119675456389452 * z
].concat(a == null || a == 1 ? [] : [a]));
}
function gam_prophotorgb(r, g, b, a) {
return [r, g, b].map(v => {
let abs = Math.abs(v);
if (abs >= 1 / 512) {
return Math.sign(v) * Math.pow(abs, 1 / 1.8);
}
return 16 * v;
}).concat(a == null || a == 1 ? [] : [a]);
}
function a98rgb2srgbvalues(r, g, b, a = null) {
// @ts-ignore
return xyz2srgb(...la98rgb2xyz(...a98rgb2la98(r, g, b, a)));
}
function srgb2a98values(r, g, b, a = null) {
// @ts-ignore
return la98rgb2a98rgb(xyz2la98rgb(...srgb2xyz(r, g, b, a)));
}
// a98-rgb functions
function a98rgb2la98(r, g, b, a = null) {
// convert an array of a98-rgb values in the range 0.0 - 1.0
// to linear light (un-companded) form.
// negative values are also now accepted
return [r, g, b].map(function (val) {
let sign = val < 0 ? -1 : 1;
let abs = Math.abs(val);
return sign * Math.pow(abs, 563 / 256);
}).concat(a == null || a == 1 ? [] : [a]);
}
function la98rgb2a98rgb(r, g, b, a = null) {
// convert an array of linear-light a98-rgb in the range 0.0-1.0
// to gamma corrected form
// negative values are also now accepted
return [r, b, g].map(function (val) {
let sign = val < 0 ? -1 : 1;
let abs = Math.abs(val);
return sign * Math.pow(abs, 256 / 563);
}).concat(a == null || a == 1 ? [] : [a]);
}
function la98rgb2xyz(r, g, b, a = null) {
// convert an array of linear-light a98-rgb values to CIE XYZ
// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
// has greater numerical precision than section 4.3.5.3 of
// https://www.adobe.com/digitalimag/pdfs/AdobeRGB1998.pdf
// but the values below were calculated from first principles
// from the chromaticity coordinates of R G B W
// see matrixmaker.html
var M = [
[573536 / 994567, 263643 / 1420810, 187206 / 994567],
[591459 / 1989134, 6239551 / 9945670, 374412 / 4972835],
[53769 / 1989134, 351524 / 4972835, 4929758 / 4972835],
];
return multiplyMatrices(M, [r, g, b]).concat(a == null || a == 1 ? [] : [a]);
}
function xyz2la98rgb(x, y, z, a = null) {
// convert XYZ to linear-light a98-rgb
var M = [
[1829569 / 896150, -506331 / 896150, -308931 / 896150],
[-851781 / 878810, 1648619 / 878810, 36519 / 878810],
[16779 / 1248040, -147721 / 1248040, 1266979 / 1248040],
];
return multiplyMatrices(M, [x, y, z]).concat(a == null || a == 1 ? [] : [a]);
}
function rec20202srgb(r, g, b, a) {
// @ts-ignore
return xyz2srgb(...lrec20202xyz(...rec20202lrec2020(r, g, b)), a);
}
function srgb2rec2020values(r, g, b, a) {
// @ts-ignore
return lrec20202rec2020(...xyz2lrec2020(...srgb2xyz(r, g, b)), a);
}
function rec20202lrec2020(r, g, b, a) {
// convert an array of rec2020 RGB values in the range 0.0 - 1.0
// to linear light (un-companded) form.
// ITU-R BT.2020-2 p.4
const α = 1.09929682680944;
const β = 0.018053968510807;
return [r, g, b].map(function (val) {
let sign = val < 0 ? -1 : 1;
let abs = Math.abs(val);
if (abs < β * 4.5) {
return val / 4.5;
}
return sign * (Math.pow((abs + α - 1) / α, 1 / 0.45));
}).concat([] );
}
function lrec20202rec2020(r, g, b, a) {
// convert an array of linear-light rec2020 RGB in the range 0.0-1.0
// to gamma corrected form
// ITU-R BT.2020-2 p.4
const α = 1.09929682680944;
const β = 0.018053968510807;
return [r, g, b].map(function (val) {
let sign = val < 0 ? -1 : 1;
let abs = Math.abs(val);
if (abs > β) {
return sign * (α * Math.pow(abs, 0.45) - (α - 1));
}
return 4.5 * val;
}).concat(a == null || a == 1 ? [] : [a]);
}
function lrec20202xyz(r, g, b, a) {
// convert an array of linear-light rec2020 values to CIE XYZ
// using D65 (no chromatic adaptation)
// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
var M = [
[63426534 / 99577255, 20160776 / 139408157, 47086771 / 278816314],
[26158966 / 99577255, 472592308 / 697040785, 8267143 / 139408157],
[0, 19567812 / 697040785, 295819943 / 278816314],
];
// 0 is actually calculated as 4.994106574466076e-17
return multiplyMatrices(M, [r, g, b]).concat(a == null || a == 1 ? [] : [a]);
}
function xyz2lrec2020(x, y, z, a) {
// convert XYZ to linear-light rec2020
var M = [
[30757411 / 17917100, -6372589 / 17917100, -4539589 / 17917100],
[-19765991 / 29648200, 47925759 / 29648200, 467509 / 29648200],
[792561 / 44930125, -1921689 / 44930125, 42328811 / 44930125],
];
return multiplyMatrices(M, [x, y, z]).concat(a == null || a == 1 ? [] : [a]);
}
function p32srgbvalues(r, g, b, alpha) {
// @ts-ignore
return xyz2srgb(...lp32xyz(...p32lp3(r, g, b, alpha)));
}
function srgb2p3values(r, g, b, alpha) {
// @ts-ignore
return srgb2xyz(...xyz2lp3(...lp32p3(r, g, b, alpha)));
}
function p32lp3(r, g, b, alpha) {
// convert an array of display-p3 RGB values in the range 0.0 - 1.0
// to linear light (un-companded) form.
return srgb2lsrgbvalues(r, g, b, alpha); // same as sRGB
}
function lp32p3(r, g, b, alpha) {
// convert an array of linear-light display-p3 RGB in the range 0.0-1.0
// to gamma corrected form
return lsrgb2srgbvalues(r, g, b, alpha); // same as sRGB
}
function lp32xyz(r, g, b, alpha) {
// convert an array of linear-light display-p3 values to CIE XYZ
// using D65 (no chromatic adaptation)
// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
const M = [
[608311 / 1250200, 189793 / 714400, 198249 / 1000160],
[35783 / 156275, 247089 / 357200, 198249 / 2500400],
[0, 32229 / 714400, 5220557 / 5000800],
];
const result = multiplyMatrices(M, [r, g, b]);
if (alpha != null && alpha != 1) {
result.push(alpha);
}
return result;
}
function xyz2lp3(x, y, z, alpha) {
// convert XYZ to linear-light P3
const M = [
[446124 / 178915, -333277 / 357830, -72051 / 178915],
[-14852 / 17905, 63121 / 35810, 423 / 17905],
[11844 / 330415, -50337 / 660830, 316169 / 330415],
];
const result = multiplyMatrices(M, [x, y, z]);
if (alpha != null && alpha != 1) {
result.push(alpha);
}
return result;
}
function convert(token, to) {
if (token.kin == to) {
return token;
}
if (token.kin == 'color') {
const colorSpace = token.chi.find(t => ![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType].includes(t.typ));
if (colorSpace.val == to) {
return token;
}
}
let values = [];
if (to == 'hsl') {
switch (token.kin) {
case 'rgb':
case 'rgba':
values.push(...rgb2hsl(token));
break;
case 'hex':
case 'lit':
values.push(...hex2hsl(token));
break;
case 'hwb':
values.push(...hwb2hsl(token));
break;
case 'oklab':
values.push(...oklab2hsl(token));
break;
case 'oklch':
values.push(...oklch2hsl(token));
break;
case 'lab':
values.push(...lab2hsl(token));
break;
case 'lch':
values.push(...lch2hsl(token));
break;
case 'color':
// @ts-ignore
values.push(...srgb2hsl(...color2srgbvalues(token)));
break;
}
if (values.length > 0) {
return values2hsltoken(values);
}
}
else if (to == 'hwb') {
switch (token.kin) {
case 'rgb':
case 'rgba':
values.push(...rgb2hwb(token));
break;
case 'hex':
case 'lit':
values.push(...hex2hsl(token));
break;
case 'hsl':
case 'hsla':
values.push(...hsl2hwb(token));
break;
case 'oklab':
values.push(...oklab2hwb(token));
break;
case 'oklch':
values.push(...oklch2hwb(token));
break;
case 'lab':
values.push(...lab2hwb(token));
break;
case 'lch':
values.push(...lch2hwb(token));
break;
}
if (values.length > 0) {
return values2hwbtoken(values);
}
}
else if (to == 'rgb') {
switch (token.kin) {
case 'hex':
case 'lit':
values.push(...hex2rgb(token));
break;
case 'hsl':
values.push(...hsl2rgb(token));
break;
case 'hwb':
values.push(...hwb2rgb(token));
break;
case 'oklab':
values.push(...oklab2rgb(token));
break;
case 'oklch':
values.push(...oklch2rgb(token));
break;
case 'lab':
values.push(...lab2rgb(token));
break;
case 'lch':
values.push(...lch2rgb(token));
break;
case 'color':
// @ts-ignore
values.push(...srgb2rgb(...color2srgbvalues(token)));
break;
}
if (values.length > 0) {
return values2rgbtoken(values);
}
}
else if (to == 'lab') {
switch (token.kin) {
case 'hex':
case 'lit':
values.push(...hex2lab(token));
break;
case 'rgb':
case 'rgba':
values.push(...rgb2lab(token));
break;
case 'hsl':
case 'hsla':
values.push(...hsl2lab(token));
break;
case 'hwb':
values.push(...hwb2lab(token));
break;
case 'lch':
values.push(...lch2lab(token));
break;
case 'oklab':
values.push(...oklab2lab(token));
break;
case 'oklch':
values.push(...oklch2lab(token));
break;
case 'color':
// @ts-ignore
values.push(...srgb2lab(...color2srgbvalues(token)));
break;
}
if (values.length > 0) {
return values2colortoken(values, to);
}
}
else if (to == 'lch') {
switch (token.kin) {
case 'hex':
case 'lit':
values.push(...hex2lch(token));
break;
case 'rgb':
case 'rgba':
values.push(...rgb2lch(token));
break;
case 'hsl':
case 'hsla':
values.push(...hsl2lch(token));
break;
case 'hwb':
values.push(...hwb2lch(token));
break;
case 'lab':
values.push(...lab2lch(token));
break;
case 'oklab':
values.push(...oklab2lch(token));
break;
case 'oklch':
values.push(...oklch2lch(token));
break;
case 'color':
// @ts-ignore
values.push(...srgb2lch(...color2srgbvalues(token)));
break;
}
if (values.length > 0) {
return values2colortoken(values, to);
}
}
else if (to == 'oklab') {
switch (token.kin) {
case 'hex':
case 'lit':
values.push(...hex2oklab(token));
break;
case 'rgb':
case 'rgba':
values.push(...rgb2oklab(token));
break;
case 'hsl':
case 'hsla':
values.push(...hsl2oklab(token));
break;
case 'hwb':
values.push(...hwb2oklab(token));
break;
case 'lab':
values.push(...lab2oklab(token));
break;
case 'lch':
values.push(...lch2oklab(token));
break;
case 'oklch':
values.push(...oklch2oklab(token));
break;
case 'color':
// @ts-ignore
values.push(...srgb2oklab(...color2srgbvalues(token)));
break;
}
if (values.length > 0) {
return values2colortoken(values, to);
}
}
else if (to == 'oklch') {
switch (token.kin) {
case 'hex':
case 'lit':
values.push(...hex2oklch(token));
break;
case 'rgb':
case 'rgba':
values.push(...rgb2oklch(token));
break;
case 'hsl':
case 'hsla':
values.push(...hsl2oklch(token));
break;
case 'hwb':
values.push(...hwb2oklch(token));
break;
case 'lab':
values.push(...lab2oklch(token));
break;
case 'oklab':
values.push(...oklab2oklch(token));
break;
case 'lch':
values.push(...lch2oklch(token));
break;
case 'color':
// @ts-ignore
let val = color2srgbvalues(token);
switch (to) {
case 'srgb':
values.push(...val);
break;
case 'srgb-linear':
// @ts-ignore
values.push(...srgb2lsrgbvalues(...val));
break;
case 'display-p3':
// @ts-ignore
values.push(...srgb2p3values(...val));
break;
case 'prophoto-rgb':
// @ts-ignore
values.push(...srgb2prophotorgbvalues(...val));
break;
case 'a98-rgb':
// @ts-ignore
values.push(...srgb2a98values(...val));
break;
case 'rec2020':
// @ts-ignore
values.push(...srgb2rec2020values(...val));
break;
case 'xyz':
case 'xyz-d65':
// @ts-ignore
values.push(...srgb2xyz(...val));
break;
case 'xyz-d50':
// @ts-ignore
values.push(...(XYZ_D65_to_D50(...srgb2xyz(...val))));
break;
}
break;
}
if (values.length > 0) {
return values2colortoken(values, to);
}
}
else if (colorFuncColorSpace.includes(to)) {
switch (token.kin) {
case 'hex':
case 'lit':
values.push(...hex2srgb(token));
break;
case 'rgb':
case 'rgba':
values.push(...rgb2srgb(token));
break;
case 'hsl':
case 'hsla':
values.push(...hsl2srgb(token));
break;
case 'hwb':
values.push(...hwb2srgb(token));
break;
case 'lab':
values.push(...lab2srgb(token));
break;
case 'oklab':
values.push(...oklab2srgb(token));
break;
case 'lch':
values.push(...lch2srgb(token));
break;
case 'oklch':
// @ts-ignore
values.push(...srgb2oklch(...color2srgbvalues(token)));
break;
case 'color':
const val = color2srgbvalues(token);
switch (to) {
case 'srgb':
values.push(...val);
break;
case 'srgb-linear':
// @ts-ignore
values.push(...srgb2lsrgbvalues(...val));
break;
case 'display-p3':
// @ts-ignore
values.push(...srgb2p3values(...val));
break;
case 'prophoto-rgb':
// @ts-ignore
values.push(...srgb2prophotorgbvalues(...val));
break;
case 'a98-rgb':
// @ts-ignore
values.push(...srgb2a98values(...val));
break;
case 'rec2020':
// @ts-ignore
values.push(...srgb2rec2020values(...val));
break;
case 'xyz':
case 'xyz-d65':
// @ts-ignore
values.push(...srgb2xyz(...val));
break;
case 'xyz-d50':
// @ts-ignore
values.push(...(XYZ_D65_to_D50(...srgb2xyz(...val))));
break;
}
break;
}
if (values.length > 0) {
return values2colortoken(values, to);
}
}
return null;
}
function minmax(value, min, max) {
if (value < min) {
return min;
}
if (value > max) {
return max;
}
return value;
}
function color2srgbvalues(token) {
const components = getComponents(token);
const colorSpace = components.shift();
let values = components.map((val) => getNumber(val));
switch (colorSpace.val) {
case 'display-p3':
// @ts-ignore
values = p32srgbvalues(...values);
break;
case 'srgb-linear':
// @ts-ignore
values = lsrgb2srgbvalues(...values);
break;
case 'prophoto-rgb':
// @ts-ignore
values = prophotorgb2srgbvalues(...values);
break;
case 'a98-rgb':
// @ts-ignore
values = a98rgb2srgbvalues(...values);
break;
case 'rec2020':
// @ts-ignore
values = rec20202srgb(...values);
break;
case 'xyz':
case 'xyz-d65':
// @ts-ignore
values = xyz2srgb(...values);
break;
case 'xyz-d50':
// @ts-ignore
values = xyzd502srgb(...values);
break;
// case srgb:
}
return values;
}
function values2hsltoken(values) {
const to = 'hsl';
const chi = [
{ typ: exports.EnumToken.AngleTokenType, val: String(values[0] * 360), unit: 'deg' },
{ typ: exports.EnumToken.PercentageTokenType, val: String(values[1] * 100) },
{ typ: exports.EnumToken.PercentageTokenType, val: String(values[2] * 100) },
];
if (values.length == 4) {
chi.push({ typ: exports.EnumToken.PercentageTokenType, val: String(values[3] * 100) });
}
return {
typ: exports.EnumToken.ColorTokenType,
val: to,
chi,
kin: to
};
}
function values2rgbtoken(values) {
const to = 'rgb';
const chi = [
{ typ: exports.EnumToken.NumberTokenType, val: String(values[0]) },
{ typ: exports.EnumToken.NumberTokenType, val: String(values[1]) },
{ typ: exports.EnumToken.NumberTokenType, val: String(values[2]) },
];
if (values.length == 4) {
chi.push({ typ: exports.EnumToken.PercentageTokenType, val: String(values[3] * 100) });
}
return {
typ: exports.EnumToken.ColorTokenType,
val: to,
chi,
kin: to
};
}
function values2hwbtoken(values) {
const to = 'hwb';
const chi = [
{ typ: exports.EnumToken.AngleTokenType, val: String(values[0] * 360), unit: 'deg' },
{ typ: exports.EnumToken.PercentageTokenType, val: String(values[1] * 100) },
{ typ: exports.EnumToken.PercentageTokenType, val: String(values[2] * 100) },
];
if (values.length == 4) {
chi.push({ typ: exports.EnumToken.PercentageTokenType, val: String(values[3] * 100) });
}
return {
typ: exports.EnumToken.ColorTokenType,
val: to,
chi,
kin: to
};
}
function values2colortoken(values, to) {
const chi = [
{ typ: exports.EnumToken.NumberTokenType, val: String(values[0]) },
{ typ: exports.EnumToken.NumberTokenType, val: String(values[1]) },
{ typ: exports.EnumToken.NumberTokenType, val: String(values[2]) },
];
if (values.length == 4) {
chi.push({ typ: exports.EnumToken.PercentageTokenType, val: String(values[3] * 100) });
}
return colorFuncColorSpace.includes(to) ? {
typ: exports.EnumToken.ColorTokenType,
val: 'color',
chi: [{ typ: exports.EnumToken.IdenTokenType, val: to }].concat(chi),
kin: 'color'
} : {
typ: exports.EnumToken.ColorTokenType,
val: to,
chi,
kin: to
};
}
/**
* clamp color values
* @param token
*/
function clamp(token) {
if (token.kin == 'rgb' || token.kin == 'rgba') {
token.chi.filter((token) => ![exports.EnumToken.LiteralTokenType, exports.EnumToken.CommaTokenType, exports.EnumToken.WhitespaceTokenType].includes(token.typ)).forEach((token, index) => {
if (index <= 2) {
if (token.typ == exports.EnumToken.NumberTokenType) {
token.val = String(minmax(+token.val, 0, 255));
}
else if (token.typ == exports.EnumToken.PercentageTokenType) {
token.val = String(minmax(+token.val, 0, 100));
}
}
else {
if (token.typ == exports.EnumToken.NumberTokenType) {
token.val = String(minmax(+token.val, 0, 1));
}
else if (token.typ == exports.EnumToken.PercentageTokenType) {
token.val = String(minmax(+token.val, 0, 100));
}
}
});
}
return token;
}
function getNumber(token) {
if (token.typ == exports.EnumToken.IdenTokenType && token.val == 'none') {
return 0;
}
// @ts-ignore
return token.typ == exports.EnumToken.PercentageTokenType ? token.val / 100 : +token.val;
}
function getAngle(token) {
if (token.typ == exports.EnumToken.IdenTokenType) {
if (token.val == 'none') {
return 0;
}
}
if (token.typ == exports.EnumToken.AngleTokenType) {
switch (token.unit) {
case 'deg':
// @ts-ignore
return token.val / 360;
case 'rad':
// @ts-ignore
return token.val / (2 * Math.PI);
case 'grad':
// @ts-ignore
return token.val / 400;
case 'turn':
// @ts-ignore
return +token.val;
}
}
// @ts-ignore
return token.val / 360;
}
function interpolateHue(interpolationMethod, h1, h2) {
switch (interpolationMethod.val) {
case 'longer':
if (h2 - h1 < 180 && h2 - h1 > 0) {
h1 += 360;
}
else if (h2 - h1 <= 0 && h2 - h1 > -180) {
h2 += 360;
}
break;
case 'increasing':
if (h2 < h1) {
h2 += 360;
}
break;
case 'decreasing':
if (h2 > h1) {
h1 += 360;
}
break;
case 'shorter':
default:
// shorter
if (h2 - h1 > 180) {
h1 += 360;
}
else if (h2 - h1 < -180) {
h2 += 360;
}
break;
}
return [h1, h2];
}
function colorMix(colorSpace, hueInterpolationMethod, color1, percentage1, color2, percentage2) {
if (hueInterpolationMethod != null && isRectangularOrthogonalColorspace(colorSpace)) {
return null;
}
if (isPolarColorspace(colorSpace) && hueInterpolationMethod == null) {
hueInterpolationMethod = { typ: exports.EnumToken.IdenTokenType, val: 'shorter' };
}
if (percentage1 == null) {
if (percentage2 == null) {
// @ts-ignore
percentage1 = { typ: exports.EnumToken.NumberTokenType, val: '.5' };
// @ts-ignore
percentage2 = { typ: exports.EnumToken.NumberTokenType, val: '.5' };
}
else {
if (+percentage2.val <= 0) {
return null;
}
if (+percentage2.val >= 100) {
// @ts-ignore
percentage2 = { typ: exports.EnumToken.NumberTokenType, val: '1' };
}
// @ts-ignore
percentage1 = { typ: exports.EnumToken.NumberTokenType, val: String(1 - percentage2.val / 100) };
}
}
else {
// @ts-ignore
if (percentage1.val <= 0) {
return null;
}
if (percentage2 == null) {
// @ts-ignore
if (percentage1.val >= 100) {
// @ts-ignore
percentage1 = { typ: exports.EnumToken.NumberTokenType, val: '1' };
}
// @ts-ignore
percentage2 = { typ: exports.EnumToken.NumberTokenType, val: String(1 - percentage1.val / 100) };
}
else {
// @ts-ignore
if (percentage2.val <= 0) {
return null;
}
}
}
let values1 = srgbvalues(color1);
let values2 = srgbvalues(color2);
if (values1 == null || values2 == null) {
return null;
}
const components1 = getComponents(color1);
const components2 = getComponents(color2);
if ((components1[3] != null && components1[3].typ == exports.EnumToken.IdenTokenType && components1[3].val == 'none') && values2.length == 4) {
values1[3] = values2[3];
}
if ((components2[3] != null && components2[3].typ == exports.EnumToken.IdenTokenType && components2[3].val == 'none') && values1.length == 4) {
values2[3] = values1[3];
}
const p1 = getNumber(percentage1);
const p2 = getNumber(percentage2);
const mul1 = values1.length == 4 ? values1.pop() : 1;
const mul2 = values2.length == 4 ? values2.pop() : 1;
const mul = mul1 * p1 + mul2 * p2;
// @ts-ignore
const calculate = () => [colorSpace].concat(values1.map((v1, i) => {
return {
// @ts-ignore
typ: exports.EnumToken.NumberTokenType, val: String((mul1 * v1 * p1 + mul2 * values2[i] * p2) / mul)
};
}).concat(mul == 1 ? [] : [{
typ: exports.EnumToken.NumberTokenType, val: String(mul)
}]));
switch (colorSpace.val) {
case 'srgb':
break;
case 'display-p3':
// @ts-ignore
values1 = srgb2p3values(...values1);
// @ts-ignore
values2 = srgb2p3values(...values2);
break;
case 'a98-rgb':
// @ts-ignore
values1 = srgb2a98values(...values1);
// @ts-ignore
values2 = srgb2a98values(...values2);
break;
case 'prophoto-rgb':
// @ts-ignore
values1 = srgb2prophotorgbvalues(...values1);
// @ts-ignore
values2 = srgb2prophotorgbvalues(...values2);
break;
case 'srgb-linear':
// @ts-ignore
values1 = srgb2lsrgbvalues(...values1);
// @ts-ignore
values2 = srgb2lsrgbvalues(...values2);
break;
case 'rec2020':
// @ts-ignore
values1 = srgb2rec2020values(...values1);
// @ts-ignore
values2 = srgb2rec2020values(...values2);
break;
case 'xyz':
case 'xyz-d65':
case 'xyz-d50':
// @ts-ignore
values1 = srgb2xyz(...values1);
// @ts-ignore
values2 = srgb2xyz(...values2);
if (colorSpace.val == 'xyz-d50') {
// @ts-ignore
values1 = XYZ_D65_to_D50(...values1);
// @ts-ignore
values2 = XYZ_D65_to_D50(...values2);
}
break;
case 'rgb':
// @ts-ignore
values1 = srgb2rgb(...values1);
// @ts-ignore
values2 = srgb2rgb(...values2);
break;
case 'hsl':
// @ts-ignore
values1 = srgb2hsl(...values1);
// @ts-ignore
values2 = srgb2hsl(...values2);
break;
case 'hwb':
// @ts-ignore
values1 = srgb2hwb(...values1);
// @ts-ignore
values2 = srgb2hwb(...values2);
break;
case 'lab':
// @ts-ignore
values1 = srgb2lab(...values1);
// @ts-ignore
values2 = srgb2lab(...values2);
break;
case 'lch':
// @ts-ignore
values1 = srgb2lch(...values1);
// @ts-ignore
values2 = srgb2lch(...values2);
break;
case 'oklab':
// @ts-ignore
values1 = srgb2oklab(...values1);
// @ts-ignore
values2 = srgb2oklab(...values2);
break;
case 'oklch':
// @ts-ignore
values1 = srgb2oklch(...values1);
// @ts-ignore
values2 = srgb2oklch(...values2);
break;
default:
return null;
}
const lchSpaces = ['lch', 'oklch'];
// powerless
if (lchSpaces.includes(color1.kin) || lchSpaces.includes(colorSpace.val)) {
if ((components1[2].typ == exports.EnumToken.IdenTokenType && components1[2].val == 'none') || values1[2] == 0) {
values1[2] = values2[2];
}
}
// powerless
if (lchSpaces.includes(color1.kin) || lchSpaces.includes(colorSpace.val)) {
if ((components2[2].typ == exports.EnumToken.IdenTokenType && components2[2].val == 'none') || values2[2] == 0) {
values2[2] = values1[2];
}
}
if (hueInterpolationMethod != null) {
let hueIndex = 2;
let multiplier = 1;
if (['hwb', 'hsl'].includes(colorSpace.val)) {
hueIndex = 0;
multiplier = 360;
}
const [h1, h2] = interpolateHue(hueInterpolationMethod, values1[hueIndex] * multiplier, values2[hueIndex] * multiplier);
values1[hueIndex] = h1 / multiplier;
values2[hueIndex] = h2 / multiplier;
}
switch (colorSpace.val) {
case 'xyz':
case 'xyz-d65':
case 'xyz-d50':
let values = values1.map((v1, i) => (mul1 * v1 * p1 + mul2 * values2[i] * p2) / mul)
.concat(mul == 1 ? [] : [mul]);
if (colorSpace.val == 'xyz-d50') {
// @ts-ignore
values = xyzd502lch(...values);
}
else {
// @ts-ignore
values = xyz2lchvalues(...values);
}
// @ts-ignore
return {
typ: exports.EnumToken.ColorTokenType,
val: 'lch',
chi: values.map(v => {
return {
typ: exports.EnumToken.NumberTokenType,
val: String(v)
};
}),
kin: 'lch'
};
case 'srgb':
case 'srgb-linear':
case 'a98-rgb':
case 'rec2020':
// @ts-ignore
return {
typ: exports.EnumToken.ColorTokenType,
val: 'color',
chi: calculate(),
kin: 'color',
cal: 'col'
};
case 'rgb':
case 'hsl':
case 'hwb':
case 'lab':
case 'lch':
case 'oklab':
case 'oklch':
if (['hsl', 'hwb'].includes(colorSpace.val)) {
// @ts-ignore
if (values1[2] < 0) {
// @ts-ignore
values1[2] += 1;
}
// @ts-ignore
if (values2[2] < 0) {
// @ts-ignore
values2[2] += 1;
}
}
else if (['lch', 'oklch'].includes(colorSpace.val)) {
// @ts-ignore
if (values1[2] < 0) {
// @ts-ignore
values1[2] += 360;
}
// @ts-ignore
if (values2[2] < 0) {
// @ts-ignore
values2[2] += 360;
}
}
// @ts-ignore
const result = {
typ: exports.EnumToken.ColorTokenType,
val: colorSpace.val,
chi: calculate().slice(1),
kin: colorSpace.val
};
if (colorSpace.val == 'hsl' || colorSpace.val == 'hwb') {
// @ts-ignore
result.chi[0] = { typ: exports.EnumToken.AngleTokenType, val: String(result.chi[0].val * 360), unit: 'deg' };
// @ts-ignore
result.chi[1] = { typ: exports.EnumToken.PercentageTokenType, val: String(result.chi[1].val * 100) };
// @ts-ignore
result.chi[2] = { typ: exports.EnumToken.PercentageTokenType, val: String(result.chi[2].val * 100) };
}
return result;
}
return null;
}
function gcd(x, y) {
x = Math.abs(x);
y = Math.abs(y);
let t;
if (x == 0 || y == 0) {
return 1;
}
while (y) {
t = y;
y = x % y;
x = t;
}
return x;
}
function compute(a, b, op) {
if (typeof a == 'number' && typeof b == 'number') {
switch (op) {
case exports.EnumToken.Add:
return a + b;
case exports.EnumToken.Sub:
return a - b;
case exports.EnumToken.Mul:
return a * b;
case exports.EnumToken.Div:
const r = simplify(a, b);
if (r[1] == 1) {
return r[0];
}
const result = a / b;
const r2 = reduceNumber(r[0]) + '/' + reduceNumber(r[1]);
return reduceNumber(result).length <= r2.length ? result : {
typ: exports.EnumToken.FractionTokenType,
l: { typ: exports.EnumToken.NumberTokenType, val: reduceNumber(r[0]) },
r: { typ: exports.EnumToken.NumberTokenType, val: reduceNumber(r[1]) }
};
}
}
let l1 = typeof a == 'number' ? {
typ: exports.EnumToken.FractionTokenType,
l: { typ: exports.EnumToken.NumberTokenType, val: reduceNumber(a) },
r: { typ: exports.EnumToken.NumberTokenType, val: '1' }
} : a;
let r1 = typeof b == 'number' ? {
typ: exports.EnumToken.FractionTokenType,
l: { typ: exports.EnumToken.NumberTokenType, val: reduceNumber(b) },
r: { typ: exports.EnumToken.NumberTokenType, val: '1' }
} : b;
let l2;
let r2;
switch (op) {
case exports.EnumToken.Add:
// @ts-ignore
l2 = l1.l.val * r1.r.val + l1.r.val * r1.l.val;
// @ts-ignore
r2 = l1.r.val * r1.r.val;
break;
case exports.EnumToken.Sub:
// @ts-ignore
l2 = l1.l.val * r1.r.val - l1.r.val * r1.l.val;
// @ts-ignore
r2 = l1.r.val * r1.r.val;
break;
case exports.EnumToken.Mul:
// @ts-ignore
l2 = l1.l.val * r1.l.val;
// @ts-ignore
r2 = l1.r.val * r1.r.val;
break;
case exports.EnumToken.Div:
// @ts-ignore
l2 = l1.l.val * r1.r.val;
// @ts-ignore
r2 = l1.r.val * r1.l.val;
break;
}
const a2 = simplify(l2, r2);
if (a2[1] == 1) {
return a2[0];
}
const result = a2[0] / a2[1];
return reduceNumber(result).length <= reduceNumber(a2[0]).length + 1 + reduceNumber(a2[1]).length ? result : {
typ: exports.EnumToken.FractionTokenType,
l: { typ: exports.EnumToken.NumberTokenType, val: reduceNumber(a2[0]) },
r: { typ: exports.EnumToken.NumberTokenType, val: reduceNumber(a2[1]) }
};
}
function rem(...a) {
if (a.some((i) => !Number.isInteger(i))) {
return a.reduce((a, b) => Math.max(a, String(b).split('.')[1]?.length ?? 0), 0);
}
return 0;
}
function simplify(a, b) {
const g = gcd(a, b);
return g > 1 ? [a / g, b / g] : [a, b];
}
/**
* evaluate an array of tokens
* @param tokens
*/
function evaluate(tokens) {
let nodes;
if (tokens.length == 1 && tokens[0].typ == exports.EnumToken.FunctionTokenType && tokens[0].val != 'calc' && mathFuncs.includes(tokens[0].val)) {
const chi = tokens[0].chi.reduce((acc, t) => {
if (acc.length == 0 || t.typ == exports.EnumToken.CommaTokenType) {
acc.push([]);
}
if ([exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommaTokenType, exports.EnumToken.CommaTokenType].includes(t.typ)) {
return acc;
}
acc.at(-1).push(t);
return acc;
}, []);
for (let i = 0; i < chi.length; i++) {
chi[i] = evaluate(chi[i]);
}
tokens[0].chi = chi.reduce((acc, t) => {
if (acc.length > 0) {
acc.push({ typ: exports.EnumToken.CommaTokenType });
}
acc.push(...t);
return acc;
});
return evaluateFunc(tokens[0]);
}
try {
nodes = inlineExpression(evaluateExpression(buildExpression(tokens)));
}
catch (e) {
return tokens;
}
if (nodes.length <= 1) {
// @ts-ignore
if (nodes.length == 1 && nodes[0].typ == exports.EnumToken.IdenTokenType && typeof Math[nodes[0].val.toUpperCase()] == 'number') {
return [{
...nodes[0],
// @ts-ignore
val: '' + Math[nodes[0].val.toUpperCase()],
typ: exports.EnumToken.NumberTokenType
}];
}
return nodes;
}
const map = new Map;
let token;
let i;
for (i = 0; i < nodes.length; i++) {
token = nodes[i];
if (token.typ == exports.EnumToken.Add) {
continue;
}
if (token.typ == exports.EnumToken.Sub) {
if (!isScalarToken(nodes[i + 1])) {
token = { typ: exports.EnumToken.ListToken, chi: [nodes[i], nodes[i + 1]] };
}
else {
token = doEvaluate(nodes[i + 1], { typ: exports.EnumToken.NumberTokenType, val: '-1' }, exports.EnumToken.Mul);
}
i++;
}
if (!map.has(token.typ)) {
map.set(token.typ, [token]);
}
else {
map.get(token.typ).push(token);
}
}
return [...map].reduce((acc, curr) => {
const token = curr[1].reduce((acc, curr) => doEvaluate(acc, curr, exports.EnumToken.Add));
if (token.typ != exports.EnumToken.BinaryExpressionTokenType) {
if ('val' in token && +token.val < 0) {
acc.push({ typ: exports.EnumToken.Sub }, { ...token, val: String(-token.val) });
return acc;
}
}
if (acc.length > 0 && curr[0] != exports.EnumToken.ListToken) {
acc.push({ typ: exports.EnumToken.Add });
}
acc.push(token);
return acc;
}, []);
}
/**
* evaluate arithmetic operation
* @param l
* @param r
* @param op
*/
function doEvaluate(l, r, op) {
const defaultReturn = {
typ: exports.EnumToken.BinaryExpressionTokenType,
op,
l,
r
};
if (!isScalarToken(l) || !isScalarToken(r) || (l.typ == r.typ && 'unit' in l && 'unit' in r && l.unit != r.unit)) {
return defaultReturn;
}
if (l.typ == exports.EnumToken.FunctionTokenType) {
const val = evaluateFunc(l);
if (val.length == 1) {
l = val[0];
}
else {
return defaultReturn;
}
}
if (r.typ == exports.EnumToken.FunctionTokenType) {
const val = evaluateFunc(r);
if (val.length == 1) {
r = val[0];
}
else {
return defaultReturn;
}
}
if (l.typ == exports.EnumToken.FunctionTokenType) {
const val = evaluateFunc(l);
if (val.length == 1) {
l = val[0];
}
}
if ((op == exports.EnumToken.Add || op == exports.EnumToken.Sub)) {
// @ts-ignore
if (l.typ != r.typ) {
return defaultReturn;
}
}
else if (op == exports.EnumToken.Mul &&
![exports.EnumToken.NumberTokenType, exports.EnumToken.PercentageTokenType].includes(l.typ) &&
![exports.EnumToken.NumberTokenType, exports.EnumToken.PercentageTokenType].includes(r.typ)) {
return defaultReturn;
}
let typ = l.typ == exports.EnumToken.NumberTokenType ? r.typ : (r.typ == exports.EnumToken.NumberTokenType ? l.typ : (l.typ == exports.EnumToken.PercentageTokenType ? r.typ : l.typ));
// @ts-ignore
let v1 = getValue$1(l);
let v2 = getValue$1(r);
if (v1 == null || v2 == null) {
return defaultReturn;
}
if (op == exports.EnumToken.Mul) {
if (l.typ != exports.EnumToken.NumberTokenType && r.typ != exports.EnumToken.NumberTokenType) {
if (typeof v1 == 'number' && l.typ == exports.EnumToken.PercentageTokenType) {
v1 = {
typ: exports.EnumToken.FractionTokenType,
l: { typ: exports.EnumToken.NumberTokenType, val: String(v1) },
r: { typ: exports.EnumToken.NumberTokenType, val: '100' }
};
}
else if (typeof v2 == 'number' && r.typ == exports.EnumToken.PercentageTokenType) {
v2 = {
typ: exports.EnumToken.FractionTokenType,
l: { typ: exports.EnumToken.NumberTokenType, val: String(v2) },
r: { typ: exports.EnumToken.NumberTokenType, val: '100' }
};
}
}
}
// @ts-ignore
const val = compute(v1, v2, op);
// typ = typeof val == 'number' ? EnumToken.NumberTokenType : EnumToken.FractionTokenType;
const token = {
...(l.typ == exports.EnumToken.NumberTokenType ? r : l),
typ,
val: typeof val == 'number' ? reduceNumber(val) : val
};
if (token.typ == exports.EnumToken.IdenTokenType) {
// @ts-ignore
token.typ = exports.EnumToken.NumberTokenType;
}
return token;
}
function getValue$1(t) {
let v1;
if (t.typ == exports.EnumToken.FunctionTokenType) {
v1 = evaluateFunc(t);
if (v1.length != 1 || v1[0].typ == exports.EnumToken.BinaryExpressionTokenType) {
return null;
}
t = v1[0];
}
if (t.typ == exports.EnumToken.IdenTokenType) {
// @ts-ignore
return Math[t.val.toUpperCase()];
}
if (t.val.typ == exports.EnumToken.FractionTokenType) {
// @ts-ignore
return t.val.l.val / t.val.r.val;
}
// @ts-ignore
return t.typ == exports.EnumToken.FractionTokenType ? t.l.val / t.r.val : +t.val;
}
function evaluateFunc(token) {
const values = token.chi.slice();
switch (token.val) {
case 'abs':
case 'sin':
case 'cos':
case 'tan':
case 'asin':
case 'acos':
case 'atan':
case 'sign':
case 'sqrt':
case 'exp': {
const value = evaluate(values);
if (value.length != 1 || (value[0].typ != exports.EnumToken.NumberTokenType && value[0].typ != exports.EnumToken.FractionTokenType) || (value[0].typ == exports.EnumToken.FractionTokenType && (+value[0].r.val == 0 || !Number.isFinite(+value[0].l.val) || !Number.isFinite(+value[0].r.val)))) {
return value;
}
// @ts-ignore
let val = value[0].typ == exports.EnumToken.NumberTokenType ? +value[0].val : value[0].l.val / value[0].r.val;
return [{
typ: exports.EnumToken.NumberTokenType,
val: '' + Math[token.val](val)
}];
}
case 'hypot': {
const chi = values.filter(t => ![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType, exports.EnumToken.CommaTokenType].includes(t.typ));
let all = [];
let ref = chi[0];
let value = 0;
if (![exports.EnumToken.NumberTokenType, exports.EnumToken.PercentageTokenType].includes(ref.typ) && !('unit' in ref)) {
return [token];
}
for (let i = 0; i < chi.length; i++) {
// @ts-ignore
if (chi[i].typ != ref.typ || ('unit' in chi[i] && 'unit' in ref && chi[i].unit != ref.unit)) {
return [token];
}
// @ts-ignore
const val = getValue$1(chi[i]);
if (val == null) {
return [token];
}
all.push(val);
value += val * val;
}
return [
{
...ref,
val: Math.sqrt(value).toFixed(rem(...all))
}
];
}
case 'atan2':
case 'pow':
case 'rem':
case 'mod': {
const chi = values.filter(t => ![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType].includes(t.typ));
if (chi.length != 3 || chi[1].typ != exports.EnumToken.CommaTokenType) {
return [token];
}
if (token.val == 'pow' && (chi[0].typ != exports.EnumToken.NumberTokenType || chi[2].typ != exports.EnumToken.NumberTokenType)) {
return [token];
}
if (['rem', 'mod'].includes(token.val) &&
(chi[0].typ != chi[2].typ) || ('unit' in chi[0] && 'unit' in chi[2] &&
chi[0].unit != chi[2].unit)) {
return [token];
}
// https://developer.mozilla.org/en-US/docs/Web/CSS/mod
const v1 = evaluate([chi[0]]);
const v2 = evaluate([chi[2]]);
const types = [exports.EnumToken.PercentageTokenType, exports.EnumToken.DimensionTokenType, exports.EnumToken.AngleTokenType, exports.EnumToken.NumberTokenType, exports.EnumToken.LengthTokenType, exports.EnumToken.TimeTokenType, exports.EnumToken.FrequencyTokenType, exports.EnumToken.ResolutionTokenType];
if (v1.length != 1 || v2.length != 1 || !types.includes(v1[0].typ) || !types.includes(v2[0].typ) || v1[0].unit != v2[0].unit) {
return [token];
}
// @ts-ignore
const val1 = getValue$1(v1[0]);
// @ts-ignore
const val2 = getValue$1(v2[0]);
if (val1 == null || val2 == null || (v1[0].typ != v2[0].typ && val1 != 0 && val2 != 0)) {
return [token];
}
if (token.val == 'rem') {
if (val2 == 0) {
return [token];
}
return [
{
...v1[0],
val: (val1 % val2).toFixed(rem(val1, val2))
}
];
}
if (token.val == 'pow') {
return [
{
...v1[0],
val: String(Math.pow(val1, val2))
}
];
}
if (token.val == 'atan2') {
return [
{
...{}, ...v1[0],
val: String(Math.atan2(val1, val2))
}
];
}
return [
{
...v1[0],
val: String(val2 == 0 ? val1 : val1 - (Math.floor(val1 / val2) * val2))
}
];
}
case 'clamp':
token.chi = values;
return [token];
case 'log':
case 'round':
case 'min':
case 'max':
{
const strategy = token.val == 'round' && values[0]?.typ == exports.EnumToken.IdenTokenType ? values.shift().val : null;
const valuesMap = new Map;
for (const curr of values) {
if (curr.typ == exports.EnumToken.CommaTokenType || curr.typ == exports.EnumToken.WhitespaceTokenType || curr.typ == exports.EnumToken.CommentTokenType) {
continue;
}
const result = evaluate([curr]);
if (result.length != 1 || result[0].typ == exports.EnumToken.FunctionTokenType) {
return [token];
}
const key = result[0].typ + ('unit' in result[0] ? result[0].unit : '');
if (!valuesMap.has(key)) {
valuesMap.set(key, []);
}
valuesMap.get(key).push(result[0]);
}
if (valuesMap.size == 1) {
const values = valuesMap.values().next().value;
if (token.val == 'log') {
if (values[0].typ != exports.EnumToken.NumberTokenType || values.length > 2) {
return [token];
}
const val1 = getValue$1(values[0]);
const val2 = values.length == 2 ? getValue$1(values[1]) : null;
if (values.length == 1) {
return [
{
...values[0],
val: String(Math.log(val1))
}
];
}
return [
{
...values[0],
val: String(Math.log(val1) / Math.log(val2))
}
];
}
if (token.val == 'min' || token.val == 'max') {
let val = getValue$1(values[0]);
let val2 = val;
let ret = values[0];
for (const curr of values.slice(1)) {
val2 = getValue$1(curr);
if (val2 < val && token.val == 'min') {
val = val2;
ret = curr;
}
else if (val2 > val && token.val == 'max') {
val = val2;
ret = curr;
}
}
return [ret];
}
if (token.val == 'round') {
let val = getValue$1(values[0]);
let val2 = getValue$1(values[1]);
if (Number.isNaN(val) || Number.isNaN(val2)) {
return [token];
}
if (strategy == null || strategy == 'down') {
val = val - (val % val2);
}
else {
val = strategy == 'to-zero' ? Math.trunc(val / val2) * val2 : (strategy == 'nearest' ? Math.round(val / val2) * val2 : Math.ceil(val / val2) * val2);
}
// @ts-ignore
return [{ ...values[0], val: String(val) }];
}
}
}
return [token];
}
return [token];
}
/**
* convert BinaryExpression into an array
* @param token
*/
function inlineExpression(token) {
const result = [];
if (token.typ == exports.EnumToken.ParensTokenType && token.chi.length == 1) {
result.push(token.chi[0]);
}
else if (token.typ == exports.EnumToken.BinaryExpressionTokenType) {
if ([exports.EnumToken.Mul, exports.EnumToken.Div].includes(token.op)) {
result.push(token);
}
else {
result.push(...inlineExpression(token.l), { typ: token.op }, ...inlineExpression(token.r));
}
}
else {
result.push(token);
}
return result;
}
/**
* evaluate expression
* @param token
*/
function evaluateExpression(token) {
if (token.typ != exports.EnumToken.BinaryExpressionTokenType) {
return token;
}
if (token.r.typ == exports.EnumToken.BinaryExpressionTokenType) {
token.r = evaluateExpression(token.r);
}
if (token.l.typ == exports.EnumToken.BinaryExpressionTokenType) {
token.l = evaluateExpression(token.l);
}
return doEvaluate(token.l, token.r, token.op);
}
function isScalarToken(token) {
return 'unit' in token ||
(token.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(token.val)) ||
// @ts-ignore
(token.typ == exports.EnumToken.IdenTokenType && typeof Math[token.val.toUpperCase()] == 'number') ||
[exports.EnumToken.NumberTokenType, exports.EnumToken.FractionTokenType, exports.EnumToken.PercentageTokenType].includes(token.typ);
}
/**
*
* generate binary expression tree
* @param tokens
*/
function buildExpression(tokens) {
return factor(factor(tokens.filter(t => t.typ != exports.EnumToken.WhitespaceTokenType), ['/', '*']), ['+', '-'])[0];
}
function getArithmeticOperation(op) {
if (op == '+') {
return exports.EnumToken.Add;
}
if (op == '-') {
return exports.EnumToken.Sub;
}
if (op == '/') {
return exports.EnumToken.Div;
}
return exports.EnumToken.Mul;
}
/**
*
* generate binary expression tree
* @param token
*/
function factorToken(token) {
if (token.typ == exports.EnumToken.ParensTokenType || (token.typ == exports.EnumToken.FunctionTokenType && token.val == 'calc')) {
if (token.typ == exports.EnumToken.FunctionTokenType && token.val == 'calc') {
token = { ...token, typ: exports.EnumToken.ParensTokenType };
// @ts-ignore
delete token.val;
}
return buildExpression(token.chi);
}
return token;
}
/**
* generate binary expression tree
* @param tokens
* @param ops
*/
function factor(tokens, ops) {
let isOp;
const opList = ops.map(x => getArithmeticOperation(x));
if (tokens.length == 1) {
return [factorToken(tokens[0])];
}
for (let i = 0; i < tokens.length; i++) {
if (tokens[i].typ == exports.EnumToken.ListToken) {
// @ts-ignore
tokens.splice(i, 1, ...tokens[i].chi);
}
isOp = opList.includes(tokens[i].typ);
if (isOp ||
// @ts-ignore
(tokens[i].typ == exports.EnumToken.LiteralTokenType && ops.includes(tokens[i].val))) {
tokens.splice(i - 1, 3, {
typ: exports.EnumToken.BinaryExpressionTokenType,
op: isOp ? tokens[i].typ : getArithmeticOperation(tokens[i].val),
l: factorToken(tokens[i - 1]),
r: factorToken(tokens[i + 1])
});
i--;
}
}
return tokens;
}
function parseRelativeColor(relativeKeys, original, rExp, gExp, bExp, aExp) {
let r;
let g;
let b;
let alpha = null;
let keys = {};
let values = {};
// colorFuncColorSpace x,y,z or r,g,b
const names = relativeKeys.startsWith('xyz') ? 'xyz' : relativeKeys.slice(-3);
// @ts-ignore
const converted = convert(original, relativeKeys);
if (converted == null) {
return null;
}
const children = converted.chi.filter(t => ![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.LiteralTokenType, exports.EnumToken.CommentTokenType].includes(t.typ));
[r, g, b, alpha] = converted.kin == 'color' ? children.slice(1) : children;
values = {
[names[0]]: getValue(r, converted, names[0]),
[names[1]]: getValue(g, converted, names[1]), // string,
[names[2]]: getValue(b, converted, names[2]),
// @ts-ignore
alpha: alpha == null || (alpha.typ == exports.EnumToken.IdenTokenType && alpha.val == 'none') ? {
typ: exports.EnumToken.NumberTokenType,
val: '1'
} : (alpha.typ == exports.EnumToken.PercentageTokenType ? {
typ: exports.EnumToken.NumberTokenType,
val: String(getNumber(alpha))
} : alpha)
};
keys = {
[names[0]]: getValue(rExp, converted, names[0]),
[names[1]]: getValue(gExp, converted, names[1]),
[names[2]]: getValue(bExp, converted, names[2]),
// @ts-ignore
alpha: getValue(aExp == null || (aExp.typ == exports.EnumToken.IdenTokenType && aExp.val == 'none') ? {
typ: exports.EnumToken.NumberTokenType,
val: '1'
} : aExp)
};
return computeComponentValue(keys, converted, values);
}
function getValue(t, converted, component) {
if (t == null) {
return t;
}
if (t.typ == exports.EnumToken.PercentageTokenType) {
let value = getNumber(t);
if (converted.kin in colorRange) {
// @ts-ignore
value *= colorRange[converted.kin][component].at(-1);
}
return {
typ: exports.EnumToken.NumberTokenType,
val: String(value)
};
}
return t;
}
function computeComponentValue(expr, converted, values) {
for (const object of [values, expr]) {
if ('h' in object) {
// normalize hue
// @ts-ignore
for (const k of walkValues([object.h])) {
if (k.value.typ == exports.EnumToken.AngleTokenType && k.value.unit == 'deg') {
// @ts-ignore
k.value.typ = exports.EnumToken.NumberTokenType;
// @ts-ignore
delete k.value.unit;
}
}
}
}
for (const [key, exp] of Object.entries(expr)) {
if (exp == null) {
if (key in values) {
if (typeof values[key] == 'number') {
expr[key] = {
typ: exports.EnumToken.NumberTokenType,
val: reduceNumber(values[key])
};
}
else {
expr[key] = values[key];
}
}
}
else if ([exports.EnumToken.NumberTokenType, exports.EnumToken.PercentageTokenType, exports.EnumToken.AngleTokenType, exports.EnumToken.LengthTokenType].includes(exp.typ)) ;
else if (exp.typ == exports.EnumToken.IdenTokenType && exp.val in values) {
if (typeof values[exp.val] == 'number') {
expr[key] = {
typ: exports.EnumToken.NumberTokenType,
val: reduceNumber(values[exp.val])
};
}
else {
expr[key] = values[exp.val];
}
}
else if (exp.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(exp.val)) {
for (let { value, parent } of walkValues(exp.chi, exp)) {
if (parent == null) {
parent = exp;
}
if (value.typ == exports.EnumToken.PercentageTokenType) {
replaceValue(parent, value, getValue(value, converted, key));
}
else if (value.typ == exports.EnumToken.IdenTokenType) {
// @ts-ignore
if (!(value.val in values || typeof Math[value.val.toUpperCase()] == 'number')) {
return null;
}
// @ts-ignore
replaceValue(parent, value, values[value.val] ?? {
typ: exports.EnumToken.NumberTokenType,
// @ts-ignore
val: '' + Math[value.val.toUpperCase()]
// @ts-ignore
});
}
}
const result = exp.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(exp.val) && exp.val != 'calc' ? evaluateFunc(exp) : evaluate(exp.chi);
if (result.length == 1 && result[0].typ != exports.EnumToken.BinaryExpressionTokenType) {
expr[key] = result[0];
}
else {
return null;
}
}
}
return expr;
}
function replaceValue(parent, value, newValue) {
if (parent.typ == exports.EnumToken.BinaryExpressionTokenType) {
if (parent.l == value) {
parent.l = newValue;
}
else {
parent.r = newValue;
}
}
else {
for (let i = 0; i < parent.chi.length; i++) {
if (parent.chi[i] == value) {
parent.chi.splice(i, 1, newValue);
break;
}
if (parent.chi[i].typ == exports.EnumToken.BinaryExpressionTokenType) {
if (parent.chi[i].l == value) {
parent.chi[i].l = newValue;
break;
}
else if (parent.chi[i].r == value) {
parent.chi[i].r = newValue;
break;
}
}
}
}
}
// from https://github.com/Rich-Harris/vlq/tree/master
// credit: Rich Harris
const integer_to_char = {};
let i = 0;
for (const char of 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=') {
integer_to_char[i++] = char;
}
function encode(value) {
if (typeof value === 'number') {
return encode_integer(value);
}
let result = '';
for (let i = 0; i < value.length; i += 1) {
result += encode_integer(value[i]);
}
return result;
}
function encode_integer(num) {
let result = '';
if (num < 0) {
num = (-num << 1) | 1;
}
else {
num <<= 1;
}
do {
let clamped = num & 31;
num >>>= 5;
if (num > 0) {
clamped |= 32;
}
result += integer_to_char[clamped];
} while (num > 0);
return result;
}
class SourceMap {
lastLocation = null;
#version = 3;
#sources = [];
#map = new Map;
#line = -1;
add(source, original) {
if (original.src !== '') {
if (!this.#sources.includes(original.src)) {
this.#sources.push(original.src);
}
const line = source.sta.lin - 1;
let record;
if (line > this.#line) {
this.#line = line;
}
if (!this.#map.has(line)) {
record = [Math.max(0, source.sta.col - 1), this.#sources.indexOf(original.src), original.sta.lin - 1, original.sta.col - 1];
this.#map.set(line, [record]);
}
else {
const arr = this.#map.get(line);
record = [Math.max(0, source.sta.col - 1 - arr[0][0]), this.#sources.indexOf(original.src) - arr[0][1], original.sta.lin - 1, original.sta.col - 1];
arr.push(record);
}
if (this.lastLocation != null) {
record[2] -= this.lastLocation.sta.lin - 1;
record[3] -= this.lastLocation.sta.col - 1;
}
this.lastLocation = original;
}
}
toUrl() {
// /*# sourceMappingURL = ${url} */
return `data:application/json,${encodeURIComponent(JSON.stringify(this.toJSON()))}`;
}
toJSON() {
const mappings = [];
let i = 0;
for (; i <= this.#line; i++) {
if (!this.#map.has(i)) {
mappings.push('');
}
else {
mappings.push(this.#map.get(i).reduce((acc, curr) => acc + (acc === '' ? '' : ',') + encode(curr), ''));
}
}
return {
version: this.#version,
sources: this.#sources.slice(),
mappings: mappings.join(';')
};
}
}
const colorsFunc = ['rgb', 'rgba', 'hsl', 'hsla', 'hwb', 'device-cmyk', 'color-mix', 'color', 'oklab', 'lab', 'oklch', 'lch', 'light-dark'];
function reduceNumber(val) {
val = String(+val);
if (val === '0') {
return '0';
}
const chr = val.charAt(0);
if (chr == '-') {
const slice = val.slice(0, 2);
if (slice == '-0') {
return val.length == 2 ? '0' : '-' + val.slice(2);
}
}
if (chr == '0') {
return val.slice(1);
}
return val;
}
function update(position, str) {
let i = 0;
for (; i < str.length; i++) {
if (isNewLine(str[i].charCodeAt(0))) {
position.lin++;
position.col = 0;
}
else {
position.col++;
}
}
}
/**
* render ast
* @param data
* @param options
*/
function doRender(data, options = {}) {
const minify = options.minify ?? true;
const beautify = options.beautify ?? !minify;
options = {
...(beautify ? {
indent: ' ',
newLine: '\n',
} : {
indent: '',
newLine: '',
}),
...(minify ? {
removeEmpty: true,
removeComments: true
} : {
removeEmpty: false,
removeComments: false,
}), sourcemap: false, convertColor: true, expandNestingRules: false, preserveLicense: false, ...options
};
if (options.withParents) {
// @ts-ignore
let parent = data.parent;
// @ts-ignore
while (data.parent != null) {
// @ts-ignore
parent = { ...data.parent, chi: [{ ...data }] };
// @ts-ignore
parent.parent = data.parent.parent;
// @ts-ignore
data = parent;
}
}
const startTime = performance.now();
const errors = [];
const sourcemap = options.sourcemap ? new SourceMap : null;
const cache = Object.create(null);
const result = {
code: renderAstNode(options.expandNestingRules ? expand(data) : data, options, sourcemap, {
ind: 0,
lin: 1,
col: 1
}, errors, function reducer(acc, curr) {
if (curr.typ == exports.EnumToken.CommentTokenType && options.removeComments) {
if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
return acc;
}
return acc + curr.val;
}
return acc + renderToken(curr, options, cache, reducer, errors);
}, cache), errors, stats: {
total: `${(performance.now() - startTime).toFixed(2)}ms`
}
};
if (options.output != null) {
// @ts-ignore
options.output = options.resolve(options.output, options.cwd).absolute;
}
if (sourcemap != null) {
result.map = sourcemap;
}
return result;
}
function updateSourceMap(node, options, cache, sourcemap, position, str) {
if ([exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType, exports.EnumToken.KeyFrameRuleNodeType].includes(node.typ)) {
let src = node.loc?.src ?? '';
let output = options.output ?? '';
if (!(src in cache)) {
// @ts-ignore
cache[src] = options.resolve(src, options.cwd ?? '').relative;
}
if (!(output in cache)) {
// @ts-ignore
cache[output] = options.resolve(output, options.cwd).relative;
}
// @ts-ignore
sourcemap.add({ src: cache[output], sta: { ...position } }, {
...node.loc,
// @ts-ignore
src: options.resolve(cache[src], options.cwd).relative
});
}
update(position, str);
}
/**
* render ast node
* @param data
* @param options
* @param sourcemap
* @param position
* @param errors
* @param reducer
* @param cache
* @param level
* @param indents
*/
function renderAstNode(data, options, sourcemap, position, errors, reducer, cache, level = 0, indents = []) {
if (indents.length < level + 1) {
indents.push(options.indent.repeat(level));
}
if (indents.length < level + 2) {
indents.push(options.indent.repeat(level + 1));
}
const indent = indents[level];
const indentSub = indents[level + 1];
switch (data.typ) {
case exports.EnumToken.DeclarationNodeType:
return `${data.nam}:${options.indent}${data.val.reduce(reducer, '')}`;
case exports.EnumToken.CommentNodeType:
case exports.EnumToken.CDOCOMMNodeType:
if (data.val.startsWith('/*# sourceMappingURL=')) {
// ignore sourcemap
return '';
}
return !options.removeComments || (options.preserveLicense && data.val.startsWith('/*!')) ? data.val : '';
case exports.EnumToken.StyleSheetNodeType:
return data.chi.reduce((css, node) => {
const str = renderAstNode(node, options, sourcemap, { ...position }, errors, reducer, cache, level, indents);
if (str === '') {
return css;
}
if (css === '') {
if (sourcemap != null && node.loc != null) {
updateSourceMap(node, options, cache, sourcemap, position, str);
}
return str;
}
if (sourcemap != null && node.loc != null) {
update(position, options.newLine);
updateSourceMap(node, options, cache, sourcemap, position, str);
}
return `${css}${options.newLine}${str}`;
}, '');
case exports.EnumToken.AtRuleNodeType:
case exports.EnumToken.RuleNodeType:
case exports.EnumToken.KeyFrameRuleNodeType:
if (data.typ == exports.EnumToken.AtRuleNodeType && !('chi' in data)) {
return `${indent}@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val};`;
}
// @ts-ignore
let children = data.chi.reduce((css, node) => {
let str;
if (node.typ == exports.EnumToken.CommentNodeType) {
str = options.removeComments && (!options.preserveLicense || !node.val.startsWith('/*!')) ? '' : node.val;
}
else if (node.typ == exports.EnumToken.DeclarationNodeType) {
if (node.val.length == 0) {
// @ts-ignore
errors.push({
action: 'ignore',
message: `render: invalid declaration ${JSON.stringify(node)}`,
location: node.loc
});
return '';
}
str = `${node.nam}:${options.indent}${node.val.reduce(reducer, '').trimEnd()};`;
}
else if (node.typ == exports.EnumToken.AtRuleNodeType && !('chi' in node)) {
str = `${data.val === '' ? '' : options.indent || ' '}${data.val};`;
}
else {
str = renderAstNode(node, options, sourcemap, { ...position }, errors, reducer, cache, level + 1, indents);
}
if (css === '') {
return str;
}
if (str === '') {
return css;
}
return `${css}${options.newLine}${indentSub}${str}`;
}, '');
if (options.removeEmpty && children === '') {
return '';
}
if (children.endsWith(';')) {
children = children.slice(0, -1);
}
if (data.typ == exports.EnumToken.AtRuleNodeType) {
return `@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val}${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
}
return data.sel + `${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
case exports.EnumToken.InvalidRuleTokenType:
case exports.EnumToken.InvalidAtRuleTokenType:
return '';
default:
// return renderToken(data as Token, options, cache, reducer, errors);
throw new Error(`render: unexpected token ${JSON.stringify(data, null, 1)}`);
}
}
/**
* render ast token
* @param token
* @param options
* @param cache
* @param reducer
* @param errors
*/
function renderToken(token, options = {}, cache = Object.create(null), reducer, errors) {
if (reducer == null) {
reducer = function (acc, curr) {
if (curr.typ == exports.EnumToken.CommentTokenType && options.removeComments) {
if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
return acc;
}
return acc + curr.val;
}
return acc + renderToken(curr, options, cache, reducer, errors);
};
}
if (token.typ == exports.EnumToken.FunctionTokenType && colorsFunc.includes(token.val)) {
if (isColor(token)) {
// @ts-ignore
token.typ = exports.EnumToken.ColorTokenType;
if (token.chi[0].typ == exports.EnumToken.IdenTokenType && token.chi[0].val == 'from') {
// @ts-ignore
token.cal = 'rel';
}
else if (token.val == 'color-mix' && token.chi[0].typ == exports.EnumToken.IdenTokenType && token.chi[0].val == 'in') {
// @ts-ignore
token.cal = 'mix';
}
else {
if (token.val == 'color') {
// @ts-ignore
token.cal = 'col';
}
token.chi = token.chi.filter((t) => ![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommaTokenType, exports.EnumToken.CommentTokenType].includes(t.typ));
}
}
}
switch (token.typ) {
case exports.EnumToken.ListToken:
return token.chi.reduce((acc, curr) => acc + renderToken(curr, options, cache), '');
case exports.EnumToken.BinaryExpressionTokenType:
if ([exports.EnumToken.Mul, exports.EnumToken.Div].includes(token.op)) {
let result = '';
if (token.l.typ == exports.EnumToken.BinaryExpressionTokenType &&
[exports.EnumToken.Add, exports.EnumToken.Sub].includes(token.l.op)) {
result = '(' + renderToken(token.l, options, cache) + ')';
}
else {
result = renderToken(token.l, options, cache);
}
result += token.op == exports.EnumToken.Mul ? '*' : '/';
if (token.r.typ == exports.EnumToken.BinaryExpressionTokenType &&
[exports.EnumToken.Add, exports.EnumToken.Sub].includes(token.r.op)) {
result += '(' + renderToken(token.r, options, cache) + ')';
}
else {
result += renderToken(token.r, options, cache);
}
return result;
}
return renderToken(token.l, options, cache) + (token.op == exports.EnumToken.Add ? ' + ' : (token.op == exports.EnumToken.Sub ? ' - ' : (token.op == exports.EnumToken.Mul ? '*' : '/'))) + renderToken(token.r, options, cache);
case exports.EnumToken.FractionTokenType:
const fraction = renderToken(token.l) + '/' + renderToken(token.r);
if (+token.r.val != 0) {
const value = reduceNumber(+token.l.val / +token.r.val);
if (value.length <= fraction.length) {
return value;
}
}
return fraction;
case exports.EnumToken.Add:
return ' + ';
case exports.EnumToken.Sub:
return ' - ';
case exports.EnumToken.UniversalSelectorTokenType:
case exports.EnumToken.Mul:
return '*';
case exports.EnumToken.Div:
return '/';
case exports.EnumToken.ColorTokenType:
if (token.kin == 'light-dark') {
return token.val + '(' + token.chi.reduce((acc, curr) => acc + renderToken(curr, options, cache), '') + ')';
}
if (options.convertColor) {
if (token.cal == 'mix' && token.val == 'color-mix') {
const children = token.chi.reduce((acc, t) => {
if (t.typ == exports.EnumToken.ColorTokenType) {
acc.push([t]);
}
else {
if (![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType].includes(t.typ)) {
acc[acc.length - 1].push(t);
}
}
return acc;
}, [[]]);
const value = colorMix(children[0][1], children[0][2], children[1][0], children[1][1], children[2][0], children[2][1]);
if (value != null) {
token = value;
}
}
if (token.cal == 'rel' && ['rgb', 'hsl', 'hwb', 'lab', 'lch', 'oklab', 'oklch', 'color'].includes(token.val)) {
const chi = getComponents(token);
const offset = token.val == 'color' ? 2 : 1;
// @ts-ignore
const color = chi[1];
const components = parseRelativeColor(token.val == 'color' ? chi[offset].val : token.val, color, chi[offset + 1], chi[offset + 2], chi[offset + 3], chi[offset + 4]);
if (components != null) {
token.chi = [...(token.val == 'color' ? [chi[offset]] : []), ...Object.values(components)];
delete token.cal;
}
}
if (token.val == 'color') {
if (token.chi[0].typ == exports.EnumToken.IdenTokenType && colorFuncColorSpace.includes(token.chi[0].val.toLowerCase())) {
// @ts-ignore
return reduceHexValue(srgb2hexvalues(...color2srgbvalues(token)));
}
}
if (token.cal != null) {
let slice = false;
if (token.cal == 'rel') {
const last = token.chi.at(-1);
if ((last.typ == exports.EnumToken.NumberTokenType && last.val == '1') || (last.typ == exports.EnumToken.IdenTokenType && last.val == 'none')) {
const prev = token.chi.at(-2);
if (prev.typ == exports.EnumToken.LiteralTokenType && prev.val == '/') {
slice = true;
}
}
}
return clamp(token).val + '(' + (slice ? token.chi.slice(0, -2) : token.chi).reduce((acc, curr) => {
const val = renderToken(curr, options, cache);
if ([exports.EnumToken.LiteralTokenType, exports.EnumToken.CommaTokenType].includes(curr.typ)) {
return acc + val;
}
if (acc.length > 0) {
return acc + (['/', ','].includes(acc.at(-1)) ? '' : ' ') + val;
}
return val;
}, '') + ')';
}
if (token.kin == 'lit' && token.val.localeCompare('currentcolor', undefined, { sensitivity: 'base' }) == 0) {
return 'currentcolor';
}
clamp(token);
if (Array.isArray(token.chi) && token.chi.some((t) => t.typ == exports.EnumToken.FunctionTokenType || (t.typ == exports.EnumToken.ColorTokenType && Array.isArray(t.chi)))) {
return (token.val.endsWith('a') ? token.val.slice(0, -1) : token.val) + '(' + token.chi.reduce((acc, curr) => acc + (acc.length > 0 && !(acc.endsWith('/') || curr.typ == exports.EnumToken.LiteralTokenType) ? ' ' : '') + renderToken(curr, options, cache), '') + ')';
}
let value = token.kin == 'hex' ? token.val.toLowerCase() : (token.kin == 'lit' ? COLORS_NAMES[token.val.toLowerCase()] : '');
if (token.val == 'rgb' || token.val == 'rgba') {
value = rgb2hex(token);
}
else if (token.val == 'hsl' || token.val == 'hsla') {
value = hsl2hex(token);
}
else if (token.val == 'hwb') {
value = hwb2hex(token);
}
else if (token.val == 'device-cmyk') {
value = cmyk2hex(token);
}
else if (token.val == 'oklab') {
value = oklab2hex(token);
}
else if (token.val == 'oklch') {
value = oklch2hex(token);
}
else if (token.val == 'lab') {
value = lab2hex(token);
}
else if (token.val == 'lch') {
value = lch2hex(token);
}
if (value !== '') {
return reduceHexValue(value);
}
}
if (['hex', 'lit', 'sys', 'dpsys'].includes(token.kin)) {
return token.val;
}
if (Array.isArray(token.chi)) {
return (token.val.endsWith('a') ? token.val.slice(0, -1) : token.val) + '(' + token.chi.reduce((acc, curr) => acc + (acc.length > 0 && !(acc.endsWith('/') || curr.typ == exports.EnumToken.LiteralTokenType) ? ' ' : '') + renderToken(curr, options, cache), '') + ')';
}
case exports.EnumToken.ParensTokenType:
case exports.EnumToken.FunctionTokenType:
case exports.EnumToken.UrlFunctionTokenType:
case exports.EnumToken.ImageFunctionTokenType:
case exports.EnumToken.TimingFunctionTokenType:
case exports.EnumToken.PseudoClassFuncTokenType:
case exports.EnumToken.TimelineFunctionTokenType:
case exports.EnumToken.GridTemplateFuncTokenType:
if (token.typ == exports.EnumToken.FunctionTokenType &&
mathFuncs.includes(token.val) &&
token.chi.length == 1 &&
![exports.EnumToken.BinaryExpressionTokenType, exports.EnumToken.FractionTokenType, exports.EnumToken.IdenTokenType].includes(token.chi[0].typ) &&
// @ts-ignore
token.chi[0].val?.typ != exports.EnumToken.FractionTokenType) {
return token.chi.reduce((acc, curr) => acc + renderToken(curr, options, cache, reducer), '');
}
// @ts-ignore
return ( /* options.minify && 'Pseudo-class-func' == token.typ && token.val.slice(0, 2) == '::' ? token.val.slice(1) :*/token.val ?? '') + '(' + token.chi.reduce(reducer, '') + ')';
case exports.EnumToken.MatchExpressionTokenType:
return renderToken(token.l, options, cache, reducer, errors) +
renderToken(token.op, options, cache, reducer, errors) +
renderToken(token.r, options, cache, reducer, errors) +
(token.attr ? ' ' + token.attr : '');
case exports.EnumToken.NameSpaceAttributeTokenType:
return (token.l == null ? '' : renderToken(token.l, options, cache, reducer, errors)) + '|' +
renderToken(token.r, options, cache, reducer, errors);
case exports.EnumToken.BlockStartTokenType:
return '{';
case exports.EnumToken.BlockEndTokenType:
return '}';
case exports.EnumToken.StartParensTokenType:
return '(';
case exports.EnumToken.DelimTokenType:
case exports.EnumToken.EqualMatchTokenType:
return '=';
case exports.EnumToken.IncludeMatchTokenType:
return '~=';
case exports.EnumToken.DashMatchTokenType:
return '|=';
case exports.EnumToken.StartMatchTokenType:
return '^=';
case exports.EnumToken.EndMatchTokenType:
return '$=';
case exports.EnumToken.ContainMatchTokenType:
return '*=';
case exports.EnumToken.LtTokenType:
return '<';
case exports.EnumToken.LteTokenType:
return '<=';
case exports.EnumToken.SubsequentSiblingCombinatorTokenType:
return '~';
case exports.EnumToken.NextSiblingCombinatorTokenType:
return '+';
case exports.EnumToken.GtTokenType:
case exports.EnumToken.ChildCombinatorTokenType:
return '>';
case exports.EnumToken.GteTokenType:
return '>=';
case exports.EnumToken.ColumnCombinatorTokenType:
return '||';
case exports.EnumToken.EndParensTokenType:
return ')';
case exports.EnumToken.AttrStartTokenType:
return '[';
case exports.EnumToken.AttrEndTokenType:
return ']';
case exports.EnumToken.DescendantCombinatorTokenType:
case exports.EnumToken.WhitespaceTokenType:
return ' ';
case exports.EnumToken.ColonTokenType:
return ':';
case exports.EnumToken.SemiColonTokenType:
return ';';
case exports.EnumToken.CommaTokenType:
return ',';
case exports.EnumToken.ImportantTokenType:
return '!important';
case exports.EnumToken.AttrTokenType:
case exports.EnumToken.IdenListTokenType:
return '[' + token.chi.reduce(reducer, '') + ']';
case exports.EnumToken.TimeTokenType:
case exports.EnumToken.AngleTokenType:
case exports.EnumToken.LengthTokenType:
case exports.EnumToken.DimensionTokenType:
case exports.EnumToken.FrequencyTokenType:
case exports.EnumToken.ResolutionTokenType:
let val = token.val.typ == exports.EnumToken.FractionTokenType ? renderToken(token.val, options, cache) : reduceNumber(token.val);
let unit = token.unit;
if (token.typ == exports.EnumToken.AngleTokenType && !val.includes('/')) {
const angle = getAngle(token);
let v;
let value = val + unit;
for (const u of ['turn', 'deg', 'rad', 'grad']) {
if (token.unit == u) {
continue;
}
switch (u) {
case 'turn':
v = reduceNumber(angle);
if (v.length + 4 < value.length) {
val = v;
unit = u;
value = v + u;
}
break;
case 'deg':
v = reduceNumber(angle * 360);
if (v.length + 3 < value.length) {
val = v;
unit = u;
value = v + u;
}
break;
case 'rad':
v = reduceNumber(angle * (2 * Math.PI));
if (v.length + 3 < value.length) {
val = v;
unit = u;
value = v + u;
}
break;
case 'grad':
v = reduceNumber(angle * 400);
if (v.length + 4 < value.length) {
val = v;
unit = u;
value = v + u;
}
break;
}
}
}
if (val === '0') {
if (token.typ == exports.EnumToken.TimeTokenType) {
return '0s';
}
if (token.typ == exports.EnumToken.FrequencyTokenType) {
return '0Hz';
}
// @ts-ignore
if (token.typ == exports.EnumToken.ResolutionTokenType) {
return '0x';
}
return '0';
}
if (token.typ == exports.EnumToken.TimeTokenType) {
if (unit == 'ms') {
// @ts-ignore
const v = reduceNumber(val / 1000);
if (v.length + 1 <= val.length) {
return v + 's';
}
return val + 'ms';
}
return val + 's';
}
return val.includes('/') ? val.replace('/', unit + '/') : val + unit;
case exports.EnumToken.FlexTokenType:
case exports.EnumToken.PercentageTokenType:
const uni = token.typ == exports.EnumToken.PercentageTokenType ? '%' : 'fr';
const perc = token.val.typ == exports.EnumToken.FractionTokenType ? renderToken(token.val, options, cache) : reduceNumber(token.val);
return options.minify && perc == '0' ? '0' : (perc.includes('/') ? perc.replace('/', uni + '/') : perc + uni);
case exports.EnumToken.NumberTokenType:
return token.val.typ == exports.EnumToken.FractionTokenType ? renderToken(token.val, options, cache) : reduceNumber(token.val);
case exports.EnumToken.CommentTokenType:
if (options.removeComments && (!options.preserveLicense || !token.val.startsWith('/*!'))) {
return '';
}
case exports.EnumToken.PseudoClassTokenType:
case exports.EnumToken.PseudoElementTokenType:
// https://www.w3.org/TR/selectors-4/#single-colon-pseudos
if (token.typ == exports.EnumToken.PseudoElementTokenType && pseudoElements.includes(token.val.slice(1))) {
return token.val.slice(1);
}
case exports.EnumToken.UrlTokenTokenType:
if (token.typ == exports.EnumToken.UrlTokenTokenType) {
if (options.output != null) {
if (!('original' in token)) {
// do not modify original token
token = { ...token };
Object.defineProperty(token, 'original', { enumerable: false, writable: false, value: token.val });
}
// @ts-ignore
if (!(token.original in cache)) {
let output = options.output ?? '';
const key = output + 'abs';
if (!(key in cache)) {
// @ts-ignore
cache[key] = options.dirname(options.resolve(output, options.cwd).absolute);
}
// @ts-ignore
cache[token.original] = options.resolve(token.original, cache[key]).relative;
}
// @ts-ignore
token.val = cache[token.original];
}
}
case exports.EnumToken.HashTokenType:
case exports.EnumToken.IdenTokenType:
case exports.EnumToken.AtRuleTokenType:
case exports.EnumToken.StringTokenType:
case exports.EnumToken.LiteralTokenType:
case exports.EnumToken.DashedIdenTokenType:
case exports.EnumToken.PseudoPageTokenType:
case exports.EnumToken.ClassSelectorTokenType:
return /* options.minify && 'Pseudo-class' == token.typ && '::' == token.val.slice(0, 2) ? token.val.slice(1) : */ token.val;
case exports.EnumToken.NestingSelectorTokenType:
return '&';
case exports.EnumToken.InvalidAttrTokenType:
return '[' + token.chi.reduce((acc, curr) => acc + renderToken(curr, options, cache), '');
case exports.EnumToken.InvalidClassSelectorTokenType:
return token.val;
case exports.EnumToken.DeclarationNodeType:
return token.nam + ':' + token.val.reduce((acc, curr) => acc + renderToken(curr, options, cache), '');
case exports.EnumToken.MediaQueryConditionTokenType:
return renderToken(token.l, options, cache, reducer, errors) + renderToken(token.op, options, cache, reducer, errors) + token.r.reduce((acc, curr) => acc + renderToken(curr, options, cache), '');
case exports.EnumToken.MediaFeatureTokenType:
return token.val;
case exports.EnumToken.MediaFeatureNotTokenType:
return 'not ' + renderToken(token.val, options, cache, reducer, errors);
case exports.EnumToken.MediaFeatureOnlyTokenType:
return 'only ' + renderToken(token.val, options, cache, reducer, errors);
case exports.EnumToken.MediaFeatureAndTokenType:
return 'and';
case exports.EnumToken.MediaFeatureOrTokenType:
return 'or';
default:
throw new Error(`render: unexpected token ${JSON.stringify(token, null, 1)}`);
}
errors?.push({ action: 'ignore', message: `render: unexpected token ${JSON.stringify(token, null, 1)}` });
return '';
}
// https://www.w3.org/TR/CSS21/syndata.html#syntax
// https://www.w3.org/TR/2021/CRD-css-syntax-3-20211224/#typedef-ident-token
// '\\'
const REVERSE_SOLIDUS = 0x5c;
const dimensionUnits = new Set([
'q', 'cap', 'ch', 'cm', 'cqb', 'cqh', 'cqi', 'cqmax', 'cqmin', 'cqw', 'dvb',
'dvh', 'dvi', 'dvmax', 'dvmin', 'dvw', 'em', 'ex', 'ic', 'in', 'lh', 'lvb',
'lvh', 'lvi', 'lvmax', 'lvw', 'mm', 'pc', 'pt', 'px', 'rem', 'rlh', 'svb',
'svh', 'svi', 'svmin', 'svw', 'vb', 'vh', 'vi', 'vmax', 'vmin', 'vw'
]);
const fontFormat = ['collection', 'embedded-opentype', 'opentype', 'svg', 'truetype', 'woff', 'woff2'];
const colorFontTech = ['color-colrv0', 'color-colrv1', 'color-svg', 'color-sbix', 'color-cbdt'];
const fontFeaturesTech = ['features-opentype', 'features-aat', 'features-graphite', 'incremental-patch', 'incremental-range', 'incremental-auto', 'variations', 'palettes'];
// https://drafts.csswg.org/mediaqueries/#media-types
const mediaTypes = ['all', 'print', 'screen',
/* deprecated */
'aural', 'braille', 'embossed', 'handheld', 'projection', 'tty', 'tv', 'speech'];
// https://www.w3.org/TR/css-values-4/#math-function
const mathFuncs = ['calc', 'clamp', 'min', 'max', 'round', 'mod', 'rem', 'sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'atan2', 'pow', 'sqrt', 'hypot', 'log', 'exp', 'abs', 'sign'];
const pseudoElements = [':before', ':after', ':first-line', ':first-letter'];
const webkitPseudoAliasMap = {
'-webkit-autofill': 'autofill',
'-webkit-any': 'is',
'-moz-any': 'is',
'-webkit-border-after': 'border-block-end',
'-webkit-border-after-color': 'border-block-end-color',
'-webkit-border-after-style': 'border-block-end-style',
'-webkit-border-after-width': 'border-block-end-width',
'-webkit-border-before': 'border-block-start',
'-webkit-border-before-color': 'border-block-start-color',
'-webkit-border-before-style': 'border-block-start-style',
'-webkit-border-before-width': 'border-block-start-width',
'-webkit-border-end': 'border-inline-end',
'-webkit-border-end-color': 'border-inline-end-color',
'-webkit-border-end-style': 'border-inline-end-style',
'-webkit-border-end-width': 'border-inline-end-width',
'-webkit-border-start': 'border-inline-start',
'-webkit-border-start-color': 'border-inline-start-color',
'-webkit-border-start-style': 'border-inline-start-style',
'-webkit-border-start-width': 'border-inline-start-width',
'-webkit-box-align': 'align-items',
'-webkit-box-direction': 'flex-direction',
'-webkit-box-flex': 'flex-grow',
'-webkit-box-lines': 'flex-flow',
'-webkit-box-ordinal-group': 'order',
'-webkit-box-orient': 'flex-direction',
'-webkit-box-pack': 'justify-content',
'-webkit-column-break-after': 'break-after',
'-webkit-column-break-before': 'break-before',
'-webkit-column-break-inside': 'break-inside',
'-webkit-font-feature-settings': 'font-feature-settings',
'-webkit-hyphenate-character': 'hyphenate-character',
'-webkit-initial-letter': 'initial-letter',
'-webkit-margin-end': 'margin-block-end',
'-webkit-margin-start': 'margin-block-start',
'-webkit-padding-after': 'padding-block-end',
'-webkit-padding-before': 'padding-block-start',
'-webkit-padding-end': 'padding-inline-end',
'-webkit-padding-start': 'padding-inline-start',
'-webkit-min-device-pixel-ratio': 'min-resolution',
'-webkit-max-device-pixel-ratio': 'max-resolution'
};
// https://developer.mozilla.org/en-US/docs/Web/CSS/WebKit_Extensions
// https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-scrollbar
const webkitExtensions = new Set([
'-webkit-app-region',
'-webkit-border-horizontal-spacing',
'-webkit-border-vertical-spacing',
'-webkit-box-reflect',
'-webkit-column-axis',
'-webkit-column-progression',
'-webkit-cursor-visibility',
'-webkit-font-smoothing',
'-webkit-hyphenate-limit-after',
'-webkit-hyphenate-limit-before',
'-webkit-hyphenate-limit-lines',
'-webkit-line-align',
'-webkit-line-box-contain',
'-webkit-line-clamp',
'-webkit-line-grid',
'-webkit-line-snap',
'-webkit-locale',
'-webkit-logical-height',
'-webkit-logical-width',
'-webkit-margin-after',
'-webkit-margin-before',
'-webkit-mask-box-image-outset',
'-webkit-mask-box-image-repeat',
'-webkit-mask-box-image-slice',
'-webkit-mask-box-image-source',
'-webkit-mask-box-image-width',
'-webkit-mask-box-image',
'-webkit-mask-composite',
'-webkit-mask-position-x',
'-webkit-mask-position-y',
'-webkit-mask-repeat-x',
'-webkit-mask-repeat-y',
'-webkit-mask-source-type',
'-webkit-max-logical-height',
'-webkit-max-logical-width',
'-webkit-min-logical-height',
'-webkit-min-logical-width',
'-webkit-nbsp-mode',
'-webkit-perspective-origin-x',
'-webkit-perspective-origin-y',
'-webkit-rtl-ordering',
'-webkit-tap-highlight-color',
'-webkit-text-decoration-skip',
'-webkit-text-decorations-in-effect',
'-webkit-text-fill-color',
'-webkit-text-security',
'-webkit-text-stroke-color',
'-webkit-text-stroke-width',
'-webkit-text-stroke',
'-webkit-text-zoom',
'-webkit-touch-callout',
'-webkit-transform-origin-x',
'-webkit-transform-origin-y',
'-webkit-transform-origin-z',
'-webkit-user-drag',
'-webkit-user-modify',
'-webkit-border-after',
'-webkit-border-after-color',
'-webkit-border-after-style',
'-webkit-border-after-width',
'-webkit-border-before',
'-webkit-border-before-color',
'-webkit-border-before-style',
'-webkit-border-before-width',
'-webkit-border-end',
'-webkit-border-end-color',
'-webkit-border-end-style',
'-webkit-border-end-width',
'-webkit-border-start',
'-webkit-border-start-color',
'-webkit-border-start-style',
'-webkit-border-start-width',
'-webkit-box-align',
'-webkit-box-direction',
'-webkit-box-flex-group',
'-webkit-box-flex',
'-webkit-box-lines',
'-webkit-box-ordinal-group',
'-webkit-box-orient',
'-webkit-box-pack',
'-webkit-column-break-after',
'-webkit-column-break-before',
'-webkit-column-break-inside',
'-webkit-font-feature-settings',
'-webkit-hyphenate-character',
'-webkit-initial-letter',
'-webkit-margin-end',
'-webkit-margin-start',
'-webkit-padding-after',
'-webkit-padding-before',
'-webkit-padding-end',
'-webkit-padding-start',
'-webkit-fill-available',
':-webkit-animating-full-screen-transition',
':-webkit-any',
':-webkit-any-link',
':-webkit-autofill',
':-webkit-autofill-strong-password',
':-webkit-drag',
':-webkit-full-page-media',
':-webkit-full-screen*',
':-webkit-full-screen-ancestor',
':-webkit-full-screen-document',
':-webkit-full-screen-controls-hidden',
'::-webkit-file-upload-button*',
'::-webkit-inner-spin-button',
'::-webkit-input-placeholder',
'::-webkit-meter-bar',
'::-webkit-meter-even-less-good-value',
'::-webkit-meter-inner-element',
'::-webkit-meter-optimum-value',
'::-webkit-meter-suboptimum-value',
'::-webkit-progress-bar',
'::-webkit-progress-inner-element',
'::-webkit-progress-value',
'::-webkit-search-cancel-button',
'::-webkit-search-results-button',
'::-webkit-slider-runnable-track',
'::-webkit-slider-thumb',
'-webkit-animation',
'-webkit-device-pixel-ratio',
'-webkit-transform-2d',
'-webkit-transform-3d',
'-webkit-transition',
'::-webkit-scrollbar',
'::-webkit-scrollbar-button',
'::-webkit-scrollbar',
'::-webkit-scrollbar-thumb',
'::-webkit-scrollbar-track',
'::-webkit-scrollbar-track-piece',
'::-webkit-scrollbar:vertical',
'::-webkit-scrollbar-corner ',
'::-webkit-resizer',
':vertical',
':horizontal',
]);
// https://developer.mozilla.org/en-US/docs/Web/CSS/Mozilla_Extensions
const mozExtensions = new Set([
'-moz-box-align',
'-moz-box-direction',
'-moz-box-flex',
'-moz-box-ordinal-group',
'-moz-box-orient',
'-moz-box-pack',
'-moz-float-edge',
'-moz-force-broken-image-icon',
'-moz-image-region',
'-moz-orient',
'-moz-osx-font-smoothing',
'-moz-user-focus',
'-moz-user-input',
'-moz-user-modify',
'-moz-animation',
'-moz-animation-delay',
'-moz-animation-direction',
'-moz-animation-duration',
'-moz-animation-fill-mode',
'-moz-animation-iteration-count',
'-moz-animation-name',
'-moz-animation-play-state',
'-moz-animation-timing-function',
'-moz-appearance',
'-moz-backface-visibility',
'-moz-background-clip',
'-moz-background-origin',
'-moz-background-inline-policy',
'-moz-background-size',
'-moz-border-end',
'-moz-border-end-color',
'-moz-border-end-style',
'-moz-border-end-width',
'-moz-border-image',
'-moz-border-start',
'-moz-border-start-color',
'-moz-border-start-style',
'-moz-border-start-width',
'-moz-box-sizing',
'clip-path',
'-moz-column-count',
'-moz-column-fill',
'-moz-column-gap',
'-moz-column-width',
'-moz-column-rule',
'-moz-column-rule-width',
'-moz-column-rule-style',
'-moz-column-rule-color',
'filter',
'-moz-font-feature-settings',
'-moz-font-language-override',
'-moz-hyphens',
'-moz-margin-end',
'-moz-margin-start',
'mask',
'-moz-opacity',
'-moz-outline',
'-moz-outline-color',
'-moz-outline-offset',
'-moz-outline-style',
'-moz-outline-width',
'-moz-padding-end',
'-moz-padding-start',
'-moz-perspective',
'-moz-perspective-origin',
'pointer-events',
'-moz-tab-size',
'-moz-text-align-last',
'-moz-text-decoration-color',
'-moz-text-decoration-line',
'-moz-text-decoration-style',
'-moz-text-size-adjust',
'-moz-transform',
'-moz-transform-origin',
'-moz-transform-style',
'-moz-transition',
'-moz-transition-delay',
'-moz-transition-duration',
'-moz-transition-property',
'-moz-transition-timing-function',
'-moz-user-select',
'-moz-initial',
'-moz-appearance',
'-moz-linear-gradient',
'-moz-radial-gradient',
'-moz-element',
'-moz-image-rect',
'::-moz-anonymous-block',
'::-moz-anonymous-positioned-block',
':-moz-any',
':-moz-any-link',
':-moz-broken',
'::-moz-canvas',
'::-moz-color-swatch',
'::-moz-cell-content',
':-moz-drag-over',
':-moz-first-node',
'::-moz-focus-inner',
'::-moz-focus-outer',
':-moz-full-screen',
':-moz-full-screen-ancestor',
':-moz-handler-blocked',
':-moz-handler-crashed',
':-moz-handler-disabled',
'::-moz-inline-table',
':-moz-last-node',
'::-moz-list-bullet',
'::-moz-list-number',
':-moz-loading',
':-moz-locale-dir',
':-moz-locale-dir',
':-moz-lwtheme',
':-moz-lwtheme-brighttext',
':-moz-lwtheme-darktext',
'::-moz-meter-bar',
':-moz-native-anonymous',
':-moz-only-whitespace',
'::-moz-pagebreak',
'::-moz-pagecontent',
':-moz-placeholder',
'::-moz-placeholder',
'::-moz-progress-bar',
'::-moz-range-progress',
'::-moz-range-thumb',
'::-moz-range-track',
':-moz-read-only',
':-moz-read-write',
'::-moz-scrolled-canvas',
'::-moz-scrolled-content',
'::-moz-selection',
':-moz-submit-invalid',
':-moz-suppressed',
'::-moz-svg-foreign-content',
'::-moz-table',
'::-moz-table-cell',
'::-moz-table-column',
'::-moz-table-column-group',
'::-moz-table-outer',
'::-moz-table-row',
'::-moz-table-row-group',
':-moz-ui-invalid',
':-moz-ui-valid',
':-moz-user-disabled',
'::-moz-viewport',
'::-moz-viewport-scroll',
':-moz-window-inactive',
'-moz-device-pixel-ratio',
'-moz-os-version',
'-moz-touch-enabled',
'-moz-windows-glass',
'-moz-alt-content'
]);
function isLength(dimension) {
return 'unit' in dimension && dimensionUnits.has(dimension.unit.toLowerCase());
}
function isResolution(dimension) {
return 'unit' in dimension && ['dpi', 'dpcm', 'dppx', 'x'].includes(dimension.unit.toLowerCase());
}
function isAngle(dimension) {
return 'unit' in dimension && ['rad', 'turn', 'deg', 'grad'].includes(dimension.unit.toLowerCase());
}
function isTime(dimension) {
return 'unit' in dimension && ['ms', 's'].includes(dimension.unit.toLowerCase());
}
function isFrequency(dimension) {
return 'unit' in dimension && ['hz', 'khz'].includes(dimension.unit.toLowerCase());
}
function isColorspace(token) {
if (token.typ != exports.EnumToken.IdenTokenType) {
return false;
}
return ['srgb', 'srgb-linear', 'lab', 'oklab', 'lch', 'oklch', 'xyz', 'xyz-d50', 'xyz-d65', 'display-p3', 'a98-rgb', 'prophoto-rgb', 'rec2020', 'rgb', 'hsl', 'hwb'].includes(token.val.toLowerCase());
}
function isRectangularOrthogonalColorspace(token) {
if (token.typ != exports.EnumToken.IdenTokenType) {
return false;
}
return ['srgb', 'srgb-linear', 'display-p3', 'a98-rgb', 'prophoto-rgb', 'rec2020', 'lab', 'oklab', 'xyz', 'xyz-d50', 'xyz-d65'].includes(token.val.toLowerCase());
}
function isPolarColorspace(token) {
if (token.typ != exports.EnumToken.IdenTokenType) {
return false;
}
return ['hsl', 'hwb', 'lch', 'oklch'].includes(token.val);
}
function isHueInterpolationMethod(token) {
if (token.typ != exports.EnumToken.IdenTokenType) {
return false;
}
return ['shorter', 'longer', 'increasing', 'decreasing'].includes(token.val);
}
function isColor(token) {
if (token.typ == exports.EnumToken.ColorTokenType) {
return true;
}
if (token.typ == exports.EnumToken.IdenTokenType) {
// named color
return token.val.toLowerCase() in COLORS_NAMES;
}
let isLegacySyntax = false;
if (token.typ == exports.EnumToken.FunctionTokenType && token.chi.length > 0 && colorsFunc.includes(token.val)) {
if (token.val == 'light-dark') {
const children = token.chi.filter((t) => [exports.EnumToken.IdenTokenType, exports.EnumToken.NumberTokenType, exports.EnumToken.LiteralTokenType, exports.EnumToken.ColorTokenType, exports.EnumToken.FunctionTokenType, exports.EnumToken.PercentageTokenType].includes(t.typ));
if (children.length != 2) {
return false;
}
if (isColor(children[0]) && isColor(children[1])) {
return true;
}
}
if (token.val == 'color') {
const children = token.chi.filter((t) => [exports.EnumToken.IdenTokenType, exports.EnumToken.NumberTokenType, exports.EnumToken.LiteralTokenType, exports.EnumToken.ColorTokenType, exports.EnumToken.FunctionTokenType, exports.EnumToken.PercentageTokenType].includes(t.typ));
const isRelative = children[0].typ == exports.EnumToken.IdenTokenType && children[0].val == 'from';
if (children.length < 4 || children.length > 8) {
return false;
}
if (!isRelative && !isColorspace(children[0])) {
return false;
}
for (let i = 1; i < children.length - 2; i++) {
if (children[i].typ == exports.EnumToken.IdenTokenType) {
if (children[i].val != 'none' &&
!(isRelative && ['alpha', 'r', 'g', 'b', 'x', 'y', 'z'].includes(children[i].val) || isColorspace(children[i]))) {
return false;
}
}
if (children[i].typ == exports.EnumToken.FunctionTokenType && !mathFuncs.includes(children[i].val)) {
return false;
}
}
if (children.length == 4 || (isRelative && children.length == 6)) {
return true;
}
if (children.length == 8 || children.length == 6) {
const sep = children.at(-2);
const alpha = children.at(-1);
// @ts-ignore
if ((children.length > 6 || !isRelative) && sep.typ != exports.EnumToken.LiteralTokenType || sep.val != '/') {
return false;
}
if (alpha.typ == exports.EnumToken.IdenTokenType && alpha.val != 'none') {
return false;
}
else {
// @ts-ignore
if (alpha.typ == exports.EnumToken.PercentageTokenType) {
if (+alpha.val < 0 || +alpha.val > 100) {
return false;
}
}
else if (alpha.typ == exports.EnumToken.NumberTokenType) {
if (+alpha.val < 0 || +alpha.val > 1) {
return false;
}
}
}
}
return true;
}
else if (token.val == 'color-mix') {
const children = token.chi.reduce((acc, t) => {
if (t.typ == exports.EnumToken.CommaTokenType) {
acc.push([]);
}
else {
if (![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType].includes(t.typ)) {
acc[acc.length - 1].push(t);
}
}
return acc;
}, [[]]);
if (children.length == 3) {
if (children[0].length > 3 ||
children[0][0].typ != exports.EnumToken.IdenTokenType ||
children[0][0].val != 'in' ||
!isColorspace(children[0][1]) ||
(children[0].length == 3 && !isHueInterpolationMethod(children[0][2])) ||
children[1].length > 2 ||
children[1][0].typ != exports.EnumToken.ColorTokenType ||
children[2].length > 2 ||
children[2][0].typ != exports.EnumToken.ColorTokenType) {
return false;
}
if (children[1].length == 2) {
if (!(children[1][1].typ == exports.EnumToken.PercentageTokenType || (children[1][1].typ == exports.EnumToken.NumberTokenType && children[1][1].val == '0'))) {
return false;
}
}
if (children[2].length == 2) {
if (!(children[2][1].typ == exports.EnumToken.PercentageTokenType || (children[2][1].typ == exports.EnumToken.NumberTokenType && children[2][1].val == '0'))) {
return false;
}
}
return true;
}
return false;
}
else {
const keywords = ['from', 'none'];
if (['rgb', 'hsl', 'hwb', 'lab', 'lch', 'oklab', 'oklch'].includes(token.val)) {
keywords.push('alpha', ...token.val.slice(-3).split(''));
}
// @ts-ignore
for (const v of token.chi) {
if (v.typ == exports.EnumToken.CommaTokenType) {
isLegacySyntax = true;
}
if (v.typ == exports.EnumToken.IdenTokenType) {
if (!(keywords.includes(v.val) || v.val.toLowerCase() in COLORS_NAMES)) {
return false;
}
if (keywords.includes(v.val)) {
if (isLegacySyntax) {
return false;
}
if (v.val == 'from' && ['rgba', 'hsla'].includes(token.val)) {
return false;
}
}
continue;
}
if (v.typ == exports.EnumToken.FunctionTokenType && (mathFuncs.includes(v.val) || v.val == 'var' || colorsFunc.includes(v.val))) {
continue;
}
if (![exports.EnumToken.ColorTokenType, exports.EnumToken.IdenTokenType, exports.EnumToken.NumberTokenType, exports.EnumToken.AngleTokenType, exports.EnumToken.PercentageTokenType, exports.EnumToken.CommaTokenType, exports.EnumToken.WhitespaceTokenType, exports.EnumToken.LiteralTokenType].includes(v.typ)) {
return false;
}
}
}
return true;
}
return false;
}
function isLetter(codepoint) {
// lowercase
return (codepoint >= 0x61 && codepoint <= 0x7a) ||
// uppercase
(codepoint >= 0x41 && codepoint <= 0x5a);
}
function isNonAscii(codepoint) {
return codepoint >= 0x80;
}
function isIdentStart(codepoint) {
// _
return codepoint == 0x5f || isLetter(codepoint) || isNonAscii(codepoint) || codepoint == REVERSE_SOLIDUS;
}
function isDigit(codepoint) {
return codepoint >= 0x30 && codepoint <= 0x39;
}
function isIdentCodepoint(codepoint) {
// -
return codepoint == 0x2d || isDigit(codepoint) || isIdentStart(codepoint);
}
function isIdent(name) {
const j = name.length - 1;
let i = 0;
let codepoint = name.charCodeAt(0);
// -
if (codepoint == 0x2d) {
const nextCodepoint = name.charCodeAt(1);
if (Number.isNaN(nextCodepoint)) {
return false;
}
// -
if (nextCodepoint == 0x2d) {
return true;
}
if (nextCodepoint == REVERSE_SOLIDUS) {
return name.length > 2 && !isNewLine(name.charCodeAt(2));
}
return true;
}
if (!isIdentStart(codepoint)) {
return false;
}
if (codepoint == REVERSE_SOLIDUS) {
codepoint = name.codePointAt(i + 1);
if (!isIdentCodepoint(codepoint)) {
return false;
}
i += String.fromCodePoint(codepoint).length;
if (i < j) {
codepoint = name.codePointAt(i);
if (!isIdentCodepoint(codepoint)) {
return false;
}
}
}
while (i < j) {
i += codepoint < 0x80 ? 1 : String.fromCodePoint(codepoint).length;
codepoint = name.charCodeAt(i);
if (codepoint == REVERSE_SOLIDUS) {
i += codepoint < 0x80 ? 1 : String.fromCodePoint(codepoint).length;
codepoint = name.charCodeAt(i);
i += codepoint < 0x80 ? 1 : String.fromCodePoint(codepoint).length;
continue;
}
if (!isIdentCodepoint(codepoint)) {
return false;
}
}
return true;
}
function isNonPrintable(codepoint) {
// null -> backspace
return (codepoint >= 0 && codepoint <= 0x8) ||
// tab
codepoint == 0xb ||
// delete
codepoint == 0x7f ||
(codepoint >= 0xe && codepoint <= 0x1f);
}
function isPseudo(name) {
return name.charAt(0) == ':' &&
((name.endsWith('(') && isIdent(name.charAt(1) == ':' ? name.slice(2, -1) : name.slice(1, -1))) ||
isIdent(name.charAt(1) == ':' ? name.slice(2) : name.slice(1)));
}
function isHash(name) {
return name.charAt(0) == '#' && isIdent(name.charAt(1));
}
function isNumber(name) {
if (name.length == 0) {
return false;
}
let codepoint = name.charCodeAt(0);
let i = 0;
const j = name.length;
if (j == 1 && !isDigit(codepoint)) {
return false;
}
// '+' '-'
if ([0x2b, 0x2d].includes(codepoint)) {
i++;
}
// consume digits
while (i < j) {
codepoint = name.charCodeAt(i);
if (isDigit(codepoint)) {
i++;
continue;
}
// '.' 'E' 'e'
if (codepoint == 0x2e || codepoint == 0x45 || codepoint == 0x65) {
break;
}
return false;
}
// '.'
if (codepoint == 0x2e) {
if (!isDigit(name.charCodeAt(++i))) {
return false;
}
}
while (i < j) {
codepoint = name.charCodeAt(i);
if (isDigit(codepoint)) {
i++;
continue;
}
// 'E' 'e'
if (codepoint == 0x45 || codepoint == 0x65) {
i++;
break;
}
return false;
}
// 'E' 'e'
if (codepoint == 0x45 || codepoint == 0x65) {
if (i == j) {
return false;
}
codepoint = name.charCodeAt(i + 1);
// '+' '-'
if ([0x2b, 0x2d].includes(codepoint)) {
i++;
}
codepoint = name.charCodeAt(i + 1);
if (!isDigit(codepoint)) {
return false;
}
}
while (++i < j) {
codepoint = name.charCodeAt(i);
if (!isDigit(codepoint)) {
return false;
}
}
return true;
}
function isDimension(name) {
let index = name.length;
while (index--) {
if (isLetter(name.charCodeAt(index))) {
continue;
}
index++;
break;
}
const number = name.slice(0, index);
return number.length > 0 && isIdentStart(name.charCodeAt(index)) && isNumber(number);
}
function isPercentage(name) {
return name.endsWith('%') && isNumber(name.slice(0, -1));
}
function isFlex(name) {
return name.endsWith('fr') && isNumber(name.slice(0, -2));
}
function parseDimension(name) {
let index = name.length;
while (index--) {
if (isLetter(name.charCodeAt(index))) {
continue;
}
index++;
break;
}
const dimension = {
typ: exports.EnumToken.DimensionTokenType,
val: name.slice(0, index),
unit: name.slice(index)
};
if (isAngle(dimension)) {
// @ts-ignore
dimension.typ = exports.EnumToken.AngleTokenType;
}
else if (isLength(dimension)) {
// @ts-ignore
dimension.typ = exports.EnumToken.LengthTokenType;
}
else if (isTime(dimension)) {
// @ts-ignore
dimension.typ = exports.EnumToken.TimeTokenType;
}
else if (isResolution(dimension)) {
// @ts-ignore
dimension.typ = exports.EnumToken.ResolutionTokenType;
if (dimension.unit == 'dppx') {
dimension.unit = 'x';
}
}
else if (isFrequency(dimension)) {
// @ts-ignore
dimension.typ = exports.EnumToken.FrequencyTokenType;
}
return dimension;
}
function isHexColor(name) {
if (name.charAt(0) != '#' || ![4, 5, 7, 9].includes(name.length)) {
return false;
}
for (let chr of name.slice(1)) {
let codepoint = chr.charCodeAt(0);
if (!isDigit(codepoint) &&
// A-F
!(codepoint >= 0x41 && codepoint <= 0x46) &&
// a-f
!(codepoint >= 0x61 && codepoint <= 0x66)) {
return false;
}
}
return true;
}
/*
export function isHexDigit(name: string): boolean {
if (name.length || name.length > 6) {
return false;
}
for (let chr of name) {
let codepoint = <number>chr.charCodeAt(0);
if (!isDigit(codepoint) &&
// A F
!(codepoint >= 0x41 && codepoint <= 0x46) &&
// a f
!(codepoint >= 0x61 && codepoint <= 0x66)) {
return false;
}
}
return true;
}
*/
function isFunction(name) {
return name.endsWith('(') && isIdent(name.slice(0, -1));
}
function isAtKeyword(name) {
return name.charCodeAt(0) == 0x40 && isIdent(name.slice(1));
}
function isNewLine(codepoint) {
// \n \r \f
return codepoint == 0xa || codepoint == 0xc || codepoint == 0xd;
}
function isWhiteSpace(codepoint) {
return codepoint == 0x9 || codepoint == 0x20 ||
// isNewLine
codepoint == 0xa || codepoint == 0xc || codepoint == 0xd;
}
var properties = {
gap: {
shorthand: "gap",
properties: [
"row-gap",
"column-gap"
],
types: [
"Length",
"Perc"
],
multiple: false,
separator: null,
keywords: [
"normal"
]
},
"row-gap": {
shorthand: "gap"
},
"column-gap": {
shorthand: "gap"
},
inset: {
shorthand: "inset",
properties: [
"top",
"right",
"bottom",
"left"
],
types: [
"Length",
"Perc"
],
multiple: false,
separator: null,
keywords: [
"auto"
]
},
top: {
shorthand: "inset"
},
right: {
shorthand: "inset"
},
bottom: {
shorthand: "inset"
},
left: {
shorthand: "inset"
},
margin: {
shorthand: "margin",
properties: [
"margin-top",
"margin-right",
"margin-bottom",
"margin-left"
],
types: [
"Length",
"Perc"
],
multiple: false,
separator: null,
keywords: [
"auto"
]
},
"margin-top": {
shorthand: "margin"
},
"margin-right": {
shorthand: "margin"
},
"margin-bottom": {
shorthand: "margin"
},
"margin-left": {
shorthand: "margin"
},
padding: {
shorthand: "padding",
properties: [
"padding-top",
"padding-right",
"padding-bottom",
"padding-left"
],
types: [
"Length",
"Perc"
],
keywords: [
]
},
"padding-top": {
shorthand: "padding"
},
"padding-right": {
shorthand: "padding"
},
"padding-bottom": {
shorthand: "padding"
},
"padding-left": {
shorthand: "padding"
},
"border-radius": {
shorthand: "border-radius",
properties: [
"border-top-left-radius",
"border-top-right-radius",
"border-bottom-right-radius",
"border-bottom-left-radius"
],
types: [
"Length",
"Perc"
],
multiple: true,
separator: "/",
keywords: [
]
},
"border-top-left-radius": {
shorthand: "border-radius"
},
"border-top-right-radius": {
shorthand: "border-radius"
},
"border-bottom-right-radius": {
shorthand: "border-radius"
},
"border-bottom-left-radius": {
shorthand: "border-radius"
},
"border-width": {
shorthand: "border-width",
map: "border",
properties: [
"border-top-width",
"border-right-width",
"border-bottom-width",
"border-left-width"
],
types: [
"Length",
"Perc"
],
"default": [
"medium"
],
keywords: [
"thin",
"medium",
"thick"
]
},
"border-top-width": {
map: "border",
shorthand: "border-width"
},
"border-right-width": {
map: "border",
shorthand: "border-width"
},
"border-bottom-width": {
map: "border",
shorthand: "border-width"
},
"border-left-width": {
map: "border",
shorthand: "border-width"
},
"border-style": {
shorthand: "border-style",
map: "border",
properties: [
"border-top-style",
"border-right-style",
"border-bottom-style",
"border-left-style"
],
types: [
],
"default": [
"none"
],
keywords: [
"none",
"hidden",
"dotted",
"dashed",
"solid",
"double",
"groove",
"ridge",
"inset",
"outset"
]
},
"border-top-style": {
map: "border",
shorthand: "border-style"
},
"border-right-style": {
map: "border",
shorthand: "border-style"
},
"border-bottom-style": {
map: "border",
shorthand: "border-style"
},
"border-left-style": {
map: "border",
shorthand: "border-style"
},
"border-color": {
shorthand: "border-color",
map: "border",
properties: [
"border-top-color",
"border-right-color",
"border-bottom-color",
"border-left-color"
],
types: [
"Color"
],
"default": [
"currentcolor"
],
keywords: [
]
},
"border-top-color": {
map: "border",
shorthand: "border-color"
},
"border-right-color": {
map: "border",
shorthand: "border-color"
},
"border-bottom-color": {
map: "border",
shorthand: "border-color"
},
"border-left-color": {
map: "border",
shorthand: "border-color"
}
};
var map = {
"flex-flow": {
shorthand: "flex-flow",
pattern: "flex-direction flex-wrap",
keywords: [
],
"default": [
"row",
"nowrap"
],
properties: {
"flex-direction": {
keywords: [
"row",
"row-reverse",
"column",
"column-reverse"
],
"default": [
"row"
],
types: [
]
},
"flex-wrap": {
keywords: [
"wrap",
"nowrap",
"wrap-reverse"
],
"default": [
"nowrap"
],
types: [
]
}
}
},
"flex-direction": {
shorthand: "flex-flow"
},
"flex-wrap": {
shorthand: "flex-flow"
},
container: {
shorthand: "container",
pattern: "container-name container-type",
keywords: [
],
"default": [
],
properties: {
"container-name": {
required: true,
multiple: true,
keywords: [
"none"
],
"default": [
"none"
],
types: [
"Iden",
"DashedIden"
]
},
"container-type": {
previous: "container-name",
prefix: {
typ: "Literal",
val: "/"
},
keywords: [
"size",
"inline-size",
"normal"
],
"default": [
"normal"
],
types: [
]
}
}
},
"container-name": {
shorthand: "container"
},
"container-type": {
shorthand: "container"
},
flex: {
shorthand: "flex",
pattern: "flex-grow flex-shrink flex-basis",
keywords: [
"auto",
"none",
"initial"
],
"default": [
],
mapping: {
"0 1 auto": "initial",
"0 0 auto": "none",
"1 1 auto": "auto"
},
properties: {
"flex-grow": {
required: true,
keywords: [
],
"default": [
],
types: [
"Number"
]
},
"flex-shrink": {
keywords: [
],
"default": [
],
types: [
"Number"
]
},
"flex-basis": {
keywords: [
"max-content",
"min-content",
"fit-content",
"fit-content",
"content",
"auto"
],
"default": [
],
types: [
"Length",
"Perc"
]
}
}
},
"flex-grow": {
shorthand: "flex"
},
"flex-shrink": {
shorthand: "flex"
},
"flex-basis": {
shorthand: "flex"
},
columns: {
shorthand: "columns",
pattern: "column-count column-width",
keywords: [
"auto"
],
"default": [
"auto",
"auto auto"
],
properties: {
"column-count": {
keywords: [
"auto"
],
"default": [
"auto"
],
types: [
"Number"
]
},
"column-width": {
keywords: [
"auto"
],
"default": [
"auto"
],
types: [
"Length"
]
}
}
},
"column-count": {
shorthand: "columns"
},
"column-width": {
shorthand: "columns"
},
transition: {
shorthand: "transition",
multiple: true,
separator: {
typ: "Comma"
},
pattern: "transition-property transition-duration transition-timing-function transition-delay transition-behavior",
keywords: [
"none",
"all"
],
"default": [
"0s",
"0ms",
"all",
"ease",
"none",
"normal"
],
mapping: {
"cubic-bezier(.25,.1,.25,1)": "ease",
"cubic-bezier(0,0,1,1)": "linear",
"cubic-bezier(.42,0,1,1)": "ease-in",
"cubic-bezier(0,0,.58,1)": "ease-out",
"cubic-bezier(.42,0,.58,.42)": "ease-in-out"
},
properties: {
"transition-property": {
keywords: [
"none",
"all"
],
"default": [
"all"
],
types: [
"Iden"
]
},
"transition-duration": {
keywords: [
],
"default": [
"0s",
"0ms",
"normal"
],
types: [
"Time"
]
},
"transition-timing-function": {
keywords: [
"ease",
"ease-in",
"ease-out",
"ease-in-out",
"linear",
"step-start",
"step-end"
],
"default": [
"ease"
],
types: [
"TimingFunction"
],
mapping: {
"cubic-bezier(.25,.1,.25,1)": "ease",
"cubic-bezier(0,0,1,1)": "linear",
"cubic-bezier(.42,0,1,1)": "ease-in",
"cubic-bezier(0,0,.58,1)": "ease-out",
"cubic-bezier(.42,0,.58,.42)": "ease-in-out"
}
},
"transition-delay": {
keywords: [
],
"default": [
"0s"
],
types: [
"Time"
]
},
"transition-behavior": {
keywords: [
"normal",
"allow-discrete"
],
"default": [
"normal"
],
types: [
]
}
}
},
"transition-property": {
shorthand: "transition"
},
"transition-duration": {
shorthand: "transition"
},
"transition-timing-function": {
shorthand: "transition"
},
"transition-delay": {
shorthand: "transition"
},
"transition-behavior": {
shorthand: "transition"
},
animation: {
shorthand: "animation",
pattern: "animation-name animation-duration animation-timing-function animation-delay animation-iteration-count animation-direction animation-fill-mode animation-play-state animation-timeline",
"default": [
"1",
"0s",
"0ms",
"none",
"ease",
"normal",
"running",
"auto"
],
properties: {
"animation-name": {
keywords: [
"none"
],
"default": [
"none"
],
types: [
"Iden"
]
},
"animation-duration": {
keywords: [
"auto"
],
"default": [
"0s",
"0ms",
"auto"
],
types: [
"Time"
],
mapping: {
auto: "0s"
}
},
"animation-timing-function": {
keywords: [
"ease",
"ease-in",
"ease-out",
"ease-in-out",
"linear",
"step-start",
"step-end"
],
"default": [
"ease"
],
types: [
"TimingFunction"
],
mapping: {
"cubic-bezier(.25,.1,.25,1)": "ease",
"cubic-bezier(0,0,1,1)": "linear",
"cubic-bezier(.42,0,1,1)": "ease-in",
"cubic-bezier(0,0,.58,1)": "ease-out",
"cubic-bezier(.42,0,.58,.42)": "ease-in-out"
}
},
"animation-delay": {
keywords: [
],
"default": [
"0s",
"0ms"
],
types: [
"Time"
]
},
"animation-iteration-count": {
keywords: [
"infinite"
],
"default": [
"1"
],
types: [
"Number"
]
},
"animation-direction": {
keywords: [
"normal",
"reverse",
"alternate",
"alternate-reverse"
],
"default": [
"normal"
],
types: [
]
},
"animation-fill-mode": {
keywords: [
"none",
"forwards",
"backwards",
"both"
],
"default": [
"none"
],
types: [
]
},
"animation-play-state": {
keywords: [
"running",
"paused"
],
"default": [
"running"
],
types: [
]
},
"animation-timeline": {
keywords: [
"none",
"auto"
],
"default": [
"auto"
],
types: [
"DashedIden",
"TimelineFunction"
]
}
}
},
"animation-name": {
shorthand: "animation"
},
"animation-duration": {
shorthand: "animation"
},
"animation-timing-function": {
shorthand: "animation"
},
"animation-delay": {
shorthand: "animation"
},
"animation-iteration-count": {
shorthand: "animation"
},
"animation-direction": {
shorthand: "animation"
},
"animation-fill-mode": {
shorthand: "animation"
},
"animation-play-state": {
shorthand: "animation"
},
"animation-timeline": {
shorthand: "animation"
},
"text-emphasis": {
shorthand: "text-emphasis",
pattern: "text-emphasis-color text-emphasis-style",
"default": [
"none",
"currentcolor"
],
properties: {
"text-emphasis-style": {
keywords: [
"none",
"filled",
"open",
"dot",
"circle",
"double-circle",
"triangle",
"sesame"
],
"default": [
"none"
],
types: [
"String"
]
},
"text-emphasis-color": {
"default": [
"currentcolor"
],
types: [
"Color"
]
}
}
},
"text-emphasis-style": {
shorthand: "text-emphasis"
},
"text-emphasis-color": {
shorthand: "text-emphasis"
},
border: {
shorthand: "border",
pattern: "border-color border-style border-width",
keywords: [
"none"
],
"default": [
"0",
"none"
],
properties: {
"border-color": {
types: [
"Color"
],
"default": [
"currentcolor"
],
keywords: [
]
},
"border-style": {
types: [
],
"default": [
"none"
],
keywords: [
"none",
"hidden",
"dotted",
"dashed",
"solid",
"double",
"groove",
"ridge",
"inset",
"outset"
]
},
"border-width": {
types: [
"Length",
"Perc"
],
"default": [
"medium"
],
keywords: [
"thin",
"medium",
"thick"
]
}
}
},
"border-color": {
shorthand: "border"
},
"border-style": {
shorthand: "border"
},
"border-width": {
shorthand: "border"
},
"list-style": {
shorthand: "list-style",
pattern: "list-style-type list-style-position list-style-image",
keywords: [
"none",
"outside"
],
"default": [
"none",
"outside"
],
properties: {
"list-style-position": {
types: [
],
"default": [
"outside"
],
keywords: [
"inside",
"outside"
]
},
"list-style-image": {
"default": [
"none"
],
keywords: [
"node"
],
types: [
"UrlFunc",
"ImageFunc"
]
},
"list-style-type": {
types: [
"String",
"Iden",
"Symbols"
],
"default": [
"disc"
],
keywords: [
"disc",
"circle",
"square",
"decimal",
"decimal-leading-zero",
"lower-roman",
"upper-roman",
"lower-greek",
"lower-latin",
"upper-latin",
"none"
]
}
}
},
"list-style-position": {
shorthand: "list-style"
},
"list-style-image": {
shorthand: "list-style"
},
"list-style-type": {
shorthand: "list-style"
},
overflow: {
shorthand: "overflow",
pattern: "overflow-x overflow-y",
keywords: [
"auto",
"visible",
"hidden",
"clip",
"scroll"
],
"default": [
],
mapping: {
"visible visible": "visible",
"auto auto": "auto",
"hidden hidden": "hidden",
"scroll scroll": "scroll"
},
properties: {
"overflow-x": {
"default": [
],
types: [
],
keywords: [
"auto",
"visible",
"hidden",
"clip",
"scroll"
]
},
"overflow-y": {
"default": [
],
types: [
],
keywords: [
"auto",
"visible",
"hidden",
"clip",
"scroll"
]
}
}
},
"overflow-x": {
shorthand: "overflow"
},
"overflow-y": {
shorthand: "overflow"
},
outline: {
shorthand: "outline",
pattern: "outline-color outline-style outline-width",
keywords: [
"none"
],
"default": [
"0",
"none",
"currentcolor"
],
properties: {
"outline-color": {
types: [
"Color"
],
"default": [
"currentcolor"
],
keywords: [
"currentcolor"
]
},
"outline-style": {
types: [
],
"default": [
"none"
],
keywords: [
"auto",
"none",
"dotted",
"dashed",
"solid",
"double",
"groove",
"ridge",
"inset",
"outset"
]
},
"outline-width": {
types: [
"Length",
"Perc"
],
"default": [
"medium"
],
keywords: [
"thin",
"medium",
"thick"
]
}
}
},
"outline-color": {
shorthand: "outline"
},
"outline-style": {
shorthand: "outline"
},
"outline-width": {
shorthand: "outline"
},
font: {
shorthand: "font",
pattern: "font-weight font-style font-size line-height font-stretch font-variant font-family",
keywords: [
"caption",
"icon",
"menu",
"message-box",
"small-caption",
"status-bar",
"-moz-window, ",
"-moz-document, ",
"-moz-desktop, ",
"-moz-info, ",
"-moz-dialog",
"-moz-button",
"-moz-pull-down-menu",
"-moz-list",
"-moz-field"
],
"default": [
],
properties: {
"font-weight": {
types: [
"Number"
],
"default": [
"400",
"normal"
],
keywords: [
"normal",
"bold",
"lighter",
"bolder"
],
constraints: {
value: {
min: "1",
max: "1000"
}
},
mapping: {
thin: "100",
hairline: "100",
"extra light": "200",
"ultra light": "200",
light: "300",
normal: "400",
regular: "400",
medium: "500",
"semi bold": "600",
"demi bold": "600",
bold: "700",
"extra bold": "800",
"ultra bold": "800",
black: "900",
heavy: "900",
"extra black": "950",
"ultra black": "950"
}
},
"font-style": {
types: [
"Angle"
],
"default": [
"normal"
],
keywords: [
"normal",
"italic",
"oblique"
]
},
"font-size": {
types: [
"Length",
"Perc"
],
"default": [
],
keywords: [
"xx-small",
"x-small",
"small",
"medium",
"large",
"x-large",
"xx-large",
"xxx-large",
"larger",
"smaller"
],
required: true
},
"line-height": {
types: [
"Length",
"Perc",
"Number"
],
"default": [
"normal"
],
keywords: [
"normal"
],
previous: "font-size",
prefix: {
typ: "Literal",
val: "/"
}
},
"font-stretch": {
types: [
"Perc"
],
"default": [
"normal"
],
keywords: [
"ultra-condensed",
"extra-condensed",
"condensed",
"semi-condensed",
"normal",
"semi-expanded",
"expanded",
"extra-expanded",
"ultra-expanded"
],
mapping: {
"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%"
}
},
"font-variant": {
types: [
],
"default": [
"normal"
],
keywords: [
"normal",
"none",
"common-ligatures",
"no-common-ligatures",
"discretionary-ligatures",
"no-discretionary-ligatures",
"historical-ligatures",
"no-historical-ligatures",
"contextual",
"no-contextual",
"historical-forms",
"small-caps",
"all-small-caps",
"petite-caps",
"all-petite-caps",
"unicase",
"titling-caps",
"ordinal",
"slashed-zero",
"lining-nums",
"oldstyle-nums",
"proportional-nums",
"tabular-nums",
"diagonal-fractions",
"stacked-fractions",
"ordinal",
"slashed-zero",
"ruby",
"jis78",
"jis83",
"jis90",
"jis04",
"simplified",
"traditional",
"full-width",
"proportional-width",
"ruby",
"sub",
"super",
"text",
"emoji",
"unicode"
]
},
"font-family": {
types: [
"String",
"Iden"
],
"default": [
],
keywords: [
"serif",
"sans-serif",
"monospace",
"cursive",
"fantasy",
"system-ui",
"ui-serif",
"ui-sans-serif",
"ui-monospace",
"ui-rounded",
"math",
"emoji",
"fangsong"
],
required: true,
multiple: true,
separator: {
typ: "Comma"
}
}
}
},
"font-weight": {
shorthand: "font"
},
"font-style": {
shorthand: "font"
},
"font-size": {
shorthand: "font"
},
"line-height": {
shorthand: "font"
},
"font-stretch": {
shorthand: "font"
},
"font-variant": {
shorthand: "font"
},
"font-family": {
shorthand: "font"
},
background: {
shorthand: "background",
pattern: "background-attachment background-origin background-clip background-color background-image background-repeat background-position background-size",
keywords: [
"none"
],
"default": [
"0 0",
"none",
"auto",
"repeat",
"transparent",
"#0000",
"scroll",
"padding-box",
"border-box"
],
multiple: true,
set: {
"background-origin": [
"background-clip"
]
},
separator: {
typ: "Comma"
},
properties: {
"background-repeat": {
types: [
],
"default": [
"repeat"
],
multiple: true,
keywords: [
"repeat-x",
"repeat-y",
"repeat",
"space",
"round",
"no-repeat"
],
mapping: {
"repeat no-repeat": "repeat-x",
"no-repeat repeat": "repeat-y",
"repeat repeat": "repeat",
"space space": "space",
"round round": "round",
"no-repeat no-repeat": "no-repeat"
}
},
"background-color": {
types: [
"Color"
],
"default": [
"#0000",
"transparent"
],
multiple: true,
keywords: [
]
},
"background-image": {
types: [
"UrlFunc",
"ImageFunc"
],
"default": [
"none"
],
keywords: [
"none"
]
},
"background-attachment": {
types: [
],
"default": [
"scroll"
],
multiple: true,
keywords: [
"scroll",
"fixed",
"local"
]
},
"background-clip": {
types: [
],
"default": [
"border-box"
],
multiple: true,
keywords: [
"border-box",
"padding-box",
"content-box",
"text"
]
},
"background-origin": {
types: [
],
"default": [
"padding-box"
],
multiple: true,
keywords: [
"border-box",
"padding-box",
"content-box"
]
},
"background-position": {
multiple: true,
types: [
"Perc",
"Length"
],
"default": [
"0 0",
"top left",
"left top"
],
keywords: [
"top",
"left",
"center",
"bottom",
"right"
],
mapping: {
left: "0",
top: "0",
center: "50%",
"center center": "50%",
"50% 50%": "50%",
bottom: "100%",
right: "100%"
},
constraints: {
mapping: {
max: 2
}
}
},
"background-size": {
multiple: true,
previous: "background-position",
prefix: {
typ: "Literal",
val: "/"
},
types: [
"Perc",
"Length"
],
"default": [
"auto",
"auto auto"
],
keywords: [
"auto",
"cover",
"contain"
],
mapping: {
"auto auto": "auto"
}
}
}
},
"background-repeat": {
shorthand: "background"
},
"background-color": {
shorthand: "background"
},
"background-image": {
shorthand: "background"
},
"background-attachment": {
shorthand: "background"
},
"background-clip": {
shorthand: "background"
},
"background-origin": {
shorthand: "background"
},
"background-position": {
shorthand: "background"
},
"background-size": {
shorthand: "background"
}
};
var config$3 = {
properties: properties,
map: map
};
Object.freeze(config$3);
const getConfig = () => config$3;
function matchType(val, properties) {
if (val.typ == exports.EnumToken.IdenTokenType && properties.keywords.includes(val.val) ||
// @ts-ignore
(properties.types.some((t) => exports.EnumToken[t] == val.typ))) {
return true;
}
if (val.typ == exports.EnumToken.NumberTokenType && val.val == '0') {
// @ts-ignore
return properties.types.some((type) => {
// @ts-ignore
const typ = exports.EnumToken[type];
return typ == exports.EnumToken.LengthTokenType || typ == exports.EnumToken.AngleTokenType;
});
}
if (val.typ == exports.EnumToken.FunctionTokenType) {
if (mathFuncs.includes(val.val)) {
return val.chi.every(((t) => [exports.EnumToken.Add, exports.EnumToken.Mul, exports.EnumToken.Div, exports.EnumToken.Sub, exports.EnumToken.LiteralTokenType, exports.EnumToken.CommaTokenType, exports.EnumToken.WhitespaceTokenType, exports.EnumToken.DimensionTokenType, exports.EnumToken.NumberTokenType, exports.EnumToken.LengthTokenType, exports.EnumToken.AngleTokenType, exports.EnumToken.PercentageTokenType, exports.EnumToken.ResolutionTokenType, exports.EnumToken.TimeTokenType, exports.EnumToken.BinaryExpressionTokenType].includes(t.typ) || matchType(t, properties)));
}
// match type defined like function 'symbols()', 'url()', 'attr()' etc.
// return properties.types.includes((<FunctionToken>val).val + '()')
}
return false;
}
function parseDeclarationNode(node, errors, src, position) {
while (node.val[0]?.typ == exports.EnumToken.WhitespaceTokenType) {
node.val.shift();
}
if (node.val.filter((t) => ![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType].includes(t.typ)).length == 0) {
errors.push({
action: 'drop',
message: 'doParse: invalid declaration',
location: { src, ...position }
});
return null;
}
for (const { value: val, parent } of walkValues(node.val, node)) {
if (val.typ == exports.EnumToken.AttrTokenType && val.chi.every((t) => [exports.EnumToken.IdenTokenType, exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType].includes(t.typ))) {
// @ts-ignore
val.typ = exports.EnumToken.IdenListTokenType;
}
else if (val.typ == exports.EnumToken.StringTokenType && (node.nam == 'grid' || node.nam == 'grid-template-areas' || node.nam == 'grid-template-rows' || node.nam == 'grid-template-columns')) {
val.val = val.val.at(0) + parseGridTemplate(val.val.slice(1, -1)) + val.val.at(-1);
// @ts-ignore
const array = parent?.chi ?? node.val;
const index = array.indexOf(val);
if (index > 0 && array[index - 1].typ == exports.EnumToken.WhitespaceTokenType) {
array.splice(index - 1, 1);
}
}
}
return node;
}
function parseGridTemplate(template) {
let result = '';
let buffer = '';
for (let i = 0; i < template.length; i++) {
const char = template[i];
if (isWhiteSpace(char.codePointAt(0))) {
while (i + 1 < template.length && isWhiteSpace(template[i + 1].codePointAt(0))) {
i++;
}
result += buffer + ' ';
buffer = '';
}
else if (char == '.') {
while (i + 1 < template.length && template[i + 1] == '.') {
i++;
}
if (isWhiteSpace((result.at(-1)?.codePointAt(0)))) {
result = result.slice(0, -1);
}
result += buffer + char;
buffer = '';
}
else {
buffer += char;
}
}
return buffer.length > 0 ? result + buffer : result;
}
function consumeWhiteSpace(parseInfo) {
let count = 0;
while (isWhiteSpace(parseInfo.stream.charAt(count + parseInfo.currentPosition.ind + 1).charCodeAt(0))) {
count++;
}
next(parseInfo, count);
return count;
}
function pushToken(token, parseInfo, hint) {
const result = {
token,
len: parseInfo.currentPosition.ind - parseInfo.position.ind,
hint,
position: { ...parseInfo.position },
bytesIn: parseInfo.currentPosition.ind + 1
};
parseInfo.position.ind = parseInfo.currentPosition.ind;
parseInfo.position.lin = parseInfo.currentPosition.lin;
parseInfo.position.col = Math.max(parseInfo.currentPosition.col, 1);
return result;
}
function* consumeString(quoteStr, buffer, parseInfo) {
const quote = quoteStr;
let value;
let hasNewLine = false;
if (buffer.length > 0) {
yield pushToken(buffer, parseInfo);
buffer = '';
}
buffer += quoteStr;
while (value = peek(parseInfo)) {
if (value == '\\') {
const sequence = peek(parseInfo, 6);
let escapeSequence = '';
let codepoint;
let i;
for (i = 1; i < sequence.length; i++) {
codepoint = sequence.charCodeAt(i);
if (codepoint == 0x20 ||
(codepoint >= 0x61 && codepoint <= 0x66) ||
(codepoint >= 0x41 && codepoint <= 0x46) ||
(codepoint >= 0x30 && codepoint <= 0x39)) {
escapeSequence += sequence[i];
if (codepoint == 0x20) {
break;
}
continue;
}
break;
}
if (i == 1) {
buffer += value + sequence[i];
next(parseInfo, 2);
continue;
}
if (escapeSequence.trimEnd().length > 0) {
const codepoint = parseInt(escapeSequence, 16);
if (codepoint == 0 ||
// leading surrogate
(0xD800 <= codepoint && codepoint <= 0xDBFF) ||
// trailing surrogate
(0xDC00 <= codepoint && codepoint <= 0xDFFF)) {
buffer += String.fromCodePoint(0xFFFD);
}
else {
buffer += String.fromCodePoint(codepoint);
}
next(parseInfo, escapeSequence.length + 1 + (isWhiteSpace(peek(parseInfo)?.charCodeAt(0)) ? 1 : 0));
continue;
}
buffer += next(parseInfo, 2);
continue;
}
if (value == quote) {
buffer += value;
yield pushToken(buffer, parseInfo, hasNewLine ? exports.EnumToken.BadStringTokenType : exports.EnumToken.StringTokenType);
next(parseInfo);
// i += value.length;
buffer = '';
return;
}
if (isNewLine(value.charCodeAt(0))) {
hasNewLine = true;
}
if (hasNewLine && value == ';') {
yield pushToken(buffer + value, parseInfo, exports.EnumToken.BadStringTokenType);
buffer = '';
next(parseInfo);
break;
}
buffer += value;
next(parseInfo);
}
if (hasNewLine) {
yield pushToken(buffer, parseInfo, exports.EnumToken.BadStringTokenType);
}
else {
// EOF - 'Unclosed-string' fixed
yield pushToken(buffer + quote, parseInfo, exports.EnumToken.StringTokenType);
}
}
function peek(parseInfo, count = 1) {
if (count == 1) {
return parseInfo.stream.charAt(parseInfo.currentPosition.ind + 1);
}
return parseInfo.stream.slice(parseInfo.currentPosition.ind + 1, parseInfo.currentPosition.ind + count + 1);
}
function prev(parseInfo, count = 1) {
if (count == 1) {
return parseInfo.currentPosition.ind == 0 ? '' : parseInfo.stream.charAt(parseInfo.currentPosition.ind - 1);
}
return parseInfo.stream.slice(parseInfo.currentPosition.ind - 1 - count, parseInfo.currentPosition.ind - 1);
}
function next(parseInfo, count = 1) {
let char = '';
let chr = '';
if (count < 0) {
return '';
}
while (count-- && (chr = parseInfo.stream.charAt(parseInfo.currentPosition.ind + 1))) {
char += chr;
const codepoint = parseInfo.stream.charCodeAt(++parseInfo.currentPosition.ind);
if (isNaN(codepoint)) {
return char;
}
if (isNewLine(codepoint)) {
parseInfo.currentPosition.lin++;
parseInfo.currentPosition.col = 0;
}
else {
parseInfo.currentPosition.col++;
}
}
return char;
}
/**
* tokenize css string
* @param stream
*/
function* tokenize$1(stream) {
const parseInfo = {
stream,
position: { ind: 0, lin: 1, col: 1 },
currentPosition: { ind: -1, lin: 1, col: 0 }
};
let value;
let buffer = '';
while (value = next(parseInfo)) {
if (isWhiteSpace(value.charCodeAt(0))) {
if (buffer.length > 0) {
yield pushToken(buffer, parseInfo);
buffer = '';
}
while (value = next(parseInfo)) {
if (!isWhiteSpace(value.charCodeAt(0))) {
break;
}
}
yield pushToken('', parseInfo, exports.EnumToken.WhitespaceTokenType);
buffer = '';
}
switch (value) {
case '/':
if (buffer.length > 0) {
yield pushToken(buffer, parseInfo);
buffer = '';
if (peek(parseInfo) != '*') {
yield pushToken(value, parseInfo);
break;
}
}
buffer += value;
if (peek(parseInfo) == '*') {
buffer += next(parseInfo);
while (value = next(parseInfo)) {
if (value == '*') {
buffer += value;
if (peek(parseInfo) == '/') {
yield pushToken(buffer + next(parseInfo), parseInfo, exports.EnumToken.CommentTokenType);
buffer = '';
break;
}
}
else {
buffer += value;
}
}
if (buffer.length > 0) {
yield pushToken(buffer, parseInfo, exports.EnumToken.BadCommentTokenType);
buffer = '';
}
}
break;
case '&':
if (buffer.length > 0) {
yield pushToken(buffer, parseInfo);
buffer = '';
}
yield pushToken(value, parseInfo);
break;
case '<':
if (buffer.length > 0) {
yield pushToken(buffer, parseInfo);
buffer = '';
}
if (peek(parseInfo) == '=') {
yield pushToken('', parseInfo, exports.EnumToken.LteTokenType);
next(parseInfo);
break;
}
buffer += value;
if (peek(parseInfo, 3) == '!--') {
buffer += next(parseInfo, 3);
while (value = next(parseInfo)) {
buffer += value;
if (value == '-' && peek(parseInfo, 2) == '->') {
break;
}
}
if (value === '') {
yield pushToken(buffer, parseInfo, exports.EnumToken.BadCdoTokenType);
}
else {
yield pushToken(buffer + next(parseInfo, 2), parseInfo, exports.EnumToken.CDOCOMMTokenType);
}
buffer = '';
}
break;
case '#':
if (buffer.length > 0) {
yield pushToken(buffer, parseInfo);
buffer = '';
}
buffer += value;
break;
case '\\':
// EOF
if (!(value = next(parseInfo))) {
// end of stream ignore \\
if (buffer.length > 0) {
yield pushToken(buffer, parseInfo);
buffer = '';
}
break;
}
buffer += prev(parseInfo) + value;
break;
case '"':
case "'":
yield* consumeString(value, buffer, parseInfo);
buffer = '';
break;
case '^':
case '~':
case '|':
case '$':
if (buffer.length > 0) {
yield pushToken(buffer, parseInfo);
buffer = '';
}
if (value == '|') {
if (peek(parseInfo) == '|') {
next(parseInfo);
yield pushToken('', parseInfo, exports.EnumToken.ColumnCombinatorTokenType);
}
else if (peek(parseInfo) == '=') {
buffer += next(parseInfo);
yield pushToken(buffer, parseInfo);
}
else {
yield pushToken('|', parseInfo);
}
buffer = '';
break;
}
if (buffer.length > 0) {
yield pushToken(buffer, parseInfo);
buffer = '';
}
buffer += value;
if (!(value = peek(parseInfo))) {
yield pushToken(buffer, parseInfo);
buffer = '';
break;
}
// ~=
// ^=
// $=
// |=
if (peek(parseInfo) == '=') {
next(parseInfo);
switch (buffer.charAt(0)) {
case '~':
yield pushToken(buffer, parseInfo, exports.EnumToken.IncludeMatchTokenType);
break;
case '^':
yield pushToken(buffer, parseInfo, exports.EnumToken.StartMatchTokenType);
break;
case '$':
yield pushToken(buffer, parseInfo, exports.EnumToken.EndMatchTokenType);
break;
case '|':
yield pushToken(buffer, parseInfo, exports.EnumToken.DashMatchTokenType);
break;
}
buffer = '';
break;
}
yield pushToken(buffer, parseInfo);
buffer = '';
break;
case '>':
if (buffer !== '') {
yield pushToken(buffer, parseInfo);
buffer = '';
}
if (peek(parseInfo) == '=') {
yield pushToken('', parseInfo, exports.EnumToken.GteTokenType);
next(parseInfo);
}
else {
yield pushToken('', parseInfo, exports.EnumToken.GtTokenType);
}
consumeWhiteSpace(parseInfo);
break;
case '.':
const codepoint = peek(parseInfo).charCodeAt(0);
if (!isDigit(codepoint) && buffer !== '') {
yield pushToken(buffer, parseInfo);
buffer = value;
break;
}
buffer += value;
break;
case '+':
case '*':
case ':':
case ',':
case '=':
if (buffer.length > 0 && buffer != ':') {
yield pushToken(buffer, parseInfo);
buffer = '';
}
const val = peek(parseInfo);
if (val == '=') {
next(parseInfo);
yield pushToken(value + val, parseInfo, exports.EnumToken.ContainMatchTokenType);
break;
}
if (value == ':') {
if (isWhiteSpace(val.codePointAt(0))) {
yield pushToken(value, parseInfo, exports.EnumToken.ColonTokenType);
buffer = '';
break;
}
buffer += value;
break;
}
yield pushToken(value, parseInfo);
buffer = '';
if (['+', '*', '/'].includes(value) && isWhiteSpace(peek(parseInfo).charCodeAt(0))) {
yield pushToken(next(parseInfo), parseInfo);
}
while (isWhiteSpace(peek(parseInfo).charCodeAt(0))) {
next(parseInfo);
}
break;
case ')':
if (buffer.length > 0) {
yield pushToken(buffer, parseInfo);
buffer = '';
}
yield pushToken('', parseInfo, exports.EnumToken.EndParensTokenType);
break;
case '(':
if (buffer.length == 0) {
yield pushToken(value, parseInfo);
break;
}
buffer += value;
// @ts-ignore
if (buffer == 'url(') {
yield pushToken(buffer, parseInfo);
buffer = '';
consumeWhiteSpace(parseInfo);
value = peek(parseInfo);
let cp;
let whitespace = '';
let hasWhiteSpace = false;
let errorState = false;
if (value == '"' || value == "'") {
const quote = value;
let inquote = true;
let hasNewLine = false;
buffer = next(parseInfo);
while (value = next(parseInfo)) {
cp = value.charCodeAt(0);
// consume an invalid string
if (inquote) {
buffer += value;
if (isNewLine(cp)) {
hasNewLine = true;
while (value = next(parseInfo)) {
buffer += value;
if (value == ';') {
inquote = false;
break;
}
}
if (value === '') {
yield pushToken(buffer, parseInfo, exports.EnumToken.BadUrlTokenType);
buffer = '';
break;
}
cp = value.charCodeAt(0);
}
// '\\'
if (cp == 0x5c) {
buffer += next(parseInfo);
}
else if (value == quote) {
inquote = false;
}
continue;
}
if (!inquote) {
if (isWhiteSpace(cp)) {
whitespace += value;
while (value = peek(parseInfo)) {
hasWhiteSpace = true;
if (isWhiteSpace(value?.charCodeAt(0))) {
whitespace += next(parseInfo);
continue;
}
break;
}
if (!(value = next(parseInfo))) {
yield pushToken(buffer, parseInfo, hasNewLine ? exports.EnumToken.BadUrlTokenType : exports.EnumToken.UrlTokenTokenType);
buffer = '';
break;
}
}
cp = value.charCodeAt(0);
// ')'
if (cp == 0x29) {
yield pushToken(buffer, parseInfo, hasNewLine ? exports.EnumToken.BadStringTokenType : exports.EnumToken.StringTokenType);
yield pushToken('', parseInfo, exports.EnumToken.EndParensTokenType);
buffer = '';
break;
}
while (value = next(parseInfo)) {
cp = value.charCodeAt(0);
if (cp == 0x5c) {
buffer += value + next(parseInfo);
continue;
}
if (cp == 0x29) {
yield pushToken(buffer, parseInfo, exports.EnumToken.BadStringTokenType);
yield pushToken('', parseInfo, exports.EnumToken.EndParensTokenType);
buffer = '';
break;
}
buffer += value;
}
if (hasNewLine) {
yield pushToken(buffer, parseInfo, exports.EnumToken.BadStringTokenType);
buffer = '';
}
break;
}
buffer += value;
}
break;
}
else {
buffer = '';
while (value = next(parseInfo)) {
cp = value.charCodeAt(0);
// ')'
if (cp == 0x29) {
yield pushToken(buffer, parseInfo, exports.EnumToken.UrlTokenTokenType);
yield pushToken('', parseInfo, exports.EnumToken.EndParensTokenType);
buffer = '';
break;
}
if (isWhiteSpace(cp)) {
hasWhiteSpace = true;
whitespace = value;
while (isWhiteSpace(peek(parseInfo)?.charCodeAt(0))) {
whitespace += next(parseInfo);
}
continue;
}
if (isNonPrintable(cp) ||
// '"'
cp == 0x22 ||
// "'"
cp == 0x27 ||
// \('
cp == 0x28 ||
hasWhiteSpace) {
errorState = true;
}
if (errorState) {
buffer += whitespace + value;
while (value = peek(parseInfo)) {
cp = value.charCodeAt(0);
if (cp == 0x5c) {
buffer += next(parseInfo, 2);
continue;
}
// ')'
if (cp == 0x29) {
break;
}
buffer += next(parseInfo);
}
yield pushToken(buffer, parseInfo, exports.EnumToken.BadUrlTokenType);
buffer = '';
break;
}
buffer += value;
}
}
if (buffer !== '') {
yield pushToken(buffer, parseInfo, exports.EnumToken.UrlTokenTokenType);
buffer = '';
break;
}
break;
}
yield pushToken(buffer, parseInfo);
buffer = '';
break;
case '[':
case ']':
case '{':
case '}':
case ';':
if (buffer.length > 0) {
yield pushToken(buffer, parseInfo);
buffer = '';
}
yield pushToken(value, parseInfo);
break;
case '!':
if (buffer.length > 0) {
yield pushToken(buffer, parseInfo);
buffer = '';
}
if (peek(parseInfo, 9) == 'important') {
yield pushToken('', parseInfo, exports.EnumToken.ImportantTokenType);
next(parseInfo, 9);
buffer = '';
break;
}
buffer = '!';
break;
default:
buffer += value;
break;
}
}
if (buffer.length > 0) {
yield pushToken(buffer, parseInfo);
}
// yield pushToken('', EnumToken.EOFTokenType);
}
var declarations = {
"-ms-accelerator": {
syntax: "false | true"
},
"-ms-block-progression": {
syntax: "tb | rl | bt | lr"
},
"-ms-content-zoom-chaining": {
syntax: "none | chained"
},
"-ms-content-zoom-limit": {
syntax: "<'-ms-content-zoom-limit-min'> <'-ms-content-zoom-limit-max'>"
},
"-ms-content-zoom-limit-max": {
syntax: "<percentage>"
},
"-ms-content-zoom-limit-min": {
syntax: "<percentage>"
},
"-ms-content-zoom-snap": {
syntax: "<'-ms-content-zoom-snap-type'> || <'-ms-content-zoom-snap-points'>"
},
"-ms-content-zoom-snap-points": {
syntax: "snapInterval( <percentage>, <percentage> ) | snapList( <percentage># )"
},
"-ms-content-zoom-snap-type": {
syntax: "none | proximity | mandatory"
},
"-ms-content-zooming": {
syntax: "none | zoom"
},
"-ms-filter": {
syntax: "<string>"
},
"-ms-flow-from": {
syntax: "[ none | <custom-ident> ]#"
},
"-ms-flow-into": {
syntax: "[ none | <custom-ident> ]#"
},
"-ms-grid-columns": {
syntax: "none | <track-list> | <auto-track-list>"
},
"-ms-grid-rows": {
syntax: "none | <track-list> | <auto-track-list>"
},
"-ms-high-contrast-adjust": {
syntax: "auto | none"
},
"-ms-hyphenate-limit-chars": {
syntax: "auto | <integer>{1,3}"
},
"-ms-hyphenate-limit-lines": {
syntax: "no-limit | <integer>"
},
"-ms-hyphenate-limit-zone": {
syntax: "<percentage> | <length>"
},
"-ms-ime-align": {
syntax: "auto | after"
},
"-ms-overflow-style": {
syntax: "auto | none | scrollbar | -ms-autohiding-scrollbar"
},
"-ms-scroll-chaining": {
syntax: "chained | none"
},
"-ms-scroll-limit": {
syntax: "<'-ms-scroll-limit-x-min'> <'-ms-scroll-limit-y-min'> <'-ms-scroll-limit-x-max'> <'-ms-scroll-limit-y-max'>"
},
"-ms-scroll-limit-x-max": {
syntax: "auto | <length>"
},
"-ms-scroll-limit-x-min": {
syntax: "<length>"
},
"-ms-scroll-limit-y-max": {
syntax: "auto | <length>"
},
"-ms-scroll-limit-y-min": {
syntax: "<length>"
},
"-ms-scroll-rails": {
syntax: "none | railed"
},
"-ms-scroll-snap-points-x": {
syntax: "snapInterval( <length-percentage>, <length-percentage> ) | snapList( <length-percentage># )"
},
"-ms-scroll-snap-points-y": {
syntax: "snapInterval( <length-percentage>, <length-percentage> ) | snapList( <length-percentage># )"
},
"-ms-scroll-snap-type": {
syntax: "none | proximity | mandatory"
},
"-ms-scroll-snap-x": {
syntax: "<'-ms-scroll-snap-type'> <'-ms-scroll-snap-points-x'>"
},
"-ms-scroll-snap-y": {
syntax: "<'-ms-scroll-snap-type'> <'-ms-scroll-snap-points-y'>"
},
"-ms-scroll-translation": {
syntax: "none | vertical-to-horizontal"
},
"-ms-scrollbar-3dlight-color": {
syntax: "<color>"
},
"-ms-scrollbar-arrow-color": {
syntax: "<color>"
},
"-ms-scrollbar-base-color": {
syntax: "<color>"
},
"-ms-scrollbar-darkshadow-color": {
syntax: "<color>"
},
"-ms-scrollbar-face-color": {
syntax: "<color>"
},
"-ms-scrollbar-highlight-color": {
syntax: "<color>"
},
"-ms-scrollbar-shadow-color": {
syntax: "<color>"
},
"-ms-scrollbar-track-color": {
syntax: "<color>"
},
"-ms-text-autospace": {
syntax: "none | ideograph-alpha | ideograph-numeric | ideograph-parenthesis | ideograph-space"
},
"-ms-touch-select": {
syntax: "grippers | none"
},
"-ms-user-select": {
syntax: "none | element | text"
},
"-ms-wrap-flow": {
syntax: "auto | both | start | end | maximum | clear"
},
"-ms-wrap-margin": {
syntax: "<length>"
},
"-ms-wrap-through": {
syntax: "wrap | none"
},
"-moz-appearance": {
syntax: "none | button | button-arrow-down | button-arrow-next | button-arrow-previous | button-arrow-up | button-bevel | button-focus | caret | checkbox | checkbox-container | checkbox-label | checkmenuitem | dualbutton | groupbox | listbox | listitem | menuarrow | menubar | menucheckbox | menuimage | menuitem | menuitemtext | menulist | menulist-button | menulist-text | menulist-textfield | menupopup | menuradio | menuseparator | meterbar | meterchunk | progressbar | progressbar-vertical | progresschunk | progresschunk-vertical | radio | radio-container | radio-label | radiomenuitem | range | range-thumb | resizer | resizerpanel | scale-horizontal | scalethumbend | scalethumb-horizontal | scalethumbstart | scalethumbtick | scalethumb-vertical | scale-vertical | scrollbarbutton-down | scrollbarbutton-left | scrollbarbutton-right | scrollbarbutton-up | scrollbarthumb-horizontal | scrollbarthumb-vertical | scrollbartrack-horizontal | scrollbartrack-vertical | searchfield | separator | sheet | spinner | spinner-downbutton | spinner-textfield | spinner-upbutton | splitter | statusbar | statusbarpanel | tab | tabpanel | tabpanels | tab-scroll-arrow-back | tab-scroll-arrow-forward | textfield | textfield-multiline | toolbar | toolbarbutton | toolbarbutton-dropdown | toolbargripper | toolbox | tooltip | treeheader | treeheadercell | treeheadersortarrow | treeitem | treeline | treetwisty | treetwistyopen | treeview | -moz-mac-unified-toolbar | -moz-win-borderless-glass | -moz-win-browsertabbar-toolbox | -moz-win-communicationstext | -moz-win-communications-toolbox | -moz-win-exclude-glass | -moz-win-glass | -moz-win-mediatext | -moz-win-media-toolbox | -moz-window-button-box | -moz-window-button-box-maximized | -moz-window-button-close | -moz-window-button-maximize | -moz-window-button-minimize | -moz-window-button-restore | -moz-window-frame-bottom | -moz-window-frame-left | -moz-window-frame-right | -moz-window-titlebar | -moz-window-titlebar-maximized"
},
"-moz-binding": {
syntax: "<url> | none"
},
"-moz-border-bottom-colors": {
syntax: "<color>+ | none"
},
"-moz-border-left-colors": {
syntax: "<color>+ | none"
},
"-moz-border-right-colors": {
syntax: "<color>+ | none"
},
"-moz-border-top-colors": {
syntax: "<color>+ | none"
},
"-moz-context-properties": {
syntax: "none | [ fill | fill-opacity | stroke | stroke-opacity ]#"
},
"-moz-float-edge": {
syntax: "border-box | content-box | margin-box | padding-box"
},
"-moz-force-broken-image-icon": {
syntax: "0 | 1"
},
"-moz-image-region": {
syntax: "<shape> | auto"
},
"-moz-orient": {
syntax: "inline | block | horizontal | vertical"
},
"-moz-outline-radius": {
syntax: "<outline-radius>{1,4} [ / <outline-radius>{1,4} ]?"
},
"-moz-outline-radius-bottomleft": {
syntax: "<outline-radius>"
},
"-moz-outline-radius-bottomright": {
syntax: "<outline-radius>"
},
"-moz-outline-radius-topleft": {
syntax: "<outline-radius>"
},
"-moz-outline-radius-topright": {
syntax: "<outline-radius>"
},
"-moz-stack-sizing": {
syntax: "ignore | stretch-to-fit"
},
"-moz-text-blink": {
syntax: "none | blink"
},
"-moz-user-focus": {
syntax: "ignore | normal | select-after | select-before | select-menu | select-same | select-all | none"
},
"-moz-user-input": {
syntax: "auto | none | enabled | disabled"
},
"-moz-user-modify": {
syntax: "read-only | read-write | write-only"
},
"-moz-window-dragging": {
syntax: "drag | no-drag"
},
"-moz-window-shadow": {
syntax: "default | menu | tooltip | sheet | none"
},
"-webkit-appearance": {
syntax: "none | button | button-bevel | caret | checkbox | default-button | inner-spin-button | listbox | listitem | media-controls-background | media-controls-fullscreen-background | media-current-time-display | media-enter-fullscreen-button | media-exit-fullscreen-button | media-fullscreen-button | media-mute-button | media-overlay-play-button | media-play-button | media-seek-back-button | media-seek-forward-button | media-slider | media-sliderthumb | media-time-remaining-display | media-toggle-closed-captions-button | media-volume-slider | media-volume-slider-container | media-volume-sliderthumb | menulist | menulist-button | menulist-text | menulist-textfield | meter | progress-bar | progress-bar-value | push-button | radio | searchfield | searchfield-cancel-button | searchfield-decoration | searchfield-results-button | searchfield-results-decoration | slider-horizontal | slider-vertical | sliderthumb-horizontal | sliderthumb-vertical | square-button | textarea | textfield | -apple-pay-button"
},
"-webkit-border-before": {
syntax: "<'border-width'> || <'border-style'> || <color>"
},
"-webkit-border-before-color": {
syntax: "<color>"
},
"-webkit-border-before-style": {
syntax: "<'border-style'>"
},
"-webkit-border-before-width": {
syntax: "<'border-width'>"
},
"-webkit-box-reflect": {
syntax: "[ above | below | right | left ]? <length>? <image>?"
},
"-webkit-line-clamp": {
syntax: "none | <integer>"
},
"-webkit-mask": {
syntax: "[ <mask-reference> || <position> [ / <bg-size> ]? || <repeat-style> || [ <visual-box> | border | padding | content | text ] || [ <visual-box> | border | padding | content ] ]#"
},
"-webkit-mask-attachment": {
syntax: "<attachment>#"
},
"-webkit-mask-clip": {
syntax: "[ <coord-box> | no-clip | border | padding | content | text ]#"
},
"-webkit-mask-composite": {
syntax: "<composite-style>#"
},
"-webkit-mask-image": {
syntax: "<mask-reference>#"
},
"-webkit-mask-origin": {
syntax: "[ <coord-box> | border | padding | content ]#"
},
"-webkit-mask-position": {
syntax: "<position>#"
},
"-webkit-mask-position-x": {
syntax: "[ <length-percentage> | left | center | right ]#"
},
"-webkit-mask-position-y": {
syntax: "[ <length-percentage> | top | center | bottom ]#"
},
"-webkit-mask-repeat": {
syntax: "<repeat-style>#"
},
"-webkit-mask-repeat-x": {
syntax: "repeat | no-repeat | space | round"
},
"-webkit-mask-repeat-y": {
syntax: "repeat | no-repeat | space | round"
},
"-webkit-mask-size": {
syntax: "<bg-size>#"
},
"-webkit-overflow-scrolling": {
syntax: "auto | touch"
},
"-webkit-tap-highlight-color": {
syntax: "<color>"
},
"-webkit-text-fill-color": {
syntax: "<color>"
},
"-webkit-text-stroke": {
syntax: "<length> || <color>"
},
"-webkit-text-stroke-color": {
syntax: "<color>"
},
"-webkit-text-stroke-width": {
syntax: "<length>"
},
"-webkit-touch-callout": {
syntax: "default | none"
},
"-webkit-user-modify": {
syntax: "read-only | read-write | read-write-plaintext-only"
},
"-webkit-user-select": {
syntax: "auto | text | none | all"
},
"accent-color": {
syntax: "auto | <color>"
},
"align-content": {
syntax: "normal | <baseline-position> | <content-distribution> | <overflow-position>? <content-position>"
},
"align-items": {
syntax: "normal | stretch | <baseline-position> | [ <overflow-position>? <self-position> ]"
},
"align-self": {
syntax: "auto | normal | stretch | <baseline-position> | <overflow-position>? <self-position>"
},
"align-tracks": {
syntax: "[ normal | <baseline-position> | <content-distribution> | <overflow-position>? <content-position> ]#"
},
all: {
syntax: "initial | inherit | unset | revert | revert-layer"
},
"anchor-name": {
syntax: "none | <dashed-ident>#"
},
"anchor-scope": {
syntax: "none | all | <dashed-ident>#"
},
animation: {
syntax: "<single-animation>#"
},
"animation-composition": {
syntax: "<single-animation-composition>#"
},
"animation-delay": {
syntax: "<time>#"
},
"animation-direction": {
syntax: "<single-animation-direction>#"
},
"animation-duration": {
syntax: "<time>#"
},
"animation-fill-mode": {
syntax: "<single-animation-fill-mode>#"
},
"animation-iteration-count": {
syntax: "<single-animation-iteration-count>#"
},
"animation-name": {
syntax: "[ none | <keyframes-name> ]#"
},
"animation-play-state": {
syntax: "<single-animation-play-state>#"
},
"animation-range": {
syntax: "[ <'animation-range-start'> <'animation-range-end'>? ]#"
},
"animation-range-end": {
syntax: "[ normal | <length-percentage> | <timeline-range-name> <length-percentage>? ]#"
},
"animation-range-start": {
syntax: "[ normal | <length-percentage> | <timeline-range-name> <length-percentage>? ]#"
},
"animation-timeline": {
syntax: "<single-animation-timeline>#"
},
"animation-timing-function": {
syntax: "<easing-function>#"
},
appearance: {
syntax: "none | auto | textfield | menulist-button | <compat-auto>"
},
"aspect-ratio": {
syntax: "auto || <ratio>"
},
"backdrop-filter": {
syntax: "none | <filter-value-list>"
},
"backface-visibility": {
syntax: "visible | hidden"
},
background: {
syntax: "[ <bg-layer> , ]* <final-bg-layer>"
},
"background-attachment": {
syntax: "<attachment>#"
},
"background-blend-mode": {
syntax: "<blend-mode>#"
},
"background-clip": {
syntax: "<bg-clip>#"
},
"background-color": {
syntax: "<color>"
},
"background-image": {
syntax: "<bg-image>#"
},
"background-origin": {
syntax: "<visual-box>#"
},
"background-position": {
syntax: "<bg-position>#"
},
"background-position-x": {
syntax: "[ center | [ [ left | right | x-start | x-end ]? <length-percentage>? ]! ]#"
},
"background-position-y": {
syntax: "[ center | [ [ top | bottom | y-start | y-end ]? <length-percentage>? ]! ]#"
},
"background-repeat": {
syntax: "<repeat-style>#"
},
"background-size": {
syntax: "<bg-size>#"
},
"block-size": {
syntax: "<'width'>"
},
border: {
syntax: "<line-width> || <line-style> || <color>"
},
"border-block": {
syntax: "<'border-block-start'>"
},
"border-block-color": {
syntax: "<'border-top-color'>{1,2}"
},
"border-block-end": {
syntax: "<'border-top-width'> || <'border-top-style'> || <color>"
},
"border-block-end-color": {
syntax: "<'border-top-color'>"
},
"border-block-end-style": {
syntax: "<'border-top-style'>"
},
"border-block-end-width": {
syntax: "<'border-top-width'>"
},
"border-block-start": {
syntax: "<'border-top-width'> || <'border-top-style'> || <color>"
},
"border-block-start-color": {
syntax: "<'border-top-color'>"
},
"border-block-start-style": {
syntax: "<'border-top-style'>"
},
"border-block-start-width": {
syntax: "<'border-top-width'>"
},
"border-block-style": {
syntax: "<'border-top-style'>{1,2}"
},
"border-block-width": {
syntax: "<'border-top-width'>{1,2}"
},
"border-bottom": {
syntax: "<line-width> || <line-style> || <color>"
},
"border-bottom-color": {
syntax: "<'border-top-color'>"
},
"border-bottom-left-radius": {
syntax: "<length-percentage>{1,2}"
},
"border-bottom-right-radius": {
syntax: "<length-percentage>{1,2}"
},
"border-bottom-style": {
syntax: "<line-style>"
},
"border-bottom-width": {
syntax: "<line-width>"
},
"border-collapse": {
syntax: "collapse | separate"
},
"border-color": {
syntax: "<color>{1,4}"
},
"border-end-end-radius": {
syntax: "<'border-top-left-radius'>"
},
"border-end-start-radius": {
syntax: "<'border-top-left-radius'>"
},
"border-image": {
syntax: "<'border-image-source'> || <'border-image-slice'> [ / <'border-image-width'> | / <'border-image-width'>? / <'border-image-outset'> ]? || <'border-image-repeat'>"
},
"border-image-outset": {
syntax: "[ <length> | <number> ]{1,4}"
},
"border-image-repeat": {
syntax: "[ stretch | repeat | round | space ]{1,2}"
},
"border-image-slice": {
syntax: "<number-percentage>{1,4} && fill?"
},
"border-image-source": {
syntax: "none | <image>"
},
"border-image-width": {
syntax: "[ <length-percentage> | <number> | auto ]{1,4}"
},
"border-inline": {
syntax: "<'border-block-start'>"
},
"border-inline-color": {
syntax: "<'border-top-color'>{1,2}"
},
"border-inline-end": {
syntax: "<'border-top-width'> || <'border-top-style'> || <color>"
},
"border-inline-end-color": {
syntax: "<'border-top-color'>"
},
"border-inline-end-style": {
syntax: "<'border-top-style'>"
},
"border-inline-end-width": {
syntax: "<'border-top-width'>"
},
"border-inline-start": {
syntax: "<'border-top-width'> || <'border-top-style'> || <color>"
},
"border-inline-start-color": {
syntax: "<'border-top-color'>"
},
"border-inline-start-style": {
syntax: "<'border-top-style'>"
},
"border-inline-start-width": {
syntax: "<'border-top-width'>"
},
"border-inline-style": {
syntax: "<'border-top-style'>{1,2}"
},
"border-inline-width": {
syntax: "<'border-top-width'>{1,2}"
},
"border-left": {
syntax: "<line-width> || <line-style> || <color>"
},
"border-left-color": {
syntax: "<color>"
},
"border-left-style": {
syntax: "<line-style>"
},
"border-left-width": {
syntax: "<line-width>"
},
"border-radius": {
syntax: "<length-percentage>{1,4} [ / <length-percentage>{1,4} ]?"
},
"border-right": {
syntax: "<line-width> || <line-style> || <color>"
},
"border-right-color": {
syntax: "<color>"
},
"border-right-style": {
syntax: "<line-style>"
},
"border-right-width": {
syntax: "<line-width>"
},
"border-spacing": {
syntax: "<length> <length>?"
},
"border-start-end-radius": {
syntax: "<'border-top-left-radius'>"
},
"border-start-start-radius": {
syntax: "<'border-top-left-radius'>"
},
"border-style": {
syntax: "<line-style>{1,4}"
},
"border-top": {
syntax: "<line-width> || <line-style> || <color>"
},
"border-top-color": {
syntax: "<color>"
},
"border-top-left-radius": {
syntax: "<length-percentage>{1,2}"
},
"border-top-right-radius": {
syntax: "<length-percentage>{1,2}"
},
"border-top-style": {
syntax: "<line-style>"
},
"border-top-width": {
syntax: "<line-width>"
},
"border-width": {
syntax: "<line-width>{1,4}"
},
bottom: {
syntax: "<length> | <percentage> | auto"
},
"box-align": {
syntax: "start | center | end | baseline | stretch"
},
"box-decoration-break": {
syntax: "slice | clone"
},
"box-direction": {
syntax: "normal | reverse | inherit"
},
"box-flex": {
syntax: "<number>"
},
"box-flex-group": {
syntax: "<integer>"
},
"box-lines": {
syntax: "single | multiple"
},
"box-ordinal-group": {
syntax: "<integer>"
},
"box-orient": {
syntax: "horizontal | vertical | inline-axis | block-axis | inherit"
},
"box-pack": {
syntax: "start | center | end | justify"
},
"box-shadow": {
syntax: "none | <shadow>#"
},
"box-sizing": {
syntax: "content-box | border-box"
},
"break-after": {
syntax: "auto | avoid | always | all | avoid-page | page | left | right | recto | verso | avoid-column | column | avoid-region | region"
},
"break-before": {
syntax: "auto | avoid | always | all | avoid-page | page | left | right | recto | verso | avoid-column | column | avoid-region | region"
},
"break-inside": {
syntax: "auto | avoid | avoid-page | avoid-column | avoid-region"
},
"caption-side": {
syntax: "top | bottom"
},
caret: {
syntax: "<'caret-color'> || <'caret-shape'>"
},
"caret-color": {
syntax: "auto | <color>"
},
"caret-shape": {
syntax: "auto | bar | block | underscore"
},
clear: {
syntax: "none | left | right | both | inline-start | inline-end"
},
clip: {
syntax: "<shape> | auto"
},
"clip-path": {
syntax: "<clip-source> | [ <basic-shape> || <geometry-box> ] | none"
},
"clip-rule": {
syntax: "nonzero | evenodd"
},
color: {
syntax: "<color>"
},
"color-interpolation-filters": {
syntax: "auto | sRGB | linearRGB"
},
"color-scheme": {
syntax: "normal | [ light | dark | <custom-ident> ]+ && only?"
},
"column-count": {
syntax: "<integer> | auto"
},
"column-fill": {
syntax: "auto | balance"
},
"column-gap": {
syntax: "normal | <length-percentage>"
},
"column-rule": {
syntax: "<'column-rule-width'> || <'column-rule-style'> || <'column-rule-color'>"
},
"column-rule-color": {
syntax: "<color>"
},
"column-rule-style": {
syntax: "<'border-style'>"
},
"column-rule-width": {
syntax: "<'border-width'>"
},
"column-span": {
syntax: "none | all"
},
"column-width": {
syntax: "<length> | auto"
},
columns: {
syntax: "<'column-width'> || <'column-count'>"
},
contain: {
syntax: "none | strict | content | [ [ size || inline-size ] || layout || style || paint ]"
},
"contain-intrinsic-block-size": {
syntax: "auto? [ none | <length> ]"
},
"contain-intrinsic-height": {
syntax: "auto? [ none | <length> ]"
},
"contain-intrinsic-inline-size": {
syntax: "auto? [ none | <length> ]"
},
"contain-intrinsic-size": {
syntax: "[ auto? [ none | <length> ] ]{1,2}"
},
"contain-intrinsic-width": {
syntax: "auto? [ none | <length> ]"
},
container: {
syntax: "<'container-name'> [ / <'container-type'> ]?"
},
"container-name": {
syntax: "none | <custom-ident>+"
},
"container-type": {
syntax: "normal | size | inline-size"
},
content: {
syntax: "normal | none | [ <content-replacement> | <content-list> ] [/ [ <string> | <counter> ]+ ]?"
},
"content-visibility": {
syntax: "visible | auto | hidden"
},
"counter-increment": {
syntax: "[ <counter-name> <integer>? ]+ | none"
},
"counter-reset": {
syntax: "[ <counter-name> <integer>? | <reversed-counter-name> <integer>? ]+ | none"
},
"counter-set": {
syntax: "[ <counter-name> <integer>? ]+ | none"
},
cursor: {
syntax: "[ [ <url> [ <x> <y> ]? , ]* [ auto | default | none | context-menu | help | pointer | progress | wait | cell | crosshair | text | vertical-text | alias | copy | move | no-drop | not-allowed | e-resize | n-resize | ne-resize | nw-resize | s-resize | se-resize | sw-resize | w-resize | ew-resize | ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | all-scroll | zoom-in | zoom-out | grab | grabbing ] ]"
},
cx: {
syntax: "<length> | <percentage>"
},
cy: {
syntax: "<length> | <percentage>"
},
d: {
syntax: "none | path(<string>)"
},
direction: {
syntax: "ltr | rtl"
},
display: {
syntax: "[ <display-outside> || <display-inside> ] | <display-listitem> | <display-internal> | <display-box> | <display-legacy>"
},
"dominant-baseline": {
syntax: "auto | text-bottom | alphabetic | ideographic | middle | central | mathematical | hanging | text-top"
},
"empty-cells": {
syntax: "show | hide"
},
"field-sizing": {
syntax: "content | fixed"
},
fill: {
syntax: "<paint>"
},
"fill-opacity": {
syntax: "<'opacity'>"
},
"fill-rule": {
syntax: "nonzero | evenodd"
},
filter: {
syntax: "none | <filter-value-list>"
},
flex: {
syntax: "none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]"
},
"flex-basis": {
syntax: "content | <'width'>"
},
"flex-direction": {
syntax: "row | row-reverse | column | column-reverse"
},
"flex-flow": {
syntax: "<'flex-direction'> || <'flex-wrap'>"
},
"flex-grow": {
syntax: "<number>"
},
"flex-shrink": {
syntax: "<number>"
},
"flex-wrap": {
syntax: "nowrap | wrap | wrap-reverse"
},
float: {
syntax: "left | right | none | inline-start | inline-end"
},
"flood-color": {
syntax: "<color>"
},
"flood-opacity": {
syntax: "<'opacity'>"
},
font: {
syntax: "[ [ <'font-style'> || <font-variant-css21> || <'font-weight'> || <'font-stretch'> ]? <'font-size'> [ / <'line-height'> ]? <'font-family'> ] | caption | icon | menu | message-box | small-caption | status-bar"
},
"font-family": {
syntax: "[ <family-name> | <generic-family> ]#"
},
"font-feature-settings": {
syntax: "normal | <feature-tag-value>#"
},
"font-kerning": {
syntax: "auto | normal | none"
},
"font-language-override": {
syntax: "normal | <string>"
},
"font-optical-sizing": {
syntax: "auto | none"
},
"font-palette": {
syntax: "normal | light | dark | <palette-identifier> | <palette-mix()>"
},
"font-size": {
syntax: "<absolute-size> | <relative-size> | <length-percentage>"
},
"font-size-adjust": {
syntax: "none | [ ex-height | cap-height | ch-width | ic-width | ic-height ]? [ from-font | <number> ]"
},
"font-smooth": {
syntax: "auto | never | always | <absolute-size> | <length>"
},
"font-stretch": {
syntax: "<font-stretch-absolute>"
},
"font-style": {
syntax: "normal | italic | oblique <angle>?"
},
"font-synthesis": {
syntax: "none | [ weight || style || small-caps || position]"
},
"font-synthesis-position": {
syntax: "auto | none"
},
"font-synthesis-small-caps": {
syntax: "auto | none"
},
"font-synthesis-style": {
syntax: "auto | none"
},
"font-synthesis-weight": {
syntax: "auto | none"
},
"font-variant": {
syntax: "normal | none | [ <common-lig-values> || <discretionary-lig-values> || <historical-lig-values> || <contextual-alt-values> || stylistic( <feature-value-name> ) || historical-forms || styleset( <feature-value-name># ) || character-variant( <feature-value-name># ) || swash( <feature-value-name> ) || ornaments( <feature-value-name> ) || annotation( <feature-value-name> ) || [ small-caps | all-small-caps | petite-caps | all-petite-caps | unicase | titling-caps ] || <numeric-figure-values> || <numeric-spacing-values> || <numeric-fraction-values> || ordinal || slashed-zero || <east-asian-variant-values> || <east-asian-width-values> || ruby ]"
},
"font-variant-alternates": {
syntax: "normal | [ stylistic( <feature-value-name> ) || historical-forms || styleset( <feature-value-name># ) || character-variant( <feature-value-name># ) || swash( <feature-value-name> ) || ornaments( <feature-value-name> ) || annotation( <feature-value-name> ) ]"
},
"font-variant-caps": {
syntax: "normal | small-caps | all-small-caps | petite-caps | all-petite-caps | unicase | titling-caps"
},
"font-variant-east-asian": {
syntax: "normal | [ <east-asian-variant-values> || <east-asian-width-values> || ruby ]"
},
"font-variant-emoji": {
syntax: "normal | text | emoji | unicode"
},
"font-variant-ligatures": {
syntax: "normal | none | [ <common-lig-values> || <discretionary-lig-values> || <historical-lig-values> || <contextual-alt-values> ]"
},
"font-variant-numeric": {
syntax: "normal | [ <numeric-figure-values> || <numeric-spacing-values> || <numeric-fraction-values> || ordinal || slashed-zero ]"
},
"font-variant-position": {
syntax: "normal | sub | super"
},
"font-variation-settings": {
syntax: "normal | [ <string> <number> ]#"
},
"font-weight": {
syntax: "<font-weight-absolute> | bolder | lighter"
},
"forced-color-adjust": {
syntax: "auto | none | preserve-parent-color"
},
gap: {
syntax: "<'row-gap'> <'column-gap'>?"
},
grid: {
syntax: "<'grid-template'> | <'grid-template-rows'> / [ auto-flow && dense? ] <'grid-auto-columns'>? | [ auto-flow && dense? ] <'grid-auto-rows'>? / <'grid-template-columns'>"
},
"grid-area": {
syntax: "<grid-line> [ / <grid-line> ]{0,3}"
},
"grid-auto-columns": {
syntax: "<track-size>+"
},
"grid-auto-flow": {
syntax: "[ row | column ] || dense"
},
"grid-auto-rows": {
syntax: "<track-size>+"
},
"grid-column": {
syntax: "<grid-line> [ / <grid-line> ]?"
},
"grid-column-end": {
syntax: "<grid-line>"
},
"grid-column-gap": {
syntax: "<length-percentage>"
},
"grid-column-start": {
syntax: "<grid-line>"
},
"grid-gap": {
syntax: "<'grid-row-gap'> <'grid-column-gap'>?"
},
"grid-row": {
syntax: "<grid-line> [ / <grid-line> ]?"
},
"grid-row-end": {
syntax: "<grid-line>"
},
"grid-row-gap": {
syntax: "<length-percentage>"
},
"grid-row-start": {
syntax: "<grid-line>"
},
"grid-template": {
syntax: "none | [ <'grid-template-rows'> / <'grid-template-columns'> ] | [ <line-names>? <string> <track-size>? <line-names>? ]+ [ / <explicit-track-list> ]?"
},
"grid-template-areas": {
syntax: "none | <string>+"
},
"grid-template-columns": {
syntax: "none | <track-list> | <auto-track-list> | subgrid <line-name-list>?"
},
"grid-template-rows": {
syntax: "none | <track-list> | <auto-track-list> | subgrid <line-name-list>?"
},
"hanging-punctuation": {
syntax: "none | [ first || [ force-end | allow-end ] || last ]"
},
height: {
syntax: "auto | <length-percentage [0,∞]> | min-content | max-content | fit-content | fit-content(<length-percentage [0,∞]>) | <calc-size()> | <anchor-size()>"
},
"hyphenate-character": {
syntax: "auto | <string>"
},
"hyphenate-limit-chars": {
syntax: "[ auto | <integer> ]{1,3}"
},
hyphens: {
syntax: "none | manual | auto"
},
"image-orientation": {
syntax: "from-image | <angle> | [ <angle>? flip ]"
},
"image-rendering": {
syntax: "auto | crisp-edges | pixelated | smooth"
},
"image-resolution": {
syntax: "[ from-image || <resolution> ] && snap?"
},
"ime-mode": {
syntax: "auto | normal | active | inactive | disabled"
},
"initial-letter": {
syntax: "normal | [ <number> <integer>? ]"
},
"initial-letter-align": {
syntax: "[ auto | alphabetic | hanging | ideographic ]"
},
"inline-size": {
syntax: "<'width'>"
},
inset: {
syntax: "<'top'>{1,4}"
},
"inset-block": {
syntax: "<'top'>{1,2}"
},
"inset-block-end": {
syntax: "<'top'>"
},
"inset-block-start": {
syntax: "<'top'>"
},
"inset-inline": {
syntax: "<'top'>{1,2}"
},
"inset-inline-end": {
syntax: "<'top'>"
},
"inset-inline-start": {
syntax: "<'top'>"
},
"interpolate-size": {
syntax: "numeric-only | allow-keywords"
},
isolation: {
syntax: "auto | isolate"
},
"justify-content": {
syntax: "normal | <content-distribution> | <overflow-position>? [ <content-position> | left | right ]"
},
"justify-items": {
syntax: "normal | stretch | <baseline-position> | <overflow-position>? [ <self-position> | left | right ] | legacy | legacy && [ left | right | center ]"
},
"justify-self": {
syntax: "auto | normal | stretch | <baseline-position> | <overflow-position>? [ <self-position> | left | right ]"
},
"justify-tracks": {
syntax: "[ normal | <content-distribution> | <overflow-position>? [ <content-position> | left | right ] ]#"
},
left: {
syntax: "<length> | <percentage> | auto"
},
"letter-spacing": {
syntax: "normal | <length>"
},
"lighting-color": {
syntax: "<color>"
},
"line-break": {
syntax: "auto | loose | normal | strict | anywhere"
},
"line-clamp": {
syntax: "none | <integer>"
},
"line-height": {
syntax: "normal | <number> | <length> | <percentage>"
},
"line-height-step": {
syntax: "<length>"
},
"list-style": {
syntax: "<'list-style-type'> || <'list-style-position'> || <'list-style-image'>"
},
"list-style-image": {
syntax: "<image> | none"
},
"list-style-position": {
syntax: "inside | outside"
},
"list-style-type": {
syntax: "<counter-style> | <string> | none"
},
margin: {
syntax: "<'margin-top'>{1,4}"
},
"margin-block": {
syntax: "<'margin-top'>{1,2}"
},
"margin-block-end": {
syntax: "<'margin-top'>"
},
"margin-block-start": {
syntax: "<'margin-top'>"
},
"margin-bottom": {
syntax: "<length-percentage> | auto"
},
"margin-inline": {
syntax: "<'margin-top'>{1,2}"
},
"margin-inline-end": {
syntax: "<'margin-top'>"
},
"margin-inline-start": {
syntax: "<'margin-top'>"
},
"margin-left": {
syntax: "<length-percentage> | auto"
},
"margin-right": {
syntax: "<length-percentage> | auto"
},
"margin-top": {
syntax: "<length-percentage> | auto"
},
"margin-trim": {
syntax: "none | in-flow | all"
},
marker: {
syntax: "none | <url>"
},
"marker-end": {
syntax: "none | <url>"
},
"marker-mid": {
syntax: "none | <url>"
},
"marker-start": {
syntax: "none | <url>"
},
mask: {
syntax: "<mask-layer>#"
},
"mask-border": {
syntax: "<'mask-border-source'> || <'mask-border-slice'> [ / <'mask-border-width'>? [ / <'mask-border-outset'> ]? ]? || <'mask-border-repeat'> || <'mask-border-mode'>"
},
"mask-border-mode": {
syntax: "luminance | alpha"
},
"mask-border-outset": {
syntax: "[ <length> | <number> ]{1,4}"
},
"mask-border-repeat": {
syntax: "[ stretch | repeat | round | space ]{1,2}"
},
"mask-border-slice": {
syntax: "<number-percentage>{1,4} fill?"
},
"mask-border-source": {
syntax: "none | <image>"
},
"mask-border-width": {
syntax: "[ <length-percentage> | <number> | auto ]{1,4}"
},
"mask-clip": {
syntax: "[ <coord-box> | no-clip ]#"
},
"mask-composite": {
syntax: "<compositing-operator>#"
},
"mask-image": {
syntax: "<mask-reference>#"
},
"mask-mode": {
syntax: "<masking-mode>#"
},
"mask-origin": {
syntax: "<coord-box>#"
},
"mask-position": {
syntax: "<position>#"
},
"mask-repeat": {
syntax: "<repeat-style>#"
},
"mask-size": {
syntax: "<bg-size>#"
},
"mask-type": {
syntax: "luminance | alpha"
},
"masonry-auto-flow": {
syntax: "[ pack | next ] || [ definite-first | ordered ]"
},
"math-depth": {
syntax: "auto-add | add(<integer>) | <integer>"
},
"math-shift": {
syntax: "normal | compact"
},
"math-style": {
syntax: "normal | compact"
},
"max-block-size": {
syntax: "<'max-width'>"
},
"max-height": {
syntax: "none | <length-percentage [0,∞]> | min-content | max-content | fit-content | fit-content(<length-percentage [0,∞]>) | <calc-size()> | <anchor-size()>"
},
"max-inline-size": {
syntax: "<'max-width'>"
},
"max-lines": {
syntax: "none | <integer>"
},
"max-width": {
syntax: "none | <length-percentage [0,∞]> | min-content | max-content | fit-content | fit-content(<length-percentage [0,∞]>) | <calc-size()> | <anchor-size()>"
},
"min-block-size": {
syntax: "<'min-width'>"
},
"min-height": {
syntax: "auto | <length-percentage [0,∞]> | min-content | max-content | fit-content | fit-content(<length-percentage [0,∞]>) | <calc-size()> | <anchor-size()>"
},
"min-inline-size": {
syntax: "<'min-width'>"
},
"min-width": {
syntax: "auto | <length-percentage [0,∞]> | min-content | max-content | fit-content | fit-content(<length-percentage [0,∞]>) | <calc-size()> | <anchor-size()>"
},
"mix-blend-mode": {
syntax: "<blend-mode> | plus-lighter"
},
"object-fit": {
syntax: "fill | contain | cover | none | scale-down"
},
"object-position": {
syntax: "<position>"
},
offset: {
syntax: "[ <'offset-position'>? [ <'offset-path'> [ <'offset-distance'> || <'offset-rotate'> ]? ]? ]! [ / <'offset-anchor'> ]?"
},
"offset-anchor": {
syntax: "auto | <position>"
},
"offset-distance": {
syntax: "<length-percentage>"
},
"offset-path": {
syntax: "none | <offset-path> || <coord-box>"
},
"offset-position": {
syntax: "normal | auto | <position>"
},
"offset-rotate": {
syntax: "[ auto | reverse ] || <angle>"
},
opacity: {
syntax: "<opacity-value>"
},
order: {
syntax: "<integer>"
},
orphans: {
syntax: "<integer>"
},
outline: {
syntax: "<'outline-width'> || <'outline-style'> || <'outline-color'>"
},
"outline-color": {
syntax: "auto | <color>"
},
"outline-offset": {
syntax: "<length>"
},
"outline-style": {
syntax: "auto | <outline-line-style>"
},
"outline-width": {
syntax: "<line-width>"
},
overflow: {
syntax: "[ visible | hidden | clip | scroll | auto ]{1,2}"
},
"overflow-anchor": {
syntax: "auto | none"
},
"overflow-block": {
syntax: "visible | hidden | clip | scroll | auto"
},
"overflow-clip-box": {
syntax: "padding-box | content-box"
},
"overflow-clip-margin": {
syntax: "<visual-box> || <length [0,∞]>"
},
"overflow-inline": {
syntax: "visible | hidden | clip | scroll | auto"
},
"overflow-wrap": {
syntax: "normal | break-word | anywhere"
},
"overflow-x": {
syntax: "visible | hidden | clip | scroll | auto"
},
"overflow-y": {
syntax: "visible | hidden | clip | scroll | auto"
},
overlay: {
syntax: "none | auto"
},
"overscroll-behavior": {
syntax: "[ contain | none | auto ]{1,2}"
},
"overscroll-behavior-block": {
syntax: "contain | none | auto"
},
"overscroll-behavior-inline": {
syntax: "contain | none | auto"
},
"overscroll-behavior-x": {
syntax: "contain | none | auto"
},
"overscroll-behavior-y": {
syntax: "contain | none | auto"
},
padding: {
syntax: "<'padding-top'>{1,4}"
},
"padding-block": {
syntax: "<'padding-top'>{1,2}"
},
"padding-block-end": {
syntax: "<'padding-top'>"
},
"padding-block-start": {
syntax: "<'padding-top'>"
},
"padding-bottom": {
syntax: "<length-percentage [0,∞]>"
},
"padding-inline": {
syntax: "<'padding-top'>{1,2}"
},
"padding-inline-end": {
syntax: "<'padding-top'>"
},
"padding-inline-start": {
syntax: "<'padding-top'>"
},
"padding-left": {
syntax: "<length-percentage [0,∞]>"
},
"padding-right": {
syntax: "<length-percentage [0,∞]>"
},
"padding-top": {
syntax: "<length-percentage [0,∞]>"
},
page: {
syntax: "auto | <custom-ident>"
},
"page-break-after": {
syntax: "auto | always | avoid | left | right | recto | verso"
},
"page-break-before": {
syntax: "auto | always | avoid | left | right | recto | verso"
},
"page-break-inside": {
syntax: "auto | avoid"
},
"paint-order": {
syntax: "normal | [ fill || stroke || markers ]"
},
perspective: {
syntax: "none | <length>"
},
"perspective-origin": {
syntax: "<position>"
},
"place-content": {
syntax: "<'align-content'> <'justify-content'>?"
},
"place-items": {
syntax: "<'align-items'> <'justify-items'>?"
},
"place-self": {
syntax: "<'align-self'> <'justify-self'>?"
},
"pointer-events": {
syntax: "auto | none | visiblePainted | visibleFill | visibleStroke | visible | painted | fill | stroke | all | inherit"
},
position: {
syntax: "static | relative | absolute | sticky | fixed"
},
"position-anchor": {
syntax: "auto | <anchor-name>"
},
"position-area": {
syntax: "none | <position-area>"
},
"position-try": {
syntax: "<'position-try-order'>? <'position-try-fallbacks'>"
},
"position-try-fallbacks": {
syntax: "none | [ [<dashed-ident> || <try-tactic>] | <'position-area'> ]#"
},
"position-try-order": {
syntax: "normal | <try-size>"
},
"position-visibility": {
syntax: "always | [ anchors-valid || anchors-visible || no-overflow ]"
},
"print-color-adjust": {
syntax: "economy | exact"
},
quotes: {
syntax: "none | auto | [ <string> <string> ]+"
},
r: {
syntax: "<length> | <percentage>"
},
resize: {
syntax: "none | both | horizontal | vertical | block | inline"
},
right: {
syntax: "<length> | <percentage> | auto"
},
rotate: {
syntax: "none | <angle> | [ x | y | z | <number>{3} ] && <angle>"
},
"row-gap": {
syntax: "normal | <length-percentage>"
},
"ruby-align": {
syntax: "start | center | space-between | space-around"
},
"ruby-merge": {
syntax: "separate | collapse | auto"
},
"ruby-position": {
syntax: "[ alternate || [ over | under ] ] | inter-character"
},
rx: {
syntax: "<length> | <percentage>"
},
ry: {
syntax: "<length> | <percentage>"
},
scale: {
syntax: "none | [ <number> | <percentage> ]{1,3}"
},
"scroll-behavior": {
syntax: "auto | smooth"
},
"scroll-margin": {
syntax: "<length>{1,4}"
},
"scroll-margin-block": {
syntax: "<length>{1,2}"
},
"scroll-margin-block-end": {
syntax: "<length>"
},
"scroll-margin-block-start": {
syntax: "<length>"
},
"scroll-margin-bottom": {
syntax: "<length>"
},
"scroll-margin-inline": {
syntax: "<length>{1,2}"
},
"scroll-margin-inline-end": {
syntax: "<length>"
},
"scroll-margin-inline-start": {
syntax: "<length>"
},
"scroll-margin-left": {
syntax: "<length>"
},
"scroll-margin-right": {
syntax: "<length>"
},
"scroll-margin-top": {
syntax: "<length>"
},
"scroll-padding": {
syntax: "[ auto | <length-percentage> ]{1,4}"
},
"scroll-padding-block": {
syntax: "[ auto | <length-percentage> ]{1,2}"
},
"scroll-padding-block-end": {
syntax: "auto | <length-percentage>"
},
"scroll-padding-block-start": {
syntax: "auto | <length-percentage>"
},
"scroll-padding-bottom": {
syntax: "auto | <length-percentage>"
},
"scroll-padding-inline": {
syntax: "[ auto | <length-percentage> ]{1,2}"
},
"scroll-padding-inline-end": {
syntax: "auto | <length-percentage>"
},
"scroll-padding-inline-start": {
syntax: "auto | <length-percentage>"
},
"scroll-padding-left": {
syntax: "auto | <length-percentage>"
},
"scroll-padding-right": {
syntax: "auto | <length-percentage>"
},
"scroll-padding-top": {
syntax: "auto | <length-percentage>"
},
"scroll-snap-align": {
syntax: "[ none | start | end | center ]{1,2}"
},
"scroll-snap-coordinate": {
syntax: "none | <position>#"
},
"scroll-snap-destination": {
syntax: "<position>"
},
"scroll-snap-points-x": {
syntax: "none | repeat( <length-percentage> )"
},
"scroll-snap-points-y": {
syntax: "none | repeat( <length-percentage> )"
},
"scroll-snap-stop": {
syntax: "normal | always"
},
"scroll-snap-type": {
syntax: "none | [ x | y | block | inline | both ] [ mandatory | proximity ]?"
},
"scroll-snap-type-x": {
syntax: "none | mandatory | proximity"
},
"scroll-snap-type-y": {
syntax: "none | mandatory | proximity"
},
"scroll-timeline": {
syntax: "[ <'scroll-timeline-name'> <'scroll-timeline-axis'>? ]#"
},
"scroll-timeline-axis": {
syntax: "[ block | inline | x | y ]#"
},
"scroll-timeline-name": {
syntax: "[ none | <dashed-ident> ]#"
},
"scrollbar-color": {
syntax: "auto | <color>{2}"
},
"scrollbar-gutter": {
syntax: "auto | stable && both-edges?"
},
"scrollbar-width": {
syntax: "auto | thin | none"
},
"shape-image-threshold": {
syntax: "<opacity-value>"
},
"shape-margin": {
syntax: "<length-percentage>"
},
"shape-outside": {
syntax: "none | [ <shape-box> || <basic-shape> ] | <image>"
},
"shape-rendering": {
syntax: "auto | optimizeSpeed | crispEdges | geometricPrecision"
},
"speak-as": {
syntax: "normal | spell-out || digits || [ literal-punctuation | no-punctuation ]"
},
"stop-color": {
syntax: "<'color'>"
},
"stop-opacity": {
syntax: "<'opacity'>"
},
stroke: {
syntax: "<paint>"
},
"stroke-dasharray": {
syntax: "none | <dasharray>"
},
"stroke-dashoffset": {
syntax: "<length-percentage> | <number>"
},
"stroke-linecap": {
syntax: "butt | round | square"
},
"stroke-linejoin": {
syntax: "miter | miter-clip | round | bevel | arcs"
},
"stroke-miterlimit": {
syntax: "<number>"
},
"stroke-opacity": {
syntax: "<'opacity'>"
},
"stroke-width": {
syntax: "<length-percentage> | <number>"
},
"tab-size": {
syntax: "<integer> | <length>"
},
"table-layout": {
syntax: "auto | fixed"
},
"text-align": {
syntax: "start | end | left | right | center | justify | match-parent"
},
"text-align-last": {
syntax: "auto | start | end | left | right | center | justify"
},
"text-anchor": {
syntax: "start | middle | end"
},
"text-box": {
syntax: "normal | <'text-box-trim'> || <'text-box-edge'>"
},
"text-box-edge": {
syntax: "auto | <text-edge>"
},
"text-box-trim": {
syntax: "none | trim-start | trim-end | trim-both"
},
"text-combine-upright": {
syntax: "none | all | [ digits <integer>? ]"
},
"text-decoration": {
syntax: "<'text-decoration-line'> || <'text-decoration-style'> || <'text-decoration-color'> || <'text-decoration-thickness'>"
},
"text-decoration-color": {
syntax: "<color>"
},
"text-decoration-line": {
syntax: "none | [ underline || overline || line-through || blink ] | spelling-error | grammar-error"
},
"text-decoration-skip": {
syntax: "none | [ objects || [ spaces | [ leading-spaces || trailing-spaces ] ] || edges || box-decoration ]"
},
"text-decoration-skip-ink": {
syntax: "auto | all | none"
},
"text-decoration-style": {
syntax: "solid | double | dotted | dashed | wavy"
},
"text-decoration-thickness": {
syntax: "auto | from-font | <length> | <percentage> "
},
"text-emphasis": {
syntax: "<'text-emphasis-style'> || <'text-emphasis-color'>"
},
"text-emphasis-color": {
syntax: "<color>"
},
"text-emphasis-position": {
syntax: "auto | [ over | under ] && [ right | left ]?"
},
"text-emphasis-style": {
syntax: "none | [ [ filled | open ] || [ dot | circle | double-circle | triangle | sesame ] ] | <string>"
},
"text-indent": {
syntax: "<length-percentage> && hanging? && each-line?"
},
"text-justify": {
syntax: "auto | inter-character | inter-word | none"
},
"text-orientation": {
syntax: "mixed | upright | sideways"
},
"text-overflow": {
syntax: "[ clip | ellipsis | <string> ]{1,2}"
},
"text-rendering": {
syntax: "auto | optimizeSpeed | optimizeLegibility | geometricPrecision"
},
"text-shadow": {
syntax: "none | <shadow-t>#"
},
"text-size-adjust": {
syntax: "none | auto | <percentage>"
},
"text-spacing-trim": {
syntax: "space-all | normal | space-first | trim-start"
},
"text-transform": {
syntax: "none | [ capitalize | uppercase | lowercase ] || full-width || full-size-kana | math-auto"
},
"text-underline-offset": {
syntax: "auto | <length> | <percentage> "
},
"text-underline-position": {
syntax: "auto | from-font | [ under || [ left | right ] ]"
},
"text-wrap": {
syntax: "<'text-wrap-mode'> || <'text-wrap-style'>"
},
"text-wrap-mode": {
syntax: "wrap | nowrap"
},
"text-wrap-style": {
syntax: "auto | balance | stable | pretty"
},
"timeline-scope": {
syntax: "none | <dashed-ident>#"
},
top: {
syntax: "<length> | <percentage> | auto"
},
"touch-action": {
syntax: "auto | none | [ [ pan-x | pan-left | pan-right ] || [ pan-y | pan-up | pan-down ] || pinch-zoom ] | manipulation"
},
transform: {
syntax: "none | <transform-list>"
},
"transform-box": {
syntax: "content-box | border-box | fill-box | stroke-box | view-box"
},
"transform-origin": {
syntax: "[ <length-percentage> | left | center | right | top | bottom ] | [ [ <length-percentage> | left | center | right ] && [ <length-percentage> | top | center | bottom ] ] <length>?"
},
"transform-style": {
syntax: "flat | preserve-3d"
},
transition: {
syntax: "<single-transition>#"
},
"transition-behavior": {
syntax: "<transition-behavior-value>#"
},
"transition-delay": {
syntax: "<time>#"
},
"transition-duration": {
syntax: "<time>#"
},
"transition-property": {
syntax: "none | <single-transition-property>#"
},
"transition-timing-function": {
syntax: "<easing-function>#"
},
translate: {
syntax: "none | <length-percentage> [ <length-percentage> <length>? ]?"
},
"unicode-bidi": {
syntax: "normal | embed | isolate | bidi-override | isolate-override | plaintext"
},
"user-select": {
syntax: "auto | text | none | all"
},
"vector-effect": {
syntax: "none | non-scaling-stroke | non-scaling-size | non-rotation | fixed-position"
},
"vertical-align": {
syntax: "baseline | sub | super | text-top | text-bottom | middle | top | bottom | <percentage> | <length>"
},
"view-timeline": {
syntax: "[ <'view-timeline-name'> <'view-timeline-axis'>? ]#"
},
"view-timeline-axis": {
syntax: "[ block | inline | x | y ]#"
},
"view-timeline-inset": {
syntax: "[ [ auto | <length-percentage> ]{1,2} ]#"
},
"view-timeline-name": {
syntax: "none | <dashed-ident>#"
},
"view-transition-name": {
syntax: "none | <custom-ident>"
},
visibility: {
syntax: "visible | hidden | collapse"
},
"white-space": {
syntax: "normal | pre | pre-wrap | pre-line | <'white-space-collapse'> || <'text-wrap-mode'>"
},
"white-space-collapse": {
syntax: "collapse | preserve | preserve-breaks | preserve-spaces | break-spaces"
},
widows: {
syntax: "<integer>"
},
width: {
syntax: "auto | <length-percentage [0,∞]> | min-content | max-content | fit-content | fit-content(<length-percentage [0,∞]>) | <calc-size()> | <anchor-size()>"
},
"will-change": {
syntax: "auto | <animateable-feature>#"
},
"word-break": {
syntax: "normal | break-all | keep-all | break-word | auto-phrase"
},
"word-spacing": {
syntax: "normal | <length>"
},
"word-wrap": {
syntax: "normal | break-word"
},
"writing-mode": {
syntax: "horizontal-tb | vertical-rl | vertical-lr | sideways-rl | sideways-lr"
},
x: {
syntax: "<length> | <percentage>"
},
y: {
syntax: "<length> | <percentage>"
},
"z-index": {
syntax: "auto | <integer>"
},
zoom: {
syntax: "normal | reset | <number [0,∞]> || <percentage [0,∞]>"
}
};
var functions = {
abs: {
syntax: "abs( <calc-sum> )"
},
acos: {
syntax: "acos( <calc-sum> )"
},
anchor: {
syntax: "anchor( <anchor-name>? && <anchor-side>, <length-percentage>? )"
},
"anchor-size": {
syntax: "anchor-size( [ <anchor-name> || <anchor-size> ]? , <length-percentage>? )"
},
asin: {
syntax: "asin( <calc-sum> )"
},
atan: {
syntax: "atan( <calc-sum> )"
},
atan2: {
syntax: "atan2( <calc-sum>, <calc-sum> )"
},
attr: {
syntax: "attr( <attr-name> <type-or-unit>? [, <attr-fallback> ]? )"
},
blur: {
syntax: "blur( <length>? )"
},
brightness: {
syntax: "brightness( [ <number> | <percentage> ]? )"
},
calc: {
syntax: "calc( <calc-sum> )"
},
"calc-size": {
syntax: "calc-size( <calc-size-basis>, <calc-sum> )"
},
circle: {
syntax: "circle( <radial-size>? [ at <position> ]? )"
},
clamp: {
syntax: "clamp( <calc-sum>#{3} )"
},
color: {
syntax: "color( [ from <color> ]? <colorspace-params> [ / [ <alpha-value> | none ] ]? )"
},
"color-mix": {
syntax: "color-mix( <color-interpolation-method> , [ <color> && <percentage [0,100]>? ]#{2})"
},
"conic-gradient": {
syntax: "conic-gradient( [ from <angle> ]? [ at <position> ]?, <angular-color-stop-list> )"
},
contrast: {
syntax: "contrast( [ <number> | <percentage> ]? )"
},
cos: {
syntax: "cos( <calc-sum> )"
},
counter: {
syntax: "counter( <counter-name>, <counter-style>? )"
},
counters: {
syntax: "counters( <counter-name>, <string>, <counter-style>? )"
},
"cross-fade": {
syntax: "cross-fade( <cf-mixing-image> , <cf-final-image>? )"
},
"drop-shadow": {
syntax: "drop-shadow( [ <color>? && <length>{2,3} ] )"
},
element: {
syntax: "element( <id-selector> )"
},
ellipse: {
syntax: "ellipse( <radial-size>? [ at <position> ]? )"
},
env: {
syntax: "env( <custom-ident> , <declaration-value>? )"
},
exp: {
syntax: "exp( <calc-sum> )"
},
"fit-content": {
syntax: "fit-content( <length-percentage [0,∞]> )"
},
grayscale: {
syntax: "grayscale( [ <number> | <percentage> ]? )"
},
hsl: {
syntax: "hsl( <hue>, <percentage>, <percentage>, <alpha-value>? ) | hsl( [ <hue> | none ] [ <percentage> | <number> | none ] [ <percentage> | <number> | none ] [ / [ <alpha-value> | none ] ]? )"
},
hsla: {
syntax: "hsla( <hue>, <percentage>, <percentage>, <alpha-value>? ) | hsla( [ <hue> | none ] [ <percentage> | <number> | none ] [ <percentage> | <number> | none ] [ / [ <alpha-value> | none ] ]? )"
},
"hue-rotate": {
syntax: "hue-rotate( [ <angle> | <zero> ]? )"
},
hwb: {
syntax: "hwb( [ <hue> | none ] [ <percentage> | <number> | none ] [ <percentage> | <number> | none ] [ / [ <alpha-value> | none ] ]? )"
},
hypot: {
syntax: "hypot( <calc-sum># )"
},
image: {
syntax: "image( <image-tags>? [ <image-src>? , <color>? ]! )"
},
"image-set": {
syntax: "image-set( <image-set-option># )"
},
inset: {
syntax: "inset( <length-percentage>{1,4} [ round <'border-radius'> ]? )"
},
invert: {
syntax: "invert( [ <number> | <percentage> ]? )"
},
lab: {
syntax: "lab( [<percentage> | <number> | none] [ <percentage> | <number> | none] [ <percentage> | <number> | none] [ / [<alpha-value> | none] ]? )"
},
layer: {
syntax: "layer( <layer-name> )"
},
lch: {
syntax: "lch( [<percentage> | <number> | none] [ <percentage> | <number> | none] [ <hue> | none] [ / [<alpha-value> | none] ]? )"
},
leader: {
syntax: "leader( <leader-type> )"
},
"light-dark": {
syntax: "light-dark( <color>, <color> )"
},
"linear-gradient": {
syntax: "linear-gradient( [ <angle> | to <side-or-corner> ]? , <color-stop-list> )"
},
log: {
syntax: "log( <calc-sum>, <calc-sum>? )"
},
matrix: {
syntax: "matrix( <number>#{6} )"
},
matrix3d: {
syntax: "matrix3d( <number>#{16} )"
},
max: {
syntax: "max( <calc-sum># )"
},
min: {
syntax: "min( <calc-sum># )"
},
minmax: {
syntax: "minmax( [ <length-percentage> | min-content | max-content | auto ] , [ <length-percentage> | <flex> | min-content | max-content | auto ] )"
},
mod: {
syntax: "mod( <calc-sum>, <calc-sum> )"
},
oklab: {
syntax: "oklab( [ <percentage> | <number> | none] [ <percentage> | <number> | none] [ <percentage> | <number> | none] [ / [<alpha-value> | none] ]? )"
},
oklch: {
syntax: "oklch( [ <percentage> | <number> | none] [ <percentage> | <number> | none] [ <hue> | none] [ / [<alpha-value> | none] ]? )"
},
opacity: {
syntax: "opacity( [ <number> | <percentage> ]? )"
},
paint: {
syntax: "paint( <ident>, <declaration-value>? )"
},
"palette-mix": {
syntax: "palette-mix(<color-interpolation-method> , [ [normal | light | dark | <palette-identifier> | <palette-mix()> ] && <percentage [0,100]>? ]#{2})"
},
path: {
syntax: "path( <'fill-rule'>? , <string> )"
},
perspective: {
syntax: "perspective( [ <length [0,∞]> | none ] )"
},
polygon: {
syntax: "polygon( <'fill-rule'>? , [ <length-percentage> <length-percentage> ]# )"
},
pow: {
syntax: "pow( <calc-sum>, <calc-sum> )"
},
"radial-gradient": {
syntax: "radial-gradient( [ <ending-shape> || <size> ]? [ at <position> ]? , <color-stop-list> )"
},
ray: {
syntax: "ray( <angle> && <ray-size>? && contain? && [at <position>]? )"
},
rect: {
syntax: "rect( [ <length-percentage> | auto ]{4} [ round <'border-radius'> ]? )"
},
rem: {
syntax: "rem( <calc-sum>, <calc-sum> )"
},
"repeating-conic-gradient": {
syntax: "repeating-conic-gradient( [ from <angle> ]? [ at <position> ]?, <angular-color-stop-list> )"
},
"repeating-linear-gradient": {
syntax: "repeating-linear-gradient( [ <angle> | to <side-or-corner> ]? , <color-stop-list> )"
},
"repeating-radial-gradient": {
syntax: "repeating-radial-gradient( [ <ending-shape> || <size> ]? [ at <position> ]? , <color-stop-list> )"
},
rgb: {
syntax: "rgb( <percentage>#{3} , <alpha-value>? ) | rgb( <number>#{3} , <alpha-value>? ) | rgb( [ <number> | <percentage> | none ]{3} [ / [ <alpha-value> | none ] ]? )"
},
rgba: {
syntax: "rgba( <percentage>#{3} , <alpha-value>? ) | rgba( <number>#{3} , <alpha-value>? ) | rgba( [ <number> | <percentage> | none ]{3} [ / [ <alpha-value> | none ] ]? )"
},
rotate: {
syntax: "rotate( [ <angle> | <zero> ] )"
},
rotate3d: {
syntax: "rotate3d( <number> , <number> , <number> , [ <angle> | <zero> ] )"
},
rotateX: {
syntax: "rotateX( [ <angle> | <zero> ] )"
},
rotateY: {
syntax: "rotateY( [ <angle> | <zero> ] )"
},
rotateZ: {
syntax: "rotateZ( [ <angle> | <zero> ] )"
},
round: {
syntax: "round( <rounding-strategy>?, <calc-sum>, <calc-sum> )"
},
saturate: {
syntax: "saturate( [ <number> | <percentage> ]? )"
},
scale: {
syntax: "scale( [ <number> | <percentage> ]#{1,2} )"
},
scale3d: {
syntax: "scale3d( [ <number> | <percentage> ]#{3} )"
},
scaleX: {
syntax: "scaleX( [ <number> | <percentage> ] )"
},
scaleY: {
syntax: "scaleY( [ <number> | <percentage> ] )"
},
scaleZ: {
syntax: "scaleZ( [ <number> | <percentage> ] )"
},
scroll: {
syntax: "scroll( [ <scroller> || <axis> ]? )"
},
sepia: {
syntax: "sepia( [ <number> | <percentage> ]? )"
},
sign: {
syntax: "sign( <calc-sum> )"
},
sin: {
syntax: "sin( <calc-sum> )"
},
skew: {
syntax: "skew( [ <angle> | <zero> ] , [ <angle> | <zero> ]? )"
},
skewX: {
syntax: "skewX( [ <angle> | <zero> ] )"
},
skewY: {
syntax: "skewY( [ <angle> | <zero> ] )"
},
sqrt: {
syntax: "sqrt( <calc-sum> )"
},
symbols: {
syntax: "symbols( <symbols-type>? [ <string> | <image> ]+ )"
},
tan: {
syntax: "tan( <calc-sum> )"
},
"target-counter": {
syntax: "target-counter( [ <string> | <url> ] , <custom-ident> , <counter-style>? )"
},
"target-counters": {
syntax: "target-counters( [ <string> | <url> ] , <custom-ident> , <string> , <counter-style>? )"
},
"target-text": {
syntax: "target-text( [ <string> | <url> ] , [ content | before | after | first-letter ]? )"
},
translate: {
syntax: "translate( <length-percentage> , <length-percentage>? )"
},
translate3d: {
syntax: "translate3d( <length-percentage> , <length-percentage> , <length> )"
},
translateX: {
syntax: "translateX( <length-percentage> )"
},
translateY: {
syntax: "translateY( <length-percentage> )"
},
translateZ: {
syntax: "translateZ( <length> )"
},
"var": {
syntax: "var( <custom-property-name> , <declaration-value>? )"
},
view: {
syntax: "view([<axis> || <'view-timeline-inset'>]?)"
},
xywh: {
syntax: "xywh( <length-percentage>{2} <length-percentage [0,∞]>{2} [ round <'border-radius'> ]? )"
}
};
var syntaxes = {
"abs()": {
syntax: "abs( <calc-sum> )"
},
"absolute-size": {
syntax: "xx-small | x-small | small | medium | large | x-large | xx-large | xxx-large"
},
"acos()": {
syntax: "acos( <calc-sum> )"
},
"alpha-value": {
syntax: "<number> | <percentage>"
},
"an+b": {
syntax: "odd | even | <integer> | <n-dimension> | '+'?† n | -n | <ndashdigit-dimension> | '+'?† <ndashdigit-ident> | <dashndashdigit-ident> | <n-dimension> <signed-integer> | '+'?† n <signed-integer> | -n <signed-integer> | <ndash-dimension> <signless-integer> | '+'?† n- <signless-integer> | -n- <signless-integer> | <n-dimension> ['+' | '-'] <signless-integer> | '+'?† n ['+' | '-'] <signless-integer> | -n ['+' | '-'] <signless-integer>"
},
"anchor()": {
syntax: "anchor( <anchor-name>? && <anchor-side>, <length-percentage>? )"
},
"anchor-name": {
syntax: "<dashed-ident>"
},
"anchor-side": {
syntax: "inside | outside | top | left | right | bottom | start | end | self-start | self-end | <percentage> | center"
},
"anchor-size": {
syntax: "width | height | block | inline | self-block | self-inline"
},
"anchor-size()": {
syntax: "anchor-size( [ <anchor-name> || <anchor-size> ]? , <length-percentage>? )"
},
"angle-percentage": {
syntax: "<angle> | <percentage>"
},
"angular-color-hint": {
syntax: "<angle-percentage>"
},
"angular-color-stop": {
syntax: "<color> && <color-stop-angle>?"
},
"angular-color-stop-list": {
syntax: "[ <angular-color-stop> [, <angular-color-hint>]? ]# , <angular-color-stop>"
},
"animateable-feature": {
syntax: "scroll-position | contents | <custom-ident>"
},
"asin()": {
syntax: "asin( <calc-sum> )"
},
"atan()": {
syntax: "atan( <calc-sum> )"
},
"atan2()": {
syntax: "atan2( <calc-sum>, <calc-sum> )"
},
attachment: {
syntax: "scroll | fixed | local"
},
"attr()": {
syntax: "attr( <attr-name> <type-or-unit>? [, <attr-fallback> ]? )"
},
"attr-matcher": {
syntax: "[ '~' | '|' | '^' | '$' | '*' ]? '='"
},
"attr-modifier": {
syntax: "i | s"
},
"attribute-selector": {
syntax: "'[' <wq-name> ']' | '[' <wq-name> <attr-matcher> [ <string-token> | <ident-token> ] <attr-modifier>? ']'"
},
"auto-repeat": {
syntax: "repeat( [ auto-fill | auto-fit ] , [ <line-names>? <fixed-size> ]+ <line-names>? )"
},
"auto-track-list": {
syntax: "[ <line-names>? [ <fixed-size> | <fixed-repeat> ] ]* <line-names>? <auto-repeat>\n[ <line-names>? [ <fixed-size> | <fixed-repeat> ] ]* <line-names>?"
},
axis: {
syntax: "block | inline | x | y"
},
"baseline-position": {
syntax: "[ first | last ]? baseline"
},
"basic-shape": {
syntax: "<inset()> | <circle()> | <ellipse()> | <polygon()> | <path()>"
},
"bg-clip": {
syntax: "<visual-box> | border-area | text"
},
"bg-image": {
syntax: "none | <image>"
},
"bg-layer": {
syntax: "<bg-image> || <bg-position> [ / <bg-size> ]? || <repeat-style> || <attachment> || <visual-box> || <visual-box>"
},
"bg-position": {
syntax: "[ [ left | center | right | top | bottom | <length-percentage> ] | [ left | center | right | <length-percentage> ] [ top | center | bottom | <length-percentage> ] | [ center | [ left | right ] <length-percentage>? ] && [ center | [ top | bottom ] <length-percentage>? ] ]"
},
"bg-size": {
syntax: "[ <length-percentage> | auto ]{1,2} | cover | contain"
},
"blend-mode": {
syntax: "normal | multiply | screen | overlay | darken | lighten | color-dodge | color-burn | hard-light | soft-light | difference | exclusion | hue | saturation | color | luminosity"
},
"blur()": {
syntax: "blur( <length>? )"
},
"brightness()": {
syntax: "brightness( [ <number> | <percentage> ]? )"
},
"calc()": {
syntax: "calc( <calc-sum> )"
},
"calc-constant": {
syntax: "e | pi | infinity | -infinity | NaN"
},
"calc-product": {
syntax: "<calc-value> [ '*' <calc-value> | '/' <number> ]*"
},
"calc-size()": {
syntax: "calc-size( <calc-size-basis>, <calc-sum> )"
},
"calc-size-basis": {
syntax: "<intrinsic-size-keyword> | <calc-size()> | any | <calc-sum>"
},
"calc-sum": {
syntax: "<calc-product> [ [ '+' | '-' ] <calc-product> ]*"
},
"calc-value": {
syntax: "<number> | <dimension> | <percentage> | <calc-constant> | ( <calc-sum> )"
},
"cf-final-image": {
syntax: "<image> | <color>"
},
"cf-mixing-image": {
syntax: "<percentage>? && <image>"
},
"circle()": {
syntax: "circle( <radial-size>? [ at <position> ]? )"
},
"clamp()": {
syntax: "clamp( <calc-sum>#{3} )"
},
"class-selector": {
syntax: "'.' <ident-token>"
},
"clip-source": {
syntax: "<url>"
},
color: {
syntax: "<color-base> | currentColor | <system-color> | <light-dark()> | <deprecated-system-color>"
},
"color()": {
syntax: "color( [ from <color> ]? <colorspace-params> [ / [ <alpha-value> | none ] ]? )"
},
"color-base": {
syntax: "<hex-color> | <color-function> | <named-color> | <color-mix()> | transparent"
},
"color-function": {
syntax: "<rgb()> | <rgba()> | <hsl()> | <hsla()> | <hwb()> | <lab()> | <lch()> | <oklab()> | <oklch()> | <color()>"
},
"color-interpolation-method": {
syntax: "in [ <rectangular-color-space> | <polar-color-space> <hue-interpolation-method>? | <custom-color-space> ]"
},
"color-mix()": {
syntax: "color-mix( <color-interpolation-method> , [ <color> && <percentage [0,100]>? ]#{2})"
},
"color-stop": {
syntax: "<color-stop-length> | <color-stop-angle>"
},
"color-stop-angle": {
syntax: "<angle-percentage>{1,2}"
},
"color-stop-length": {
syntax: "<length-percentage>{1,2}"
},
"color-stop-list": {
syntax: "[ <linear-color-stop> [, <linear-color-hint>]? ]# , <linear-color-stop>"
},
"colorspace-params": {
syntax: "[<custom-params> | <predefined-rgb-params> | <xyz-params>]"
},
combinator: {
syntax: "'>' | '+' | '~' | [ '||' ]"
},
"common-lig-values": {
syntax: "[ common-ligatures | no-common-ligatures ]"
},
"compat-auto": {
syntax: "searchfield | textarea | push-button | slider-horizontal | checkbox | radio | square-button | menulist | listbox | meter | progress-bar | button"
},
"complex-selector": {
syntax: "<compound-selector> [ <combinator>? <compound-selector> ]*"
},
"complex-selector-list": {
syntax: "<complex-selector>#"
},
"composite-style": {
syntax: "clear | copy | source-over | source-in | source-out | source-atop | destination-over | destination-in | destination-out | destination-atop | xor"
},
"compositing-operator": {
syntax: "add | subtract | intersect | exclude"
},
"compound-selector": {
syntax: "[ <type-selector>? <subclass-selector>* [ <pseudo-element-selector> <pseudo-class-selector>* ]* ]!"
},
"compound-selector-list": {
syntax: "<compound-selector>#"
},
"conic-gradient()": {
syntax: "conic-gradient( [ from <angle> ]? [ at <position> ]?, <angular-color-stop-list> )"
},
"content-distribution": {
syntax: "space-between | space-around | space-evenly | stretch"
},
"content-list": {
syntax: "[ <string> | contents | <image> | <counter> | <quote> | <target> | <leader()> ]+"
},
"content-position": {
syntax: "center | start | end | flex-start | flex-end"
},
"content-replacement": {
syntax: "<image>"
},
"contextual-alt-values": {
syntax: "[ contextual | no-contextual ]"
},
"contrast()": {
syntax: "contrast( [ <number> | <percentage> ]? )"
},
"coord-box": {
syntax: "<paint-box> | view-box"
},
"cos()": {
syntax: "cos( <calc-sum> )"
},
counter: {
syntax: "<counter()> | <counters()>"
},
"counter()": {
syntax: "counter( <counter-name>, <counter-style>? )"
},
"counter-name": {
syntax: "<custom-ident>"
},
"counter-style": {
syntax: "<counter-style-name> | symbols()"
},
"counter-style-name": {
syntax: "<custom-ident>"
},
"counters()": {
syntax: "counters( <counter-name>, <string>, <counter-style>? )"
},
"cross-fade()": {
syntax: "cross-fade( <cf-mixing-image> , <cf-final-image>? )"
},
"cubic-bezier-timing-function": {
syntax: "ease | ease-in | ease-out | ease-in-out | cubic-bezier(<number [0,1]>, <number>, <number [0,1]>, <number>)"
},
"custom-color-space": {
syntax: "<dashed-ident>"
},
"custom-params": {
syntax: "<dashed-ident> [ <number> | <percentage> | none ]+"
},
dasharray: {
syntax: "[ [ <length-percentage> | <number> ]+ ]#"
},
"dashndashdigit-ident": {
syntax: "<ident-token>"
},
"deprecated-system-color": {
syntax: "ActiveBorder | ActiveCaption | AppWorkspace | Background | ButtonHighlight | ButtonShadow | CaptionText | InactiveBorder | InactiveCaption | InactiveCaptionText | InfoBackground | InfoText | Menu | MenuText | Scrollbar | ThreeDDarkShadow | ThreeDFace | ThreeDHighlight | ThreeDLightShadow | ThreeDShadow | Window | WindowFrame | WindowText"
},
"discretionary-lig-values": {
syntax: "[ discretionary-ligatures | no-discretionary-ligatures ]"
},
"display-box": {
syntax: "contents | none"
},
"display-inside": {
syntax: "flow | flow-root | table | flex | grid | ruby"
},
"display-internal": {
syntax: "table-row-group | table-header-group | table-footer-group | table-row | table-cell | table-column-group | table-column | table-caption | ruby-base | ruby-text | ruby-base-container | ruby-text-container"
},
"display-legacy": {
syntax: "inline-block | inline-list-item | inline-table | inline-flex | inline-grid"
},
"display-listitem": {
syntax: "<display-outside>? && [ flow | flow-root ]? && list-item"
},
"display-outside": {
syntax: "block | inline | run-in"
},
"drop-shadow()": {
syntax: "drop-shadow( [ <color>? && <length>{2,3} ] )"
},
"easing-function": {
syntax: "linear | <cubic-bezier-timing-function> | <step-timing-function>"
},
"east-asian-variant-values": {
syntax: "[ jis78 | jis83 | jis90 | jis04 | simplified | traditional ]"
},
"east-asian-width-values": {
syntax: "[ full-width | proportional-width ]"
},
"element()": {
syntax: "element( <id-selector> )"
},
"ellipse()": {
syntax: "ellipse( <radial-size>? [ at <position> ]? )"
},
"ending-shape": {
syntax: "circle | ellipse"
},
"env()": {
syntax: "env( <custom-ident> , <declaration-value>? )"
},
"exp()": {
syntax: "exp( <calc-sum> )"
},
"explicit-track-list": {
syntax: "[ <line-names>? <track-size> ]+ <line-names>?"
},
"family-name": {
syntax: "<string> | <custom-ident>+"
},
"feature-tag-value": {
syntax: "<string> [ <integer> | on | off ]?"
},
"feature-type": {
syntax: "@stylistic | @historical-forms | @styleset | @character-variant | @swash | @ornaments | @annotation"
},
"feature-value-block": {
syntax: "<feature-type> '{' <feature-value-declaration-list> '}'"
},
"feature-value-block-list": {
syntax: "<feature-value-block>+"
},
"feature-value-declaration": {
syntax: "<custom-ident>: <integer>+;"
},
"feature-value-declaration-list": {
syntax: "<feature-value-declaration>"
},
"feature-value-name": {
syntax: "<custom-ident>"
},
"filter-function": {
syntax: "<blur()> | <brightness()> | <contrast()> | <drop-shadow()> | <grayscale()> | <hue-rotate()> | <invert()> | <opacity()> | <saturate()> | <sepia()>"
},
"filter-value-list": {
syntax: "[ <filter-function> | <url> ]+"
},
"final-bg-layer": {
syntax: "<'background-color'> || <bg-image> || <bg-position> [ / <bg-size> ]? || <repeat-style> || <attachment> || <visual-box> || <visual-box>"
},
"fit-content()": {
syntax: "fit-content( <length-percentage [0,∞]> )"
},
"fixed-breadth": {
syntax: "<length-percentage>"
},
"fixed-repeat": {
syntax: "repeat( [ <integer [1,∞]> ] , [ <line-names>? <fixed-size> ]+ <line-names>? )"
},
"fixed-size": {
syntax: "<fixed-breadth> | minmax( <fixed-breadth> , <track-breadth> ) | minmax( <inflexible-breadth> , <fixed-breadth> )"
},
"font-stretch-absolute": {
syntax: "normal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded | <percentage>"
},
"font-variant-css21": {
syntax: "[ normal | small-caps ]"
},
"font-weight-absolute": {
syntax: "normal | bold | <number [1,1000]>"
},
"frequency-percentage": {
syntax: "<frequency> | <percentage>"
},
"general-enclosed": {
syntax: "[ <function-token> <any-value> ) ] | ( <ident> <any-value> )"
},
"generic-family": {
syntax: "serif | sans-serif | cursive | fantasy | monospace"
},
"generic-name": {
syntax: "serif | sans-serif | cursive | fantasy | monospace"
},
"geometry-box": {
syntax: "<shape-box> | fill-box | stroke-box | view-box"
},
gradient: {
syntax: "<linear-gradient()> | <repeating-linear-gradient()> | <radial-gradient()> | <repeating-radial-gradient()> | <conic-gradient()> | <repeating-conic-gradient()>"
},
"grayscale()": {
syntax: "grayscale( [ <number> | <percentage> ]? )"
},
"grid-line": {
syntax: "auto | <custom-ident> | [ <integer> && <custom-ident>? ] | [ span && [ <integer> || <custom-ident> ] ]"
},
"historical-lig-values": {
syntax: "[ historical-ligatures | no-historical-ligatures ]"
},
"hsl()": {
syntax: "hsl( <hue>, <percentage>, <percentage>, <alpha-value>? ) | hsl( [ <hue> | none ] [ <percentage> | <number> | none ] [ <percentage> | <number> | none ] [ / [ <alpha-value> | none ] ]? )"
},
"hsla()": {
syntax: "hsla( <hue>, <percentage>, <percentage>, <alpha-value>? ) | hsla( [ <hue> | none ] [ <percentage> | <number> | none ] [ <percentage> | <number> | none ] [ / [ <alpha-value> | none ] ]? )"
},
hue: {
syntax: "<number> | <angle>"
},
"hue-interpolation-method": {
syntax: "[ shorter | longer | increasing | decreasing ] hue"
},
"hue-rotate()": {
syntax: "hue-rotate( [ <angle> | <zero> ]? )"
},
"hwb()": {
syntax: "hwb( [ <hue> | none ] [ <percentage> | <number> | none ] [ <percentage> | <number> | none ] [ / [ <alpha-value> | none ] ]? )"
},
"hypot()": {
syntax: "hypot( <calc-sum># )"
},
"id-selector": {
syntax: "<hash-token>"
},
integer: {
syntax: "<number-token>"
},
image: {
syntax: "<url> | <image()> | <image-set()> | <element()> | <paint()> | <cross-fade()> | <gradient>"
},
"image()": {
syntax: "image( <image-tags>? [ <image-src>? , <color>? ]! )"
},
"image-set()": {
syntax: "image-set( <image-set-option># )"
},
"image-set-option": {
syntax: "[ <image> | <string> ] [ <resolution> || type(<string>) ]"
},
"image-src": {
syntax: "<url> | <string>"
},
"image-tags": {
syntax: "ltr | rtl"
},
"inflexible-breadth": {
syntax: "<length-percentage> | min-content | max-content | auto"
},
"inset()": {
syntax: "inset( <length-percentage>{1,4} [ round <'border-radius'> ]? )"
},
"invert()": {
syntax: "invert( [ <number> | <percentage> ]? )"
},
"keyframe-block": {
syntax: "<keyframe-selector># {\n <declaration-list>\n}"
},
"keyframe-block-list": {
syntax: "<keyframe-block>+"
},
"keyframe-selector": {
syntax: "from | to | <percentage> | <timeline-range-name> <percentage>"
},
"keyframes-name": {
syntax: "<custom-ident> | <string>"
},
"lab()": {
syntax: "lab( [<percentage> | <number> | none] [ <percentage> | <number> | none] [ <percentage> | <number> | none] [ / [<alpha-value> | none] ]? )"
},
"layer()": {
syntax: "layer( <layer-name> )"
},
"layer-name": {
syntax: "<ident> [ '.' <ident> ]*"
},
"lch()": {
syntax: "lch( [<percentage> | <number> | none] [ <percentage> | <number> | none] [ <hue> | none] [ / [<alpha-value> | none] ]? )"
},
"leader()": {
syntax: "leader( <leader-type> )"
},
"leader-type": {
syntax: "dotted | solid | space | <string>"
},
"length-percentage": {
syntax: "<length> | <percentage>"
},
"light-dark()": {
syntax: "light-dark( <color>, <color> )"
},
"line-name-list": {
syntax: "[ <line-names> | <name-repeat> ]+"
},
"line-names": {
syntax: "'[' <custom-ident>* ']'"
},
"line-style": {
syntax: "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset"
},
"line-width": {
syntax: "<length> | thin | medium | thick"
},
"linear-color-hint": {
syntax: "<length-percentage>"
},
"linear-color-stop": {
syntax: "<color> <color-stop-length>?"
},
"linear-gradient()": {
syntax: "linear-gradient( [ [ <angle> | to <side-or-corner> ] || <color-interpolation-method> ]? , <color-stop-list> )"
},
"log()": {
syntax: "log( <calc-sum>, <calc-sum>? )"
},
"mask-layer": {
syntax: "<mask-reference> || <position> [ / <bg-size> ]? || <repeat-style> || <geometry-box> || [ <geometry-box> | no-clip ] || <compositing-operator> || <masking-mode>"
},
"mask-position": {
syntax: "[ <length-percentage> | left | center | right ] [ <length-percentage> | top | center | bottom ]?"
},
"mask-reference": {
syntax: "none | <image> | <mask-source>"
},
"mask-source": {
syntax: "<url>"
},
"masking-mode": {
syntax: "alpha | luminance | match-source"
},
"matrix()": {
syntax: "matrix( <number>#{6} )"
},
"matrix3d()": {
syntax: "matrix3d( <number>#{16} )"
},
"max()": {
syntax: "max( <calc-sum># )"
},
"media-and": {
syntax: "<media-in-parens> [ and <media-in-parens> ]+"
},
"media-condition": {
syntax: "<media-not> | <media-and> | <media-or> | <media-in-parens>"
},
"media-condition-without-or": {
syntax: "<media-not> | <media-and> | <media-in-parens>"
},
"media-feature": {
syntax: "( [ <mf-plain> | <mf-boolean> | <mf-range> ] )"
},
"media-in-parens": {
syntax: "( <media-condition> ) | <media-feature> | <general-enclosed>"
},
"media-not": {
syntax: "not <media-in-parens>"
},
"media-or": {
syntax: "<media-in-parens> [ or <media-in-parens> ]+"
},
"media-query": {
syntax: "<media-condition> | [ not | only ]? <media-type> [ and <media-condition-without-or> ]?"
},
"media-query-list": {
syntax: "<media-query>#"
},
"media-type": {
syntax: "<ident>"
},
"mf-boolean": {
syntax: "<mf-name>"
},
"mf-name": {
syntax: "<ident>"
},
"mf-plain": {
syntax: "<mf-name> : <mf-value>"
},
"mf-range": {
syntax: "<mf-name> [ '<' | '>' ]? '='? <mf-value>\n| <mf-value> [ '<' | '>' ]? '='? <mf-name>\n| <mf-value> '<' '='? <mf-name> '<' '='? <mf-value>\n| <mf-value> '>' '='? <mf-name> '>' '='? <mf-value>"
},
"mf-value": {
syntax: "<number> | <dimension> | <ident> | <ratio>"
},
"min()": {
syntax: "min( <calc-sum># )"
},
"minmax()": {
syntax: "minmax( [ <length-percentage> | min-content | max-content | auto ] , [ <length-percentage> | <flex> | min-content | max-content | auto ] )"
},
"mod()": {
syntax: "mod( <calc-sum>, <calc-sum> )"
},
"n-dimension": {
syntax: "<dimension-token>"
},
"ndash-dimension": {
syntax: "<dimension-token>"
},
"ndashdigit-dimension": {
syntax: "<dimension-token>"
},
"ndashdigit-ident": {
syntax: "<ident-token>"
},
"name-repeat": {
syntax: "repeat( [ <integer [1,∞]> | auto-fill ], <line-names>+ )"
},
"named-color": {
syntax: "aliceblue | antiquewhite | aqua | aquamarine | azure | beige | bisque | black | blanchedalmond | blue | blueviolet | brown | burlywood | cadetblue | chartreuse | chocolate | coral | cornflowerblue | cornsilk | crimson | 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 | firebrick | floralwhite | forestgreen | fuchsia | gainsboro | ghostwhite | gold | goldenrod | gray | green | greenyellow | grey | honeydew | hotpink | indianred | indigo | ivory | khaki | lavender | lavenderblush | lawngreen | lemonchiffon | lightblue | lightcoral | lightcyan | lightgoldenrodyellow | lightgray | lightgreen | lightgrey | lightpink | lightsalmon | lightseagreen | lightskyblue | lightslategray | lightslategrey | lightsteelblue | lightyellow | lime | limegreen | linen | magenta | maroon | mediumaquamarine | mediumblue | mediumorchid | mediumpurple | mediumseagreen | mediumslateblue | mediumspringgreen | mediumturquoise | mediumvioletred | 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 | seagreen | seashell | sienna | silver | skyblue | slateblue | slategray | slategrey | snow | springgreen | steelblue | tan | teal | thistle | tomato | turquoise | violet | wheat | white | whitesmoke | yellow | yellowgreen"
},
"namespace-prefix": {
syntax: "<ident>"
},
"ns-prefix": {
syntax: "[ <ident-token> | '*' ]? '|'"
},
"number-percentage": {
syntax: "<number> | <percentage>"
},
"numeric-figure-values": {
syntax: "[ lining-nums | oldstyle-nums ]"
},
"numeric-fraction-values": {
syntax: "[ diagonal-fractions | stacked-fractions ]"
},
"numeric-spacing-values": {
syntax: "[ proportional-nums | tabular-nums ]"
},
"offset-path": {
syntax: "<ray()> | <url> | <basic-shape>"
},
"oklab()": {
syntax: "oklab( [ <percentage> | <number> | none] [ <percentage> | <number> | none] [ <percentage> | <number> | none] [ / [<alpha-value> | none] ]? )"
},
"oklch()": {
syntax: "oklch( [ <percentage> | <number> | none] [ <percentage> | <number> | none] [ <hue> | none] [ / [<alpha-value> | none] ]? )"
},
"opacity()": {
syntax: "opacity( [ <number> | <percentage> ]? )"
},
"opacity-value": {
syntax: "<number> | <percentage>"
},
"outline-line-style": {
syntax: "none | dotted | dashed | solid | double | groove | ridge | inset | outset"
},
"outline-radius": {
syntax: "<length> | <percentage>"
},
"overflow-position": {
syntax: "unsafe | safe"
},
"page-body": {
syntax: "<declaration>? [ ; <page-body> ]? | <page-margin-box> <page-body>"
},
"page-margin-box": {
syntax: "<page-margin-box-type> '{' <declaration-list> '}'"
},
"page-margin-box-type": {
syntax: "@top-left-corner | @top-left | @top-center | @top-right | @top-right-corner | @bottom-left-corner | @bottom-left | @bottom-center | @bottom-right | @bottom-right-corner | @left-top | @left-middle | @left-bottom | @right-top | @right-middle | @right-bottom"
},
"page-selector": {
syntax: "<pseudo-page>+ | <ident> <pseudo-page>*"
},
"page-selector-list": {
syntax: "[ <page-selector># ]?"
},
"page-size": {
syntax: "A5 | A4 | A3 | B5 | B4 | JIS-B5 | JIS-B4 | letter | legal | ledger"
},
paint: {
syntax: "none | <color> | <url> [none | <color>]? | context-fill | context-stroke"
},
"paint()": {
syntax: "paint( <ident>, <declaration-value>? )"
},
"paint-box": {
syntax: "<visual-box> | fill-box | stroke-box"
},
"palette-identifier": {
syntax: "<dashed-ident>"
},
"palette-mix()": {
syntax: "palette-mix(<color-interpolation-method> , [ [normal | light | dark | <palette-identifier> | <palette-mix()> ] && <percentage [0,100]>? ]#{2})"
},
"path()": {
syntax: "path( <'fill-rule'>? , <string> )"
},
"perspective()": {
syntax: "perspective( [ <length [0,∞]> | none ] )"
},
"polar-color-space": {
syntax: "hsl | hwb | lch | oklch"
},
"polygon()": {
syntax: "polygon( <'fill-rule'>? , [ <length-percentage> <length-percentage> ]# )"
},
position: {
syntax: "[ [ left | center | right ] || [ top | center | bottom ] | [ left | center | right | <length-percentage> ] [ top | center | bottom | <length-percentage> ]? | [ [ left | right ] <length-percentage> ] && [ [ top | bottom ] <length-percentage> ] ]"
},
"position-area": {
syntax: "[ left | center | right | span-left | span-right | x-start | x-end | span-x-start | span-x-end | x-self-start | x-self-end | span-x-self-start | span-x-self-end | span-all ] || [ top | center | bottom | span-top | span-bottom | y-start | y-end | span-y-start | span-y-end | y-self-start | y-self-end | span-y-self-start | span-y-self-end | span-all ] | [ block-start | center | block-end | span-block-start | span-block-end | span-all ] || [ inline-start | center | inline-end | span-inline-start | span-inline-end | span-all ] | [ self-block-start | center | self-block-end | span-self-block-start | span-self-block-end | span-all ] || [ self-inline-start | center | self-inline-end | span-self-inline-start | span-self-inline-end | span-all ] | [ start | center | end | span-start | span-end | span-all ]{1,2} | [ self-start | center | self-end | span-self-start | span-self-end | span-all ]{1,2}"
},
"pow()": {
syntax: "pow( <calc-sum>, <calc-sum> )"
},
"predefined-rgb": {
syntax: "srgb | srgb-linear | display-p3 | a98-rgb | prophoto-rgb | rec2020"
},
"predefined-rgb-params": {
syntax: "<predefined-rgb> [ <number> | <percentage> | none ]{3}"
},
"pseudo-class-selector": {
syntax: "':' <ident-token> | ':' <function-token> <any-value> ')'"
},
"pseudo-element-selector": {
syntax: "':' <pseudo-class-selector>"
},
"pseudo-page": {
syntax: ": [ left | right | first | blank ]"
},
quote: {
syntax: "open-quote | close-quote | no-open-quote | no-close-quote"
},
"radial-extent": {
syntax: "closest-corner | closest-side | farthest-corner | farthest-side"
},
"radial-gradient()": {
syntax: "radial-gradient( [ <ending-shape> || <size> ]? [ at <position> ]? , <color-stop-list> )"
},
"radial-size": {
syntax: "<radial-extent> | <length [0,∞]> | <length-percentage [0,∞]>{2}"
},
ratio: {
syntax: "<number [0,∞]> [ / <number [0,∞]> ]?"
},
"ray()": {
syntax: "ray( <angle> && <ray-size>? && contain? && [at <position>]? )"
},
"ray-size": {
syntax: "closest-side | closest-corner | farthest-side | farthest-corner | sides"
},
"rectangular-color-space": {
syntax: "srgb | srgb-linear | display-p3 | a98-rgb | prophoto-rgb | rec2020 | lab | oklab | xyz | xyz-d50 | xyz-d65"
},
"relative-selector": {
syntax: "<combinator>? <complex-selector>"
},
"relative-selector-list": {
syntax: "<relative-selector>#"
},
"relative-size": {
syntax: "larger | smaller"
},
"rect()": {
syntax: "rect( [ <length-percentage> | auto ]{4} [ round <'border-radius'> ]? )"
},
"rem()": {
syntax: "rem( <calc-sum>, <calc-sum> )"
},
"repeat-style": {
syntax: "repeat-x | repeat-y | [ repeat | space | round | no-repeat ]{1,2}"
},
"repeating-conic-gradient()": {
syntax: "repeating-conic-gradient( [ from <angle> ]? [ at <position> ]?, <angular-color-stop-list> )"
},
"repeating-linear-gradient()": {
syntax: "repeating-linear-gradient( [ <angle> | to <side-or-corner> ]? , <color-stop-list> )"
},
"repeating-radial-gradient()": {
syntax: "repeating-radial-gradient( [ <ending-shape> || <size> ]? [ at <position> ]? , <color-stop-list> )"
},
"reversed-counter-name": {
syntax: "reversed( <counter-name> )"
},
"rgb()": {
syntax: "rgb( <percentage>#{3} , <alpha-value>? ) | rgb( <number>#{3} , <alpha-value>? ) | rgb( [ <number> | <percentage> | none ]{3} [ / [ <alpha-value> | none ] ]? )"
},
"rgba()": {
syntax: "rgba( <percentage>#{3} , <alpha-value>? ) | rgba( <number>#{3} , <alpha-value>? ) | rgba( [ <number> | <percentage> | none ]{3} [ / [ <alpha-value> | none ] ]? )"
},
"rotate()": {
syntax: "rotate( [ <angle> | <zero> ] )"
},
"rotate3d()": {
syntax: "rotate3d( <number> , <number> , <number> , [ <angle> | <zero> ] )"
},
"rotateX()": {
syntax: "rotateX( [ <angle> | <zero> ] )"
},
"rotateY()": {
syntax: "rotateY( [ <angle> | <zero> ] )"
},
"rotateZ()": {
syntax: "rotateZ( [ <angle> | <zero> ] )"
},
"round()": {
syntax: "round( <rounding-strategy>?, <calc-sum>, <calc-sum> )"
},
"rounding-strategy": {
syntax: "nearest | up | down | to-zero"
},
"saturate()": {
syntax: "saturate( [ <number> | <percentage> ]? )"
},
"scale()": {
syntax: "scale( [ <number> | <percentage> ]#{1,2} )"
},
"scale3d()": {
syntax: "scale3d( [ <number> | <percentage> ]#{3} )"
},
"scaleX()": {
syntax: "scaleX( [ <number> | <percentage> ] )"
},
"scaleY()": {
syntax: "scaleY( [ <number> | <percentage> ] )"
},
"scaleZ()": {
syntax: "scaleZ( [ <number> | <percentage> ] )"
},
"scope-end": {
syntax: "<selector-list>"
},
"scope-start": {
syntax: "<selector-list>"
},
"scroll()": {
syntax: "scroll( [ <scroller> || <axis> ]? )"
},
scroller: {
syntax: "root | nearest | self"
},
"selector-list": {
syntax: "<complex-selector-list>"
},
"self-position": {
syntax: "center | start | end | self-start | self-end | flex-start | flex-end"
},
"sepia()": {
syntax: "sepia( [ <number> | <percentage> ]? )"
},
shadow: {
syntax: "inset? && <length>{2,4} && <color>?"
},
"shadow-t": {
syntax: "[ <length>{2,3} && <color>? ]"
},
shape: {
syntax: "rect(<top>, <right>, <bottom>, <left>)"
},
"shape-box": {
syntax: "<visual-box> | margin-box"
},
"side-or-corner": {
syntax: "[ left | right ] || [ top | bottom ]"
},
"sign()": {
syntax: "sign( <calc-sum> )"
},
"signed-integer": {
syntax: "<number-token>"
},
"signless-integer": {
syntax: "<number-token>"
},
"sin()": {
syntax: "sin( <calc-sum> )"
},
"single-animation": {
syntax: "<'animation-duration'> || <easing-function> || <'animation-delay'> || <single-animation-iteration-count> || <single-animation-direction> || <single-animation-fill-mode> || <single-animation-play-state> || [ none | <keyframes-name> ] || <single-animation-timeline>"
},
"single-animation-composition": {
syntax: "replace | add | accumulate"
},
"single-animation-direction": {
syntax: "normal | reverse | alternate | alternate-reverse"
},
"single-animation-fill-mode": {
syntax: "none | forwards | backwards | both"
},
"single-animation-iteration-count": {
syntax: "infinite | <number>"
},
"single-animation-play-state": {
syntax: "running | paused"
},
"single-animation-timeline": {
syntax: "auto | none | <dashed-ident> | <scroll()> | <view()>"
},
"single-transition": {
syntax: "[ none | <single-transition-property> ] || <time> || <easing-function> || <time> || <transition-behavior-value>"
},
"single-transition-property": {
syntax: "all | <custom-ident>"
},
size: {
syntax: "closest-side | farthest-side | closest-corner | farthest-corner | <length> | <length-percentage>{2}"
},
"skew()": {
syntax: "skew( [ <angle> | <zero> ] , [ <angle> | <zero> ]? )"
},
"skewX()": {
syntax: "skewX( [ <angle> | <zero> ] )"
},
"skewY()": {
syntax: "skewY( [ <angle> | <zero> ] )"
},
"sqrt()": {
syntax: "sqrt( <calc-sum> )"
},
"step-position": {
syntax: "jump-start | jump-end | jump-none | jump-both | start | end"
},
"step-timing-function": {
syntax: "step-start | step-end | steps(<integer>[, <step-position>]?)"
},
"subclass-selector": {
syntax: "<id-selector> | <class-selector> | <attribute-selector> | <pseudo-class-selector>"
},
"supports-condition": {
syntax: "not <supports-in-parens> | <supports-in-parens> [ and <supports-in-parens> ]* | <supports-in-parens> [ or <supports-in-parens> ]*"
},
"supports-decl": {
syntax: "( <declaration> )"
},
"supports-feature": {
syntax: "<supports-decl> | <supports-selector-fn>"
},
"supports-in-parens": {
syntax: "( <supports-condition> ) | <supports-feature> | <general-enclosed>"
},
"supports-selector-fn": {
syntax: "selector( <complex-selector> )"
},
symbol: {
syntax: "<string> | <image> | <custom-ident>"
},
"symbols()": {
syntax: "symbols( <symbols-type>? [ <string> | <image> ]+ )"
},
"symbols-type": {
syntax: "cyclic | numeric | alphabetic | symbolic | fixed"
},
"system-color": {
syntax: "AccentColor | AccentColorText | ActiveText | ButtonBorder | ButtonFace | ButtonText | Canvas | CanvasText | Field | FieldText | GrayText | Highlight | HighlightText | LinkText | Mark | MarkText | SelectedItem | SelectedItemText | VisitedText"
},
"tan()": {
syntax: "tan( <calc-sum> )"
},
target: {
syntax: "<target-counter()> | <target-counters()> | <target-text()>"
},
"target-counter()": {
syntax: "target-counter( [ <string> | <url> ] , <custom-ident> , <counter-style>? )"
},
"target-counters()": {
syntax: "target-counters( [ <string> | <url> ] , <custom-ident> , <string> , <counter-style>? )"
},
"target-text()": {
syntax: "target-text( [ <string> | <url> ] , [ content | before | after | first-letter ]? )"
},
"text-edge": {
syntax: "[ text | cap | ex | ideographic | ideographic-ink ] [ text | alphabetic | ideographic | ideographic-ink ]?"
},
"time-percentage": {
syntax: "<time> | <percentage>"
},
"timeline-range-name": {
syntax: "cover | contain | entry | exit | entry-crossing | exit-crossing"
},
"track-breadth": {
syntax: "<length-percentage> | <flex> | min-content | max-content | auto"
},
"track-list": {
syntax: "[ <line-names>? [ <track-size> | <track-repeat> ] ]+ <line-names>?"
},
"track-repeat": {
syntax: "repeat( [ <integer [1,∞]> ] , [ <line-names>? <track-size> ]+ <line-names>? )"
},
"track-size": {
syntax: "<track-breadth> | minmax( <inflexible-breadth> , <track-breadth> ) | fit-content( <length-percentage> )"
},
"transform-function": {
syntax: "<matrix()> | <translate()> | <translateX()> | <translateY()> | <scale()> | <scaleX()> | <scaleY()> | <rotate()> | <skew()> | <skewX()> | <skewY()> | <matrix3d()> | <translate3d()> | <translateZ()> | <scale3d()> | <scaleZ()> | <rotate3d()> | <rotateX()> | <rotateY()> | <rotateZ()> | <perspective()>"
},
"transform-list": {
syntax: "<transform-function>+"
},
"transition-behavior-value": {
syntax: "normal | allow-discrete"
},
"translate()": {
syntax: "translate( <length-percentage> , <length-percentage>? )"
},
"translate3d()": {
syntax: "translate3d( <length-percentage> , <length-percentage> , <length> )"
},
"translateX()": {
syntax: "translateX( <length-percentage> )"
},
"translateY()": {
syntax: "translateY( <length-percentage> )"
},
"translateZ()": {
syntax: "translateZ( <length> )"
},
"try-size": {
syntax: "most-width | most-height | most-block-size | most-inline-size"
},
"try-tactic": {
syntax: "flip-block || flip-inline || flip-start"
},
"type-or-unit": {
syntax: "string | color | url | integer | number | length | angle | time | frequency | cap | ch | em | ex | ic | lh | rlh | rem | vb | vi | vw | vh | vmin | vmax | mm | Q | cm | in | pt | pc | px | deg | grad | rad | turn | ms | s | Hz | kHz | %"
},
"type-selector": {
syntax: "<wq-name> | <ns-prefix>? '*'"
},
"var()": {
syntax: "var( <custom-property-name> , <declaration-value>? )"
},
"view()": {
syntax: "view([<axis> || <'view-timeline-inset'>]?)"
},
"viewport-length": {
syntax: "auto | <length-percentage>"
},
"visual-box": {
syntax: "content-box | padding-box | border-box"
},
"wq-name": {
syntax: "<ns-prefix>? <ident-token>"
},
"xywh()": {
syntax: "xywh( <length-percentage>{2} <length-percentage [0,∞]>{2} [ round <'border-radius'> ]? )"
},
xyz: {
syntax: "xyz | xyz-d50 | xyz-d65"
},
"xyz-params": {
syntax: "<xyz> [ <number> | <percentage> | none ]{3}"
}
};
var selectors = {
":active": {
syntax: ":active"
},
":active-view-transition": {
syntax: ":active-view-transition"
},
":active-view-transition-type()": {
syntax: ":active-view-transition-type( <custom-ident># )"
},
":any-link": {
syntax: ":any-link"
},
":autofill": {
syntax: ":autofill"
},
":blank": {
syntax: ":blank"
},
":buffering": {
syntax: ":buffering"
},
":checked": {
syntax: ":checked"
},
":current": {
syntax: ":current"
},
":default": {
syntax: ":default"
},
":defined": {
syntax: ":defined"
},
":dir()": {
syntax: ":dir( [ ltr | rtl ] )"
},
":disabled": {
syntax: ":disabled"
},
":empty": {
syntax: ":empty"
},
":enabled": {
syntax: ":enabled"
},
":first": {
syntax: ":first"
},
":first-child": {
syntax: ":first-child"
},
":first-of-type": {
syntax: ":first-of-type"
},
":focus": {
syntax: ":focus"
},
":focus-visible": {
syntax: ":focus-visible"
},
":focus-within": {
syntax: ":focus-within"
},
":fullscreen": {
syntax: ":fullscreen"
},
":future": {
syntax: ":future"
},
":has()": {
syntax: ":has( <forgiving-relative-selector-list> )"
},
":has-slotted": {
syntax: ":has-slotted"
},
":host": {
syntax: ":host"
},
":host()": {
syntax: ":host( <compound-selector> )"
},
":host-context()": {
syntax: ":host-context( <compound-selector> )"
},
":hover": {
syntax: ":hover"
},
":in-range": {
syntax: ":in-range"
},
":indeterminate": {
syntax: ":indeterminate"
},
":invalid": {
syntax: ":invalid"
},
":is()": {
syntax: ":is( <forgiving-selector-list> )"
},
":lang()": {
syntax: ":lang( <language-code> )"
},
":last-child": {
syntax: ":last-child"
},
":last-of-type": {
syntax: ":last-of-type"
},
":left": {
syntax: ":left"
},
":link": {
syntax: ":link"
},
":local-link": {
syntax: ":local-link"
},
":modal": {
syntax: ":modal"
},
":muted": {
syntax: ":muted"
},
":not()": {
syntax: ":not( <complex-selector-list> )"
},
":nth-child()": {
syntax: ":nth-child( <an+b> [ of <complex-selector-list> ]? )"
},
":nth-last-child()": {
syntax: ":nth-last-child( <an+b> [ of <complex-selector-list> ]? )"
},
":nth-last-of-type()": {
syntax: ":nth-last-of-type( <an+b> )"
},
":nth-of-type()": {
syntax: ":nth-of-type( <an+b> )"
},
":only-child": {
syntax: ":only-child"
},
":only-of-type": {
syntax: ":only-of-type"
},
":optional": {
syntax: ":optional"
},
":out-of-range": {
syntax: ":out-of-range"
},
":past": {
syntax: ":past"
},
":paused": {
syntax: ":paused"
},
":picture-in-picture": {
syntax: ":picture-in-picture"
},
":placeholder-shown": {
syntax: ":placeholder-shown"
},
":playing": {
syntax: ":playing"
},
":popover-open": {
syntax: ":popover-open"
},
":read-only": {
syntax: ":read-only"
},
":read-write": {
syntax: ":read-write"
},
":required": {
syntax: ":required"
},
":right": {
syntax: ":right"
},
":root": {
syntax: ":root"
},
":scope": {
syntax: ":scope"
},
":seeking": {
syntax: ":seeking"
},
":stalled": {
syntax: ":stalled"
},
":state()": {
syntax: ":state( <custom-ident> )"
},
":target": {
syntax: ":target"
},
":target-within": {
syntax: ":target-within"
},
":user-invalid": {
syntax: ":user-invalid"
},
":user-valid": {
syntax: ":user-valid"
},
":valid": {
syntax: ":valid"
},
":visited": {
syntax: ":visited"
},
":volume-locked": {
syntax: ":volume-locked"
},
":where()": {
syntax: ":where( <complex-selector-list> )"
},
":xr-overlay": {
syntax: ":xr-overlay"
},
"::-ms-browse": {
syntax: "::-ms-browse"
},
"::-ms-check": {
syntax: "::-ms-check"
},
"::-ms-clear": {
syntax: "::-ms-clear"
},
"::-ms-expand": {
syntax: "::-ms-expand"
},
"::-ms-fill": {
syntax: "::-ms-fill"
},
"::-ms-fill-lower": {
syntax: "::-ms-fill-lower"
},
"::-ms-fill-upper": {
syntax: "::-ms-fill-upper"
},
"::-ms-reveal": {
syntax: "::-ms-reveal"
},
"::-ms-thumb": {
syntax: "::-ms-thumb"
},
"::-ms-ticks-after": {
syntax: "::-ms-ticks-after"
},
"::-ms-ticks-before": {
syntax: "::-ms-ticks-before"
},
"::-ms-tooltip": {
syntax: "::-ms-tooltip"
},
"::-ms-track": {
syntax: "::-ms-track"
},
"::-ms-value": {
syntax: "::-ms-value"
},
"::-moz-progress-bar": {
syntax: "::-moz-progress-bar"
},
"::-moz-range-progress": {
syntax: "::-moz-range-progress"
},
"::-moz-range-thumb": {
syntax: "::-moz-range-thumb"
},
"::-moz-range-track": {
syntax: "::-moz-range-track"
},
"::-webkit-progress-bar": {
syntax: "::-webkit-progress-bar"
},
"::-webkit-progress-inner-value": {
syntax: "::-webkit-progress-inner-value"
},
"::-webkit-progress-value": {
syntax: "::-webkit-progress-value"
},
"::-webkit-slider-runnable-track": {
syntax: "::-webkit-slider-runnable-track"
},
"::-webkit-slider-thumb": {
syntax: "::-webkit-slider-thumb"
},
"::after": {
syntax: "::after"
},
"::backdrop": {
syntax: "::backdrop"
},
"::before": {
syntax: "::before"
},
"::cue": {
syntax: "::cue"
},
"::cue()": {
syntax: "::cue( <selector> )"
},
"::cue-region": {
syntax: "::cue-region"
},
"::cue-region()": {
syntax: "::cue-region( <selector> )"
},
"::details-content": {
syntax: "::details-content"
},
"::file-selector-button": {
syntax: "::file-selector-button"
},
"::first-letter": {
syntax: "::first-letter"
},
"::first-line": {
syntax: "::first-line"
},
"::grammar-error": {
syntax: "::grammar-error"
},
"::highlight()": {
syntax: "::highlight( <custom-ident> )"
},
"::marker": {
syntax: "::marker"
},
"::part()": {
syntax: "::part( <ident>+ )"
},
"::placeholder": {
syntax: "::placeholder"
},
"::selection": {
syntax: "::selection"
},
"::slotted()": {
syntax: "::slotted( <compound-selector> )"
},
"::spelling-error": {
syntax: "::spelling-error"
},
"::target-text": {
syntax: "::target-text"
},
"::view-transition": {
syntax: "::view-transition"
},
"::view-transition-group()": {
syntax: "::view-transition-group([ '*' | <custom-ident> ])"
},
"::view-transition-image-pair()": {
syntax: "::view-transition-image-pair([ '*' | <custom-ident> ])"
},
"::view-transition-new()": {
syntax: "::view-transition-new([ '*' | <custom-ident> ])"
},
"::view-transition-old()": {
syntax: "::view-transition-old([ '*' | <custom-ident> ])"
}
};
var atRules = {
"@charset": {
syntax: "@charset \"<charset>\";"
},
"@counter-style": {
syntax: "@counter-style <counter-style-name> {\n [ system: <counter-system>; ] ||\n [ symbols: <counter-symbols>; ] ||\n [ additive-symbols: <additive-symbols>; ] ||\n [ negative: <negative-symbol>; ] ||\n [ prefix: <prefix>; ] ||\n [ suffix: <suffix>; ] ||\n [ range: <range>; ] ||\n [ pad: <padding>; ] ||\n [ speak-as: <speak-as>; ] ||\n [ fallback: <counter-style-name>; ]\n}",
descriptors: {
"additive-symbols": {
syntax: "[ <integer> && <symbol> ]#"
},
fallback: {
syntax: "<counter-style-name>"
},
negative: {
syntax: "<symbol> <symbol>?"
},
pad: {
syntax: "<integer> && <symbol>"
},
prefix: {
syntax: "<symbol>"
},
range: {
syntax: "[ [ <integer> | infinite ]{2} ]# | auto"
},
"speak-as": {
syntax: "auto | bullets | numbers | words | spell-out | <counter-style-name>"
},
suffix: {
syntax: "<symbol>"
},
symbols: {
syntax: "<symbol>+"
},
system: {
syntax: "cyclic | numeric | alphabetic | symbolic | additive | [ fixed <integer>? ] | [ extends <counter-style-name> ]"
}
}
},
"@document": {
syntax: "@document [ <url> | url-prefix(<string>) | domain(<string>) | media-document(<string>) | regexp(<string>) ]# {\n <group-rule-body>\n}"
},
"@font-face": {
syntax: "@font-face {\n [ font-family: <family-name>; ] ||\n [ src: <src>; ] ||\n [ unicode-range: <unicode-range>; ] ||\n [ font-variant: <font-variant>; ] ||\n [ font-feature-settings: <font-feature-settings>; ] ||\n [ font-variation-settings: <font-variation-settings>; ] ||\n [ font-stretch: <font-stretch>; ] ||\n [ font-weight: <font-weight>; ] ||\n [ font-style: <font-style>; ] ||\n [ size-adjust: <size-adjust>; ] ||\n [ ascent-override: <ascent-override>; ] ||\n [ descent-override: <descent-override>; ] ||\n [ line-gap-override: <line-gap-override>; ]\n}",
descriptors: {
"ascent-override": {
syntax: "normal | <percentage>"
},
"descent-override": {
syntax: "normal | <percentage>"
},
"font-display": {
syntax: "auto | block | swap | fallback | optional"
},
"font-family": {
syntax: "<family-name>"
},
"font-feature-settings": {
syntax: "normal | <feature-tag-value>#"
},
"font-stretch": {
syntax: "<font-stretch-absolute>{1,2}"
},
"font-style": {
syntax: "normal | italic | oblique <angle>{0,2}"
},
"font-variation-settings": {
syntax: "normal | [ <string> <number> ]#"
},
"font-weight": {
syntax: "<font-weight-absolute>{1,2}"
},
"line-gap-override": {
syntax: "normal | <percentage>"
},
"size-adjust": {
syntax: "<percentage>"
},
src: {
syntax: "[ <url> [ format( <string># ) ]? | local( <family-name> ) ]#"
},
"unicode-range": {
syntax: "<unicode-range-token>#"
}
}
},
"@font-feature-values": {
syntax: "@font-feature-values <family-name># {\n <feature-value-block-list>\n}"
},
"@font-palette-values": {
syntax: "@font-palette-values <dashed-ident> {\n <declaration-list>\n}",
descriptors: {
"base-palette": {
syntax: "light | dark | <integer [0,∞]>"
},
"font-family": {
syntax: "<family-name>#"
},
"override-colors": {
syntax: "[ <integer [0,∞]> <color> ]#"
}
}
},
"@import": {
syntax: "@import [ <string> | <url> ]\n [ layer | layer(<layer-name>) ]?\n [ supports( [ <supports-condition> | <declaration> ] ) ]?\n <media-query-list>? ;"
},
"@keyframes": {
syntax: "@keyframes <keyframes-name> {\n <keyframe-block-list>\n}"
},
"@layer": {
syntax: "@layer [ <layer-name># | <layer-name>? {\n <stylesheet>\n} ]"
},
"@media": {
syntax: "@media <media-query-list> {\n <group-rule-body>\n}"
},
"@namespace": {
syntax: "@namespace <namespace-prefix>? [ <string> | <url> ];"
},
"@page": {
syntax: "@page <page-selector-list> {\n <page-body>\n}",
descriptors: {
bleed: {
syntax: "auto | <length>"
},
marks: {
syntax: "none | [ crop || cross ]"
},
"page-orientation": {
syntax: "upright | rotate-left | rotate-right "
},
size: {
syntax: "<length>{1,2} | auto | [ <page-size> || [ portrait | landscape ] ]"
}
}
},
"@position-try": {
syntax: "@position-try <dashed-ident> {\n <declaration-list>\n}"
},
"@property": {
syntax: "@property <custom-property-name> {\n <declaration-list>\n}",
descriptors: {
inherits: {
syntax: "true | false"
},
"initial-value": {
syntax: "<declaration-value>?"
},
syntax: {
syntax: "<string>"
}
}
},
"@scope": {
syntax: "@scope [(<scope-start>)]? [to (<scope-end>)]? {\n <rule-list>\n}"
},
"@starting-style": {
syntax: "@starting-style {\n <declaration-list> | <group-rule-body>\n}"
},
"@supports": {
syntax: "@supports <supports-condition> {\n <group-rule-body>\n}"
},
"@view-transition": {
syntax: "@view-transition {\n <declaration-list>\n}",
descriptors: {
navigation: {
syntax: "auto | none"
},
types: {
syntax: "none | <custom-ident>+"
}
}
}
};
var config$2 = {
declarations: declarations,
functions: functions,
syntaxes: syntaxes,
selectors: selectors,
atRules: atRules
};
var ValidationTokenEnum;
(function (ValidationTokenEnum) {
ValidationTokenEnum[ValidationTokenEnum["Root"] = 0] = "Root";
ValidationTokenEnum[ValidationTokenEnum["Keyword"] = 1] = "Keyword";
ValidationTokenEnum[ValidationTokenEnum["PropertyType"] = 2] = "PropertyType";
ValidationTokenEnum[ValidationTokenEnum["DeclarationType"] = 3] = "DeclarationType";
ValidationTokenEnum[ValidationTokenEnum["AtRule"] = 4] = "AtRule";
ValidationTokenEnum[ValidationTokenEnum["ValidationFunctionDefinition"] = 5] = "ValidationFunctionDefinition";
ValidationTokenEnum[ValidationTokenEnum["OpenBracket"] = 6] = "OpenBracket";
ValidationTokenEnum[ValidationTokenEnum["CloseBracket"] = 7] = "CloseBracket";
ValidationTokenEnum[ValidationTokenEnum["OpenParenthesis"] = 8] = "OpenParenthesis";
ValidationTokenEnum[ValidationTokenEnum["CloseParenthesis"] = 9] = "CloseParenthesis";
ValidationTokenEnum[ValidationTokenEnum["Comma"] = 10] = "Comma";
ValidationTokenEnum[ValidationTokenEnum["Pipe"] = 11] = "Pipe";
ValidationTokenEnum[ValidationTokenEnum["Column"] = 12] = "Column";
ValidationTokenEnum[ValidationTokenEnum["Star"] = 13] = "Star";
ValidationTokenEnum[ValidationTokenEnum["OpenCurlyBrace"] = 14] = "OpenCurlyBrace";
ValidationTokenEnum[ValidationTokenEnum["CloseCurlyBrace"] = 15] = "CloseCurlyBrace";
ValidationTokenEnum[ValidationTokenEnum["HashMark"] = 16] = "HashMark";
ValidationTokenEnum[ValidationTokenEnum["QuestionMark"] = 17] = "QuestionMark";
ValidationTokenEnum[ValidationTokenEnum["Function"] = 18] = "Function";
ValidationTokenEnum[ValidationTokenEnum["Number"] = 19] = "Number";
ValidationTokenEnum[ValidationTokenEnum["Whitespace"] = 20] = "Whitespace";
ValidationTokenEnum[ValidationTokenEnum["Parenthesis"] = 21] = "Parenthesis";
ValidationTokenEnum[ValidationTokenEnum["Bracket"] = 22] = "Bracket";
ValidationTokenEnum[ValidationTokenEnum["Block"] = 23] = "Block";
ValidationTokenEnum[ValidationTokenEnum["AtLeastOnce"] = 24] = "AtLeastOnce";
ValidationTokenEnum[ValidationTokenEnum["Separator"] = 25] = "Separator";
ValidationTokenEnum[ValidationTokenEnum["Exclamation"] = 26] = "Exclamation";
ValidationTokenEnum[ValidationTokenEnum["Ampersand"] = 27] = "Ampersand";
ValidationTokenEnum[ValidationTokenEnum["PipeToken"] = 28] = "PipeToken";
ValidationTokenEnum[ValidationTokenEnum["ColumnToken"] = 29] = "ColumnToken";
ValidationTokenEnum[ValidationTokenEnum["AmpersandToken"] = 30] = "AmpersandToken";
ValidationTokenEnum[ValidationTokenEnum["Parens"] = 31] = "Parens";
ValidationTokenEnum[ValidationTokenEnum["PseudoClassToken"] = 32] = "PseudoClassToken";
ValidationTokenEnum[ValidationTokenEnum["PseudoClassFunctionToken"] = 33] = "PseudoClassFunctionToken";
ValidationTokenEnum[ValidationTokenEnum["StringToken"] = 34] = "StringToken";
ValidationTokenEnum[ValidationTokenEnum["AtRuleDefinition"] = 35] = "AtRuleDefinition";
ValidationTokenEnum[ValidationTokenEnum["DeclarationNameToken"] = 36] = "DeclarationNameToken";
ValidationTokenEnum[ValidationTokenEnum["DeclarationDefinitionToken"] = 37] = "DeclarationDefinitionToken";
ValidationTokenEnum[ValidationTokenEnum["SemiColon"] = 38] = "SemiColon";
ValidationTokenEnum[ValidationTokenEnum["Character"] = 39] = "Character";
ValidationTokenEnum[ValidationTokenEnum["ColumnArrayToken"] = 40] = "ColumnArrayToken";
})(ValidationTokenEnum || (ValidationTokenEnum = {}));
var ValidationSyntaxGroupEnum;
(function (ValidationSyntaxGroupEnum) {
ValidationSyntaxGroupEnum["Declarations"] = "declarations";
ValidationSyntaxGroupEnum["Functions"] = "functions";
ValidationSyntaxGroupEnum["Syntaxes"] = "syntaxes";
ValidationSyntaxGroupEnum["Selectors"] = "selectors";
ValidationSyntaxGroupEnum["AtRules"] = "atRules";
})(ValidationSyntaxGroupEnum || (ValidationSyntaxGroupEnum = {}));
var WalkValidationTokenEnum;
(function (WalkValidationTokenEnum) {
WalkValidationTokenEnum[WalkValidationTokenEnum["IgnoreChildren"] = 0] = "IgnoreChildren";
WalkValidationTokenEnum[WalkValidationTokenEnum["IgnoreNode"] = 1] = "IgnoreNode";
WalkValidationTokenEnum[WalkValidationTokenEnum["IgnoreAll"] = 2] = "IgnoreAll";
})(WalkValidationTokenEnum || (WalkValidationTokenEnum = {}));
var WalkValidationTokenKeyTypeEnum;
(function (WalkValidationTokenKeyTypeEnum) {
WalkValidationTokenKeyTypeEnum["Array"] = "array";
WalkValidationTokenKeyTypeEnum["Children"] = "chi";
WalkValidationTokenKeyTypeEnum["Left"] = "l";
WalkValidationTokenKeyTypeEnum["Right"] = "r";
WalkValidationTokenKeyTypeEnum["Prelude"] = "prelude";
})(WalkValidationTokenKeyTypeEnum || (WalkValidationTokenKeyTypeEnum = {}));
const skipped = [
ValidationTokenEnum.Star,
ValidationTokenEnum.HashMark,
ValidationTokenEnum.AtLeastOnce,
ValidationTokenEnum.Exclamation,
ValidationTokenEnum.QuestionMark,
ValidationTokenEnum.OpenCurlyBrace
];
const objectProperties = {
enumerable: false,
writable: true,
configurable: true
};
// syntaxes: keyword | <'property'> | <function>
// "none | [ [<dashed-ident> || <try-tactic>] | inset-area( <'inset-area'> ) ]#"
// ""
// : "<outline-radius>{1,4} [ / <outline-radius>{1,4} ]?
// ""
// false | true
// [ <mask-reference> || <position> [ / <bg-size> ]? || <repeat-style> || [ <box> | border | padding | content | text ] || [ <box> | border | padding | content ] ]#
// false | true | green | pipe
// keyword | <'property'> | <function>
// [<dashed-ident> || <try-tactic>]
// [ <mask-reference> || <position> [ / <bg-size> ]? || <repeat-style> || [ <box> | border | padding | content | text ] || [ <box> | border | padding | content ] ]#
// none | [ [<dashed-ident> || <try-tactic>] | inset-area( <'inset-area'> ) ]
function* tokenize(syntax, position = { ind: 0, lin: 1, col: 0 }, currentPosition = {
ind: -1,
lin: 1,
col: 0
}) {
let i = -1;
let buffer = '';
while (++i < syntax.length) {
let chr = syntax.charAt(i);
move(currentPosition, chr);
switch (chr) {
case '\\':
if (buffer.length > 0) {
yield getTokenType$1(buffer, position, currentPosition);
buffer = '';
}
buffer += chr;
chr = syntax.charAt(++i);
buffer += chr;
move(currentPosition, chr);
break;
case ';':
if (buffer.length > 0) {
yield getTokenType$1(buffer, position, currentPosition);
buffer = '';
}
yield getTokenType$1(chr, position, currentPosition);
buffer = '';
break;
case ':':
if (isIdent(buffer)) {
yield Object.defineProperty({
typ: ValidationTokenEnum.DeclarationNameToken,
val: buffer
}, 'pos', { ...objectProperties, value: { ...position } });
buffer = '';
move(currentPosition, chr);
break;
}
buffer += chr;
break;
case '"':
case "'":
if (buffer.length > 0) {
yield getTokenType$1(buffer, position, currentPosition);
buffer = '';
}
buffer += chr;
while (i + 1 < syntax.length) {
chr = syntax.charAt(++i);
buffer += chr;
move(currentPosition, chr);
if (chr == '\\') {
chr = syntax.charAt(++i);
buffer += chr;
move(currentPosition, chr);
continue;
}
if (chr == buffer.charAt(0)) {
break;
}
}
// check for type "<property>" or "<'property'>"
if (buffer.at(1) == '<' && buffer.at(-2) == '>') {
yield Object.defineProperty({
typ: ValidationTokenEnum.Character,
val: chr
}, 'pos', { ...objectProperties, value: { ...position } });
position = { ...currentPosition };
move(currentPosition, chr);
buffer = buffer.slice(1, -1);
yield* tokenize(buffer, position, currentPosition);
yield Object.defineProperty({
typ: ValidationTokenEnum.Character,
val: chr
}, 'pos', { ...objectProperties, value: { ...position } });
position = { ...currentPosition };
move(currentPosition, chr);
buffer = '';
break;
}
yield getTokenType$1(buffer, position, currentPosition);
buffer = '';
break;
case '<':
buffer += chr;
while (i + 1 < syntax.length) {
chr = syntax.charAt(++i);
buffer += chr;
move(currentPosition, chr);
if (chr == '>') {
break;
}
}
yield getTokenType$1(buffer, position, currentPosition);
buffer = '';
break;
case ' ':
case '\t':
case '\n':
case '\r':
case '\f':
case '|':
case '#':
case '+':
case ',':
case '[':
case ']':
case '(':
case ')':
case '*':
case '{':
case '}':
case '?':
case '!':
case '&':
if (buffer.length > 0) {
yield getTokenType$1(buffer, position, currentPosition);
}
if (chr == '|' || chr == '&') {
if (syntax.charAt(i + 1) == chr) {
move(currentPosition, chr);
yield getTokenType$1(chr + chr, position, currentPosition);
i++;
buffer = '';
continue;
}
}
Object.assign(position, currentPosition);
yield getTokenType$1(chr, position, currentPosition);
buffer = '';
break;
default:
buffer += chr;
break;
}
}
if (buffer.length > 0) {
yield getTokenType$1(buffer, position, currentPosition);
}
}
function columnCallback(token, parent, key) {
if (key == WalkValidationTokenKeyTypeEnum.Prelude) {
return WalkValidationTokenEnum.IgnoreAll;
}
if (token.typ == ValidationTokenEnum.ColumnToken || token.typ == ValidationTokenEnum.Whitespace) {
return WalkValidationTokenEnum.IgnoreNode;
}
return WalkValidationTokenEnum.IgnoreChildren;
}
function toColumnArray(ast, parent) {
const result = new Map;
// @ts-ignore
for (const { token } of walkValidationToken(ast, null, columnCallback)) {
result.set(JSON.stringify(token), token);
}
const node = {
typ: ValidationTokenEnum.ColumnArrayToken,
chi: [...result.values()]
};
if (parent != null) {
replaceNode(parent, ast, node);
}
return node;
}
function replaceNode(parent, target, node) {
if ('l' in parent && parent.l == target) {
parent.l = node;
}
if ('r' in parent && parent.r == target) {
parent.r = node;
}
if ('chi' in parent) {
// @ts-ignore
for (let i = 0; i < parent.chi.length; i++) {
// @ts-ignore
if (parent.chi[i] == target) {
// @ts-ignore
parent.chi[i] = node;
break;
}
}
}
}
function transform$1(context) {
for (const { token, parent } of walkValidationToken(context)) {
switch (token.typ) {
case ValidationTokenEnum.ColumnToken:
toColumnArray(token, parent);
break;
}
}
return context;
}
function parseSyntax(syntax) {
const root = Object.defineProperty({
typ: ValidationTokenEnum.Root,
chi: []
}, 'pos', { ...objectProperties, value: { ind: 0, lin: 1, col: 0 } });
// return minify(doParseSyntax(syntaxes, tokenize(syntaxes), root)) as ValidationRootToken;
return minify$1(transform$1(doParseSyntax(syntax, tokenize(syntax), root)));
}
function matchParens(syntax, iterator) {
let item;
let func = null;
let items = [];
let match = 0;
while ((item = iterator.next()) && !item.done) {
switch (item.value.typ) {
case ValidationTokenEnum.OpenParenthesis:
if (match > 0) {
func.chi.push(item.value);
}
else if (match == 0) {
func = items.at(-1);
if (func == null) {
func = Object.defineProperty({
typ: ValidationTokenEnum.Parens,
val: '',
chi: []
}, 'pos', { ...objectProperties, value: item.value.pos });
items.push(func);
}
else {
// @ts-ignore
func.typ = func.typ == ValidationTokenEnum.PseudoClassToken ? ValidationTokenEnum.PseudoClassFunctionToken : ValidationTokenEnum.Function;
func.chi = [];
}
}
match++;
break;
case ValidationTokenEnum.CloseParenthesis:
match--;
if (match > 0) {
func.chi.push(item.value);
}
break;
default:
if (match > 0) {
func.chi.push(item.value);
}
else {
items.push(item.value);
}
break;
}
}
for (const item of items) {
if ('chi' in item) {
// @ts-ignore
item.chi = matchParens(syntax, item.chi[Symbol.iterator]());
}
}
return items;
}
function matchBrackets(syntax, iterator) {
let item;
let bracket = null;
let items = [];
let match = 0;
while ((item = iterator.next()) && !item.done) {
switch (item.value.typ) {
case ValidationTokenEnum.OpenBracket:
if (match > 0) {
bracket.chi.push(item.value);
}
else if (match == 0) {
bracket = Object.defineProperty({
typ: ValidationTokenEnum.Bracket,
chi: []
}, 'pos', { ...objectProperties, value: item.value.pos });
items.push(bracket);
}
match++;
break;
case ValidationTokenEnum.CloseBracket:
match--;
if (match > 0) {
bracket.chi.push(item.value);
}
break;
default:
if (match > 0) {
bracket.chi.push(item.value);
}
else {
items.push(item.value);
}
break;
}
}
for (const item of items) {
if ('chi' in item) {
// @ts-ignore
item.chi = matchBrackets(syntax, item.chi[Symbol.iterator]());
}
}
return items;
}
function matchCurlBraces(syntax, iterator) {
let item;
let block = null;
let items = [];
let match = 0;
while ((item = iterator.next()) && !item.done) {
switch (item.value.typ) {
case ValidationTokenEnum.OpenCurlyBrace:
if (match > 0) {
block.chi.push(item.value);
}
else if (match == 0) {
block = Object.defineProperty({
typ: ValidationTokenEnum.Block,
chi: []
}, 'pos', { ...objectProperties, value: item.value.pos });
items.push(block);
}
match++;
break;
case ValidationTokenEnum.CloseCurlyBrace:
match--;
if (match > 0) {
block.chi.push(item.value);
}
break;
default:
if (match > 0) {
block.chi.push(item.value);
}
else {
items.push(item.value);
}
break;
}
}
let it;
let i = 0;
for (; i < items.length; i++) {
it = items[i];
if (i > 0 && it.typ == ValidationTokenEnum.Block && it.chi[0]?.typ == ValidationTokenEnum.Number) {
items[i - 1].occurence = {
min: +it.chi[0].val,
max: +(it.chi[2] ?? it.chi[0]).val
};
items.splice(i--, 1);
continue;
}
if ('chi' in it) {
// @ts-ignore
it.chi = matchBrackets(syntax, it.chi[Symbol.iterator]());
}
}
return items;
}
function matchAtRule(syntax, iterator) {
const children = [];
let item;
let token = null;
while ((item = iterator.next()) && !item.done) {
if (item.value.typ == ValidationTokenEnum.AtRule || item.value.typ == ValidationTokenEnum.AtRuleDefinition) {
token = Object.defineProperty({
...item.value,
typ: ValidationTokenEnum.AtRuleDefinition
}, 'pos', { ...objectProperties, value: item.value.pos });
children.push(token);
item = iterator.next();
if (item.done) {
// @ts-ignore
token.typ = ValidationTokenEnum.AtRule;
break;
}
if (item.value.typ != ValidationTokenEnum.Whitespace) {
console.error('unexpected token', item.value);
}
item = iterator.next();
if (item.done) {
break;
}
if (item.value.typ == ValidationTokenEnum.Pipe) {
// @ts-ignore
token.typ = ValidationTokenEnum.AtRule;
children.push(item.value);
continue;
}
if (item.value.typ != ValidationTokenEnum.OpenCurlyBrace) {
if (!('prelude' in token)) {
token.prelude = [];
}
token.prelude.push(item.value);
}
let braces = 0;
let previousItem = item.value;
while ((item = iterator.next()) && !item.done) {
if (item.value.typ == ValidationTokenEnum.DeclarationNameToken) {
iterator.next();
const t = Object.defineProperty({
typ: ValidationTokenEnum.DeclarationDefinitionToken,
nam: item.value.val,
val: iterator.next().value
}, 'pos', {
...objectProperties,
value: item.value.pos
});
if (braces > 0) {
token.chi.push(t);
}
else {
token.prelude.push(t);
}
previousItem = t;
continue;
}
if (item.value.typ == ValidationTokenEnum.OpenCurlyBrace) {
previousItem = item.value;
continue;
}
if (item.value.typ == ValidationTokenEnum.Whitespace && previousItem?.typ == ValidationTokenEnum.OpenCurlyBrace) {
braces++;
if (braces == 1) {
previousItem = item.value;
continue;
}
}
if (previousItem?.typ == ValidationTokenEnum.Whitespace && item.value.typ == ValidationTokenEnum.CloseCurlyBrace) {
braces--;
if (braces == 0) {
break;
}
}
if (braces == 0) {
if (!('prelude' in token)) {
token.prelude = [];
}
token.prelude.push(item.value);
}
else {
if (!('chi' in token)) {
token.chi = [];
}
token.chi.push(item.value);
}
previousItem = item.value;
}
if ('prelude' in token) {
if (token?.prelude?.length == 1 && token.prelude[0].typ == ValidationTokenEnum.Whitespace) {
delete token.prelude;
}
else {
const t = { typ: ValidationTokenEnum.Root, chi: token.prelude };
doParseSyntax(syntax, t.chi[Symbol.iterator](), t);
token.prelude = t.chi;
minify$1(token.prelude);
}
}
// @ts-ignore
if (token?.chi?.length > 0) {
minify$1(doParseSyntax(syntax, token.chi[Symbol.iterator](), token));
}
}
else {
children.push(item.value);
}
}
return children;
}
function matchToken$1(syntax, iterator, validationToken) {
let children = [];
let item;
let token = null;
let i;
if (validationToken == ValidationTokenEnum.Ampersand) {
// @ts-ignore
children = [...iterator];
let offsetL;
let offsetR;
for (i = 0; i < children.length; i++) {
if (children[i].typ == ValidationTokenEnum.Ampersand) {
offsetR = i + 1;
offsetL = i - 1;
while (offsetR < children.length - 1 && children[offsetR].typ == ValidationTokenEnum.Whitespace) {
offsetR++;
}
while (offsetR + 1 < children.length && skipped.includes(children[offsetR + 1].typ)) {
offsetR++;
}
while (offsetL > 0 && (children[offsetL].typ == ValidationTokenEnum.Whitespace || skipped.includes(children[offsetL].typ))) {
offsetL--;
}
token = Object.defineProperty({
typ: ValidationTokenEnum.AmpersandToken,
l: children.slice(offsetL, i),
r: children.slice(i + 1, offsetR + 1)
}, 'pos', { ...objectProperties, value: children[i].pos });
i = offsetL;
children.splice(offsetL, offsetR - offsetL + 1, token);
}
else if ('chi' in children[i]) {
// @ts-ignore
children[i].chi = matchToken$1(syntax, children[i].chi[Symbol.iterator](), validationToken);
}
else if ('l' in children[i]) {
// @ts-ignore
children[i].l = matchToken$1(syntax, children[i].l[Symbol.iterator](), validationToken);
// @ts-ignore
children[i].r = matchToken$1(syntax, children[i].r[Symbol.iterator](), validationToken);
}
}
return children;
}
while ((item = iterator.next()) && !item.done) {
if (item.value.typ == validationToken) {
if (item.value.typ == ValidationTokenEnum.Pipe) {
token = Object.defineProperty({
typ: ValidationTokenEnum.PipeToken,
chi: [matchToken$1(syntax, children.slice()[Symbol.iterator](), validationToken)], //.concat(matchToken(syntaxes, children.slice()[Symbol.iterator]() as Iterator<ValidationTokenIteratorValue>, validationToken), matchToken(syntaxes, iterator, validationToken)),
// @ts-ignore
// l: matchToken(syntaxes, children.slice()[Symbol.iterator](), validationToken),
// r: matchToken(syntaxes, iterator, validationToken)
}, 'pos', {
...objectProperties,
value: item.value.pos
});
children.length = 0;
while ((item = iterator.next()) && !item.done) {
if (item.value.typ == ValidationTokenEnum.Pipe) {
token.chi.push(matchToken$1(syntax, children.slice()[Symbol.iterator](), validationToken));
children.length = 0;
}
else {
children.push(item.value);
}
}
if (children.length > 0) {
token.chi.push(matchToken$1(syntax, children.slice()[Symbol.iterator](), validationToken));
}
token.chi.sort((a, b) => {
if (a.some((t) => t.isList)) {
return -1;
}
if (b.some((t) => t.isList)) {
return 1;
}
if (a.some((t) => t.occurence != null)) {
return -1;
}
if (b.some((t) => t.occurence != null)) {
return -1;
}
if (a.some((t) => t.isRepeatableGroup)) {
return -1;
}
if (b.some((t) => t.isRepeatableGroup)) {
return 1;
}
if (a.some((t) => t.isRepeatable)) {
return -1;
}
if (b.some((t) => t.isRepeatable)) {
return 1;
}
if (a.some((t) => t.isOptional)) {
return 1;
}
if (b.some((t) => t.isOptional)) {
return -1;
}
return 0;
});
children = [token];
}
else {
token = Object.defineProperty({
typ: ValidationTokenEnum.ColumnToken,
l: matchToken$1(syntax, children.slice()[Symbol.iterator](), validationToken),
r: matchToken$1(syntax, iterator, validationToken)
}, 'pos', {
...objectProperties,
value: item.value.pos
});
}
children.length = 0;
children.push(token);
while ((item = iterator.next()) && !item.done) {
children.push(item.value);
if ('chi' in item.value) {
// @ts-ignore
item.value.chi = matchToken$1(syntax, item.value.chi[Symbol.iterator](), validationToken);
}
else if ('l' in item.value) {
// @ts-ignore
item.value.l = matchToken$1(syntax, item.value.l[Symbol.iterator](), validationToken);
// @ts-ignore
item.value.r = matchToken$1(syntax, item.value.r[Symbol.iterator](), validationToken);
}
}
// @ts-ignore
return children;
}
else {
children.push(item.value);
if ('chi' in item.value) {
// @ts-ignore
item.value.chi = matchToken$1(syntax, item.value.chi[Symbol.iterator](), validationToken);
}
else if ('l' in item.value) {
// @ts-ignore
item.value.l = matchToken$1(syntax, item.value.l[Symbol.iterator](), validationToken);
// @ts-ignore
item.value.r = matchToken$1(syntax, item.value.r[Symbol.iterator](), validationToken);
}
}
}
return children;
}
function parseTokens$1(syntax, iterator) {
const items = [];
let item;
let i;
while ((item = iterator.next()) && !item.done) {
if (Array.isArray(item.value)) {
// @ts-ignore
item.value = parseTokens$1(syntax, item.value[Symbol.iterator]());
}
switch (item.value.typ) {
case ValidationTokenEnum.Star:
case ValidationTokenEnum.HashMark:
case ValidationTokenEnum.AtLeastOnce:
case ValidationTokenEnum.Exclamation:
case ValidationTokenEnum.QuestionMark:
case ValidationTokenEnum.OpenCurlyBrace:
i = items.length;
while (i--) {
if (items[i].typ != ValidationTokenEnum.Whitespace) {
break;
}
}
if (item.value.typ == ValidationTokenEnum.Exclamation) {
items[i].isRepeatableGroup = true;
}
else if (item.value.typ == ValidationTokenEnum.QuestionMark) {
items[i].isOptional = true;
}
else if (item.value.typ == ValidationTokenEnum.Star) {
items[i].isRepeatable = true;
}
else if (item.value.typ == ValidationTokenEnum.AtLeastOnce) {
items[i].atLeastOnce = true;
}
else if (item.value.typ == ValidationTokenEnum.HashMark) {
items[i].isList = true;
}
else if (item.value.typ == ValidationTokenEnum.OpenCurlyBrace) {
items[i].occurence = {
min: 0,
max: 0
};
while ((item = iterator.next()) && !item.done) {
if (item.value.typ == ValidationTokenEnum.Number) {
// @ts-ignore
if (items[i].occurence.min == 0) {
// @ts-ignore
items[i].occurence.min = +item.value.val;
}
else {
// @ts-ignore
items[i].occurence.max = +item.value.val;
}
}
if (item.value.typ == ValidationTokenEnum.CloseCurlyBrace) {
break;
}
}
}
break;
case ValidationTokenEnum.Pipe:
item.value.chi = item.value.chi.map((t) => parseTokens$1(syntax, t[Symbol.iterator]()));
items.push(item.value);
break;
default:
items.push(item.value);
break;
}
}
for (i = 0; i < items.length; i++) {
if ('chi' in items[i]) {
// @ts-ignore
items[i].chi = parseTokens$1(syntax, items[i].chi[Symbol.iterator]());
}
else if ('l' in items[i]) {
// @ts-ignore
items[i].l = parseTokens$1(syntax, items[i].l[Symbol.iterator]());
// @ts-ignore
items[i].r = parseTokens$1(syntax, items[i].r[Symbol.iterator]());
}
if (items[i].isOptional || items[i].isRepeatable) {
if (i <= 1) {
let k = i;
while (++k < items.length) {
if (items[k].typ == ValidationTokenEnum.Whitespace) {
continue;
}
if (items[k].typ == ValidationTokenEnum.Comma) {
items.splice(i, k - i + 1, Object.defineProperty({
typ: ValidationTokenEnum.Bracket,
chi: items.slice(i, k + 1)
}, 'pos', { ...objectProperties, value: items[i].pos }));
}
break;
}
}
else {
let k = i;
while (--k > 0) {
if (items[k].typ == ValidationTokenEnum.Whitespace) {
continue;
}
if (items[k].typ == ValidationTokenEnum.Comma) {
items.splice(k, i - k + 1, Object.defineProperty({
typ: ValidationTokenEnum.Bracket,
chi: items.slice(k, i + 1)
}, 'pos', { ...objectProperties, value: items[k].pos }));
i = k - 1;
}
break;
}
}
}
}
return items;
}
function doParseSyntax(syntax, iterator, context) {
context.chi = matchParens(syntax, iterator);
// @ts-ignore
context.chi = matchAtRule(syntax, context.chi[Symbol.iterator]());
// @ts-ignore
context.chi = matchBrackets(syntax, context.chi[Symbol.iterator]());
// @ts-ignore
context.chi = matchCurlBraces(syntax, context.chi[Symbol.iterator]());
// @ts-ignore
context.chi = matchToken$1(syntax, context.chi[Symbol.iterator](), ValidationTokenEnum.Column);
// @ts-ignore
context.chi = matchToken$1(syntax, context.chi[Symbol.iterator](), ValidationTokenEnum.Pipe);
// @ts-ignore
context.chi = parseTokens$1(syntax, context.chi[Symbol.iterator]());
// @ts-ignore
context.chi = matchToken$1(syntax, context.chi[Symbol.iterator](), ValidationTokenEnum.Ampersand);
return context;
}
function getTokenType$1(token, position, currentPosition) {
const pos = { ...position };
Object.assign(position, currentPosition);
if (token.charAt(0) == '"' || token.charAt(0) == "'") {
return Object.defineProperty({
typ: ValidationTokenEnum.StringToken,
val: token
}, 'pos', { ...objectProperties, value: pos });
}
if (token == ';') {
return Object.defineProperty({
typ: ValidationTokenEnum.SemiColon
}, 'pos', { ...objectProperties, value: pos });
}
if (token.match(/^\s+$/)) {
return Object.defineProperty({
typ: ValidationTokenEnum.Whitespace,
}, 'pos', { ...objectProperties, value: pos });
}
if (token.match(/^\d+$/)) {
return Object.defineProperty({
typ: ValidationTokenEnum.Number,
val: Number(token)
}, 'pos', { ...objectProperties, value: pos });
}
if (isPseudo(token)) {
return Object.defineProperty({
typ: ValidationTokenEnum.PseudoClassToken,
val: token
}, 'pos', { ...objectProperties, value: pos });
}
if (token == '!') {
return Object.defineProperty({
typ: ValidationTokenEnum.Exclamation
}, 'pos', { ...objectProperties, value: pos });
}
if (token == '#') {
return Object.defineProperty({
typ: ValidationTokenEnum.HashMark
}, 'pos', { ...objectProperties, value: pos });
}
if (token == '/') {
return Object.defineProperty({
typ: ValidationTokenEnum.Separator
}, 'pos', { ...objectProperties, value: pos });
}
if (token == '+') {
return Object.defineProperty({
typ: ValidationTokenEnum.AtLeastOnce
}, 'pos', { ...objectProperties, value: pos });
}
if (token == '|') {
return Object.defineProperty({
typ: ValidationTokenEnum.Pipe
}, 'pos', { ...objectProperties, value: pos });
}
if (token == '&&') {
return Object.defineProperty({
typ: ValidationTokenEnum.Ampersand
}, 'pos', { ...objectProperties, value: pos });
}
if (token == '||') {
return Object.defineProperty({
typ: ValidationTokenEnum.Column
}, 'pos', { ...objectProperties, value: pos });
}
if (token == ',') {
return Object.defineProperty({
typ: ValidationTokenEnum.Comma
}, 'pos', { ...objectProperties, value: pos });
}
if (token == '[') {
return Object.defineProperty({
typ: ValidationTokenEnum.OpenBracket
}, 'pos', { ...objectProperties, value: pos });
}
if (token == ']') {
return Object.defineProperty({
typ: ValidationTokenEnum.CloseBracket
}, 'pos', { ...objectProperties, value: pos });
}
if (token == '(') {
return Object.defineProperty({
typ: ValidationTokenEnum.OpenParenthesis
}, 'pos', { ...objectProperties, value: pos });
}
if (token == ')') {
return Object.defineProperty({
typ: ValidationTokenEnum.CloseParenthesis
}, 'pos', { ...objectProperties, value: pos });
}
if (token == '{') {
return Object.defineProperty({
typ: ValidationTokenEnum.OpenCurlyBrace
}, 'pos', { ...objectProperties, value: pos });
}
if (token == '}') {
return Object.defineProperty({
typ: ValidationTokenEnum.CloseCurlyBrace
}, 'pos', { ...objectProperties, value: pos });
}
if (token == '*') {
return Object.defineProperty({
typ: ValidationTokenEnum.Star
}, 'pos', { ...objectProperties, value: pos });
}
if (token == '?') {
return Object.defineProperty({
typ: ValidationTokenEnum.QuestionMark
}, 'pos', { ...objectProperties, value: pos });
}
if (token.startsWith("<'")) {
return Object.defineProperty({
typ: ValidationTokenEnum.DeclarationType,
val: token.slice(2, -2)
}, 'pos', { ...objectProperties, value: pos });
}
if (token.startsWith('<')) {
// <number [1,1000]>
// <length [0,∞]>
let match = token.match(/<([a-z0-9-]+)(\s+\[([0-9]+),(([0-9]+)|∞)\])?>/);
if (match == null) {
let match = token.match(/<([a-zA-Z0-9-]+)\(\)>/);
if (match != null) {
return Object.defineProperty({
typ: ValidationTokenEnum.ValidationFunctionDefinition,
val: match[1]
}, 'pos', { ...objectProperties, value: pos });
}
throw new Error('invalid token at position: ' + position.lin + ':' + position.col + ' ' + token);
}
if (match[2] != null) {
return Object.defineProperty({
typ: ValidationTokenEnum.PropertyType,
val: match[1],
range: [+match[3], match[4] == '∞' ? Infinity : +match[4]]
}, 'pos', { ...objectProperties, value: pos });
}
return Object.defineProperty({
typ: ValidationTokenEnum.PropertyType,
val: token.slice(1, -1)
}, 'pos', { ...objectProperties, value: pos });
}
if (token.startsWith('@') && isIdent(token.slice(1))) {
return Object.defineProperty({
typ: ValidationTokenEnum.AtRule,
val: token.slice(1)
}, 'pos', { ...objectProperties, value: pos });
}
return Object.defineProperty({
typ: ValidationTokenEnum.Keyword,
val: token
}, 'pos', { ...objectProperties, value: pos });
}
function move(position, chr) {
for (const c of chr) {
position.col++;
position.ind += c.length;
}
return position;
}
function minify$1(ast) {
if (Array.isArray(ast)) {
// @ts-ignore
while (ast.length > 0 && ast[0].typ == ValidationTokenEnum.Whitespace) {
// @ts-ignore
ast.shift();
}
while (ast.length > 0 && ast.at(-1).typ == ValidationTokenEnum.Whitespace) {
ast.pop();
}
for (let i = 0; i < ast.length; i++) {
// if ([ValidationTokenEnum.ColumnToken, ValidationTokenEnum.PipeToken, ValidationTokenEnum.AmpersandToken].includes(ast[i].typ)) {
// for (const j of (ast[i] as ValidationPipeToken | ValidationColumnToken | ValidationAmpersandToken).l) {
minify$1(ast[i]);
// }
// for (const j of (ast[i] as ValidationPipeToken | ValidationColumnToken | ValidationAmpersandToken).r) {
//
// minify(j);
// }
// } else
// if ('chi' in ast[i]) {
//
// minify((ast[i] as ValidationFunctionToken | ValidationBracketToken).chi as ValidationToken[]);
//
// } else
if (ast[i].typ == ValidationTokenEnum.Whitespace && ast[i + 1]?.typ == ValidationTokenEnum.Whitespace) {
ast.splice(i + 1, 1);
i--;
continue;
}
if (ast[i].typ == ValidationTokenEnum.Separator) {
if (ast[i + 1]?.typ == ValidationTokenEnum.Whitespace) {
ast.splice(i + 1, 1);
}
if (ast[i - 1]?.typ == ValidationTokenEnum.Whitespace) {
ast.splice(--i, 1);
}
}
}
return ast;
}
// else {
// if ([ValidationTokenEnum.ColumnToken, ValidationTokenEnum.PipeToken, ValidationTokenEnum.AmpersandToken].includes(ast.typ)) {
// for (const j of (ast as ValidationPipeToken | ValidationColumnToken | ValidationAmpersandToken).l) {
if ('l' in ast) {
minify$1(ast.l);
}
// }
// for (const j of (ast as ValidationPipeToken | ValidationColumnToken | ValidationAmpersandToken).r) {
if ('r' in ast) {
minify$1(ast.r);
}
if ('chi' in ast) {
minify$1(ast.chi);
}
if ('prelude' in ast) {
minify$1(ast.prelude);
}
return ast;
}
function* walkValidationToken(token, parent, callback, key) {
if (Array.isArray(token)) {
for (const child of token) {
yield* walkValidationToken(child, parent, callback, WalkValidationTokenKeyTypeEnum.Array);
}
return;
}
let action = null;
if (callback != null) {
// @ts-ignore
action = callback(token, parent, key);
}
if (action != WalkValidationTokenEnum.IgnoreNode && action != WalkValidationTokenEnum.IgnoreAll) {
yield { token, parent };
}
if (action != WalkValidationTokenEnum.IgnoreChildren && action != WalkValidationTokenEnum.IgnoreAll && 'prelude' in token) {
for (const child of token.prelude) {
yield* walkValidationToken(child, token, callback, WalkValidationTokenKeyTypeEnum.Prelude);
}
}
if (action != WalkValidationTokenEnum.IgnoreChildren && 'chi' in token) {
// @ts-ignore
for (const child of token.chi) {
yield* walkValidationToken(child, token, callback, WalkValidationTokenKeyTypeEnum.Children);
}
}
if (action != WalkValidationTokenEnum.IgnoreChildren && action != WalkValidationTokenEnum.IgnoreAll && 'l' in token) {
// @ts-ignore
for (const child of token.l) {
yield* walkValidationToken(child, token, callback, WalkValidationTokenKeyTypeEnum.Left);
}
}
if (action != WalkValidationTokenEnum.IgnoreChildren && action != WalkValidationTokenEnum.IgnoreAll && 'r' in token) {
// @ts-ignore
for (const child of token.r) {
yield* walkValidationToken(child, token, callback, WalkValidationTokenKeyTypeEnum.Right);
}
}
}
const parsedSyntaxes = new Map();
Object.freeze(config$2);
function getSyntaxConfig() {
// @ts-ignore
return config$2;
}
function getParsedSyntax(group, key) {
// @ts-ignore
let obj = config$2[group];
const keys = Array.isArray(key) ? key : [key];
for (let i = 0; i < keys.length; i++) {
key = keys[i];
if (!(key in obj)) {
if ((i == 0 && key.charAt(0) == '@') || key.charAt(0) == '-') {
const matches = key.match(/^(@?)(-[a-zA-Z]+)-(.*?)$/);
if (matches != null) {
key = matches[1] + matches[3];
}
}
if (!(key in obj)) {
return null;
}
}
// @ts-ignore
obj = obj[key];
}
const index = group + '.' + keys.join('.');
// @ts-ignore
if (!parsedSyntaxes.has(index)) {
// @ts-ignore
const syntax = parseSyntax(obj.syntax);
// @ts-ignore
parsedSyntaxes.set(index, syntax.chi);
}
return parsedSyntaxes.get(index);
}
function validateLayerName(tokens) {
const slice = tokens.reduce((acc, curr) => {
if (curr.typ == exports.EnumToken.CommaTokenType) {
acc.push([]);
}
else if (curr.typ != exports.EnumToken.CommentTokenType) {
acc[acc.length - 1].push(curr);
}
return acc;
}, [[]]);
for (let i = 0; i < slice.length; i++) {
if (slice[i].length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: tokens,
node: null,
syntax: null,
error: 'Invalid ident',
tokens
};
}
for (let j = 0; j < slice[i].length; j++) {
if (slice[i][j].typ != exports.EnumToken.IdenTokenType && slice[i][j].typ != exports.EnumToken.ClassSelectorTokenType) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: tokens,
node: slice[i][j],
syntax: '<layer-name>',
error: 'expecting ident or class selector',
tokens
};
}
}
}
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: tokens,
node: null,
syntax: null,
error: '',
tokens
};
}
function consumeWhitespace(tokens) {
if (tokens.length == 0) {
return true;
}
if (tokens[0].typ != exports.EnumToken.WhitespaceTokenType && tokens[0].typ != exports.EnumToken.DescendantCombinatorTokenType) {
return false;
}
while (tokens.length > 0 && (tokens[0].typ == exports.EnumToken.WhitespaceTokenType || tokens[0].typ == exports.EnumToken.DescendantCombinatorTokenType)) {
tokens.shift();
}
return true;
}
function splitTokenList(tokenList, split = [exports.EnumToken.CommaTokenType]) {
return tokenList.reduce((acc, curr) => {
if (curr.typ == exports.EnumToken.CommentTokenType) {
return acc;
}
if (split.includes(curr.typ)) {
acc.push([]);
}
else {
acc[acc.length - 1].push(curr);
}
return acc;
}, [[]]);
}
function validateFamilyName(tokens, atRule) {
let node;
tokens = tokens.slice();
consumeWhitespace(tokens);
if (tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: null,
error: 'expected at-rule prelude',
tokens
};
}
if (tokens[0].typ == exports.EnumToken.CommaTokenType) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: null,
error: 'unexpected token',
tokens
};
}
while (tokens.length > 0) {
// @ts-ignore
if (tokens[0].typ == exports.EnumToken.CommaTokenType) {
node = tokens.shift();
consumeWhitespace(tokens);
if (tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node,
syntax: null,
error: 'unexpected token',
tokens
};
}
}
node = tokens[0];
if (![exports.EnumToken.IdenTokenType, exports.EnumToken.StringTokenType].includes(node.typ)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node,
syntax: null,
error: 'unexpected token',
tokens
};
}
tokens.shift();
consumeWhitespace(tokens);
// @ts-ignore
if (tokens.length > 0 && node.typ == exports.EnumToken.BadStringTokenType && tokens[0].typ != exports.EnumToken.CommaTokenType) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: null,
error: 'expected comma token',
tokens
};
}
}
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: null,
syntax: null,
error: '',
tokens
};
}
function validateCompoundSelector(tokens, root, options) {
if (tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
// @ts-ignore
node: root,
// @ts-ignore
syntax: null,
error: 'expected selector',
tokens
};
}
tokens = tokens.slice();
consumeWhitespace(tokens);
const config = getSyntaxConfig();
let match = 0;
let length = tokens.length;
while (tokens.length > 0) {
while (tokens.length > 0 && tokens[0].typ == exports.EnumToken.NestingSelectorTokenType) {
if (!options?.nestedSelector) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
// @ts-ignore
node: tokens[0],
syntax: null,
error: 'nested selector not allowed',
tokens
};
}
match++;
tokens.shift();
consumeWhitespace(tokens);
}
// <type-selector>
while (tokens.length > 0 &&
[
exports.EnumToken.IdenTokenType,
exports.EnumToken.NameSpaceAttributeTokenType,
exports.EnumToken.ClassSelectorTokenType,
exports.EnumToken.HashTokenType,
exports.EnumToken.UniversalSelectorTokenType
].includes(tokens[0].typ)) {
match++;
tokens.shift();
consumeWhitespace(tokens);
}
while (tokens.length > 0 && tokens[0].typ == exports.EnumToken.PseudoClassFuncTokenType) {
if (!mozExtensions.has(tokens[0].val + '()') &&
!webkitExtensions.has(tokens[0].val + '()') &&
!((tokens[0].val + '()') in config.selectors)) {
if (!options?.lenient || /^(:?)-webkit-/.test(tokens[0].val)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
// @ts-ignore
node: tokens[0],
syntax: null,
error: 'unknown pseudo-class: ' + tokens[0].val + '()',
tokens
};
}
}
match++;
tokens.shift();
consumeWhitespace(tokens);
}
while (tokens.length > 0 && (tokens[0].typ == exports.EnumToken.PseudoElementTokenType || tokens[0].typ == exports.EnumToken.PseudoClassTokenType)) {
const isPseudoElement = tokens[0].typ == exports.EnumToken.PseudoElementTokenType;
if (
// https://developer.mozilla.org/en-US/docs/Web/CSS/WebKit_Extensions#pseudo-elements
!(isPseudoElement && tokens[0].val.startsWith('::-webkit-')) &&
!mozExtensions.has(tokens[0].val) &&
!webkitExtensions.has(tokens[0].val) &&
!(tokens[0].val in config.selectors) &&
!(!isPseudoElement &&
(':' + tokens[0].val) in config.selectors)) {
if (!options?.lenient || /^(:?)-webkit-/.test(tokens[0].val)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
// @ts-ignore
node: tokens[0],
syntax: null,
error: 'unknown pseudo-class: ' + tokens[0].val,
tokens
};
}
}
match++;
tokens.shift();
consumeWhitespace(tokens);
}
while (tokens.length > 0 && tokens[0].typ == exports.EnumToken.AttrTokenType) {
const children = tokens[0].chi.slice();
consumeWhitespace(children);
if (children.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: null,
error: 'invalid attribute selector',
tokens
};
}
if (![
exports.EnumToken.IdenTokenType,
exports.EnumToken.NameSpaceAttributeTokenType,
exports.EnumToken.MatchExpressionTokenType
].includes(children[0].typ)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: null,
error: 'invalid attribute selector',
tokens
};
}
if (children[0].typ == exports.EnumToken.MatchExpressionTokenType) {
if (children.length != 1) {
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: null,
error: 'invalid <attribute-selector>',
tokens
};
}
if (![
exports.EnumToken.IdenTokenType,
exports.EnumToken.NameSpaceAttributeTokenType
].includes(children[0].l.typ) ||
![
exports.EnumToken.EqualMatchTokenType, exports.EnumToken.DashMatchTokenType,
exports.EnumToken.StartMatchTokenType, exports.EnumToken.ContainMatchTokenType,
exports.EnumToken.EndMatchTokenType, exports.EnumToken.IncludeMatchTokenType
].includes(children[0].op.typ) ||
![
exports.EnumToken.StringTokenType,
exports.EnumToken.IdenTokenType
].includes(children[0].r.typ)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: null,
error: 'invalid attribute selector',
tokens
};
}
if (children[0].attr != null && !['i', 's'].includes(children[0].attr)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: null,
error: 'invalid attribute selector',
tokens
};
}
}
match++;
tokens.shift();
consumeWhitespace(tokens);
}
if (length == tokens.length) {
return {
valid: ValidationLevel.Drop,
matches: [],
// @ts-ignore
node: tokens[0],
// @ts-ignore
syntax: null,
error: 'expected compound selector',
tokens
};
}
length = tokens.length;
}
return match == 0 ? {
valid: ValidationLevel.Drop,
matches: [],
// @ts-ignore
node: root,
// @ts-ignore
syntax: null,
error: 'expected compound selector',
tokens
} :
// @ts-ignore
{
valid: ValidationLevel.Valid,
matches: [],
// @ts-ignore
node: root,
// @ts-ignore
syntax: null,
error: null,
tokens
};
}
const combinatorsTokens = [exports.EnumToken.ChildCombinatorTokenType, exports.EnumToken.ColumnCombinatorTokenType,
// EnumToken.DescendantCombinatorTokenType,
exports.EnumToken.NextSiblingCombinatorTokenType, exports.EnumToken.SubsequentSiblingCombinatorTokenType];
// <compound-selector> [ <combinator>? <compound-selector> ]*
function validateComplexSelector(tokens, root, options) {
// [ <type-selector>? <subclass-selector>* [ <pseudo-element-selector> <pseudo-class-selector>* ]* ]!
tokens = tokens.slice();
consumeWhitespace(tokens);
if (tokens.length == 0) {
return {
valid: ValidationLevel.Drop,
matches: [],
// @ts-ignore
node: root,
syntax: null,
error: 'expected selector',
tokens
};
}
// const config = getSyntaxConfig();
//
// let match: number = 0;
let result = null;
// const combinators: EnumToken[] = combinatorsTokens.filter((t: EnumToken) => t != EnumToken.DescendantCombinatorTokenType);
for (const t of splitTokenList(tokens, combinatorsTokens)) {
result = validateCompoundSelector(t, root, options);
if (result.valid == ValidationLevel.Drop) {
return result;
}
}
// @ts-ignore
return result ?? {
valid: ValidationLevel.Drop,
matches: [],
node: root,
syntax: null,
error: 'expecting compound-selector',
tokens
};
}
const validateSelector$1 = validateComplexSelector;
function validateRelativeSelector(tokens, root, options) {
tokens = tokens.slice();
consumeWhitespace(tokens);
if (tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
// @ts-ignore
node: root,
// @ts-ignore
syntax: null,
error: 'expected selector',
tokens
};
}
// , EnumToken.DescendantCombinatorTokenType
if (combinatorsTokens.includes(tokens[0].typ)) {
tokens.shift();
consumeWhitespace(tokens);
}
return validateSelector$1(tokens, root, options);
}
function validateRelativeSelectorList(tokens, root, options) {
tokens = tokens.slice();
consumeWhitespace(tokens);
if (tokens.length == 0) {
return {
valid: ValidationLevel.Drop,
matches: [],
// @ts-ignore
node: root,
// @ts-ignore
syntax: null,
error: 'expecting relative selector list',
tokens
};
}
for (const t of splitTokenList(tokens)) {
if (t.length == 0) {
return {
valid: ValidationLevel.Drop,
matches: [],
// @ts-ignore
node: root,
// @ts-ignore
syntax: null,
error: 'unexpected comma',
tokens
};
}
const result = validateRelativeSelector(t, root, options);
if (result.valid == ValidationLevel.Drop) {
return result;
}
}
return {
valid: ValidationLevel.Valid,
matches: [],
// @ts-ignore
node: root,
// @ts-ignore
syntax: null,
error: '',
tokens
};
}
function validateComplexSelectorList(tokens, root, options) {
tokens = tokens.slice();
consumeWhitespace(tokens);
if (tokens.length == 0) {
return {
valid: ValidationLevel.Drop,
matches: [],
// @ts-ignore
node: root,
syntax: null,
error: 'expecting complex selector list',
tokens
};
}
let result = null;
for (const t of splitTokenList(tokens)) {
result = validateSelector$1(t, root, options);
if (result.valid == ValidationLevel.Drop) {
return result;
}
}
// @ts-ignore
return result ?? {
valid: ValidationLevel.Drop,
matches: [],
// @ts-ignore
node: root,
syntax: null,
error: 'expecting complex selector list',
tokens
};
}
function validateKeyframeSelector(tokens, atRule, options) {
consumeWhitespace(tokens);
if (tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: null,
error: 'expected keyframe selector',
tokens
};
}
if (tokens[0].typ == exports.EnumToken.PercentageTokenType) {
tokens.shift();
consumeWhitespace(tokens);
if (tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: null,
error: '',
tokens
};
}
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: null,
error: 'unexpected token',
tokens
};
}
if (tokens[0].typ != exports.EnumToken.IdenTokenType) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
// @ts-ignore
syntax: null,
error: 'expected keyframe selector',
tokens
};
}
if (['from', 'to'].includes(tokens[0].val)) {
tokens.shift();
consumeWhitespace(tokens);
if (tokens.length > 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: null,
error: 'unexpected token',
tokens
};
}
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: null,
// @ts-ignore
syntax: null,
error: '',
tokens
};
}
if (!['cover', 'contain', 'entry', 'exit', 'entry-crossing', 'exit-crossing'].includes(tokens[0].val)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
// @ts-ignore
syntax: null,
error: 'unexpected token',
tokens
};
}
tokens.shift();
consumeWhitespace(tokens);
// @ts-ignore
if (tokens.length == 0 || tokens[0].typ != exports.EnumToken.PercentageTokenType) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
// @ts-ignore
syntax: null,
error: 'expecting percentage token',
tokens
};
}
tokens.shift();
consumeWhitespace(tokens);
if (tokens.length > 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
// @ts-ignore
syntax: null,
error: 'unexpected token',
tokens
};
}
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: null,
// @ts-ignore
syntax: null,
error: '',
tokens
};
}
function validateKeyframeBlockList(tokens, atRule, options) {
let i = 0;
let j = 0;
let result = null;
while (i + 1 < tokens.length) {
if (tokens[++i].typ == exports.EnumToken.CommaTokenType) {
result = validateKeyframeSelector(tokens.slice(j, i), atRule);
if (result.valid == ValidationLevel.Drop) {
return result;
}
j = i + 1;
i = j;
}
}
return validateKeyframeSelector(i == j ? tokens.slice(i) : tokens.slice(j, i + 1), atRule);
}
function validateURL(token) {
if (token.typ == exports.EnumToken.UrlTokenTokenType) {
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: token,
// @ts-ignore
syntax: 'url()',
error: '',
tokens: []
};
}
if (token.typ != exports.EnumToken.UrlFunctionTokenType) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: token,
// @ts-ignore
syntax: 'url()',
error: 'expected url()',
tokens: []
};
}
const children = token.chi.slice();
consumeWhitespace(children);
if (children.length == 0 || ![exports.EnumToken.UrlTokenTokenType, exports.EnumToken.StringTokenType, exports.EnumToken.HashTokenType].includes(children[0].typ)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: children[0] ?? token,
// @ts-ignore
syntax: 'url()',
error: 'expected url-token',
tokens: children
};
}
children.shift();
consumeWhitespace(children);
if (children.length > 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: children[0] ?? token,
// @ts-ignore
syntax: 'url()',
error: 'unexpected token',
tokens: children
};
}
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: token,
// @ts-ignore
syntax: 'url()',
error: '',
tokens: []
};
}
const validateSelectorList = validateComplexSelectorList;
function validateSelector(selector, options, root) {
if (root == null) {
return validateSelectorList(selector, root, options);
}
// @ts-ignore
if (root.typ == exports.EnumToken.AtRuleNodeType && root.nam.match(/^(-[a-z]+-)?keyframes$/)) {
return validateKeyframeBlockList(selector, root);
}
let isNested = root.typ == exports.EnumToken.RuleNodeType ? 1 : 0;
let currentRoot = root.parent;
while (currentRoot != null && isNested == 0) {
if (currentRoot.typ == exports.EnumToken.RuleNodeType) {
isNested++;
if (isNested > 0) {
// @ts-ignore
return validateRelativeSelectorList(selector, root, { ...(options ?? {}), nestedSelector: true });
}
}
currentRoot = currentRoot.parent;
}
const nestedSelector = isNested > 0;
// @ts-ignore
return nestedSelector ? validateRelativeSelectorList(selector, root, { ...(options ?? {}), nestedSelector }) : validateSelectorList(selector, root, { ...(options ?? {}), nestedSelector });
}
function validateAtRuleMedia(atRule, options, root) {
// media-query-list
if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: null,
syntax: null,
error: '',
tokens: []
};
}
let result = null;
const slice = atRule.tokens.slice();
consumeWhitespace(slice);
if (slice.length == 0) {
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@media',
error: '',
tokens: []
};
}
result = validateAtRuleMediaQueryList(atRule.tokens, atRule);
if (result.valid == ValidationLevel.Drop) {
return result;
}
if (!('chi' in atRule)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@media',
error: 'expected at-rule body',
tokens: []
};
}
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@media',
error: '',
tokens: []
};
}
function validateAtRuleMediaQueryList(tokenList, atRule) {
const split = splitTokenList(tokenList);
const matched = [];
let result = null;
let previousToken;
let mediaFeatureType;
for (let i = 0; i < split.length; i++) {
const tokens = split[i].slice();
const match = [];
result = null;
mediaFeatureType = null;
previousToken = null;
if (tokens.length == 0) {
// @ts-ignore
result = {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0] ?? atRule,
syntax: '@media',
error: 'unexpected token',
tokens: []
};
continue;
}
while (tokens.length > 0) {
previousToken = tokens[0];
// media-condition | media-type | custom-media
if (!(validateMediaCondition(tokens[0], atRule) || validateMediaFeature(tokens[0]) || validateCustomMediaCondition(tokens[0], atRule))) {
if (tokens[0].typ == exports.EnumToken.ParensTokenType) {
result = validateAtRuleMediaQueryList(tokens[0].chi, atRule);
}
else {
result = {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0] ?? atRule,
syntax: '@media',
error: 'expecting media feature or media condition',
tokens: []
};
}
if (result.valid == ValidationLevel.Drop) {
break;
}
result = null;
}
match.push(tokens.shift());
if (tokens.length == 0) {
break;
}
if (!consumeWhitespace(tokens)) {
if (previousToken?.typ != exports.EnumToken.ParensTokenType) {
// @ts-ignore
result = {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0] ?? atRule,
syntax: '@media',
error: 'expected media query list',
tokens: []
};
break;
}
}
else if (![exports.EnumToken.MediaFeatureOrTokenType, exports.EnumToken.MediaFeatureAndTokenType].includes(tokens[0].typ)) {
// @ts-ignore
result = {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0] ?? atRule,
syntax: '@media',
error: 'expected and/or',
tokens: []
};
break;
}
if (mediaFeatureType == null) {
mediaFeatureType = tokens[0];
}
if (mediaFeatureType.typ != tokens[0].typ) {
// @ts-ignore
result = {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0] ?? atRule,
syntax: '@media',
error: 'mixing and/or not allowed at the same level',
tokens: []
};
break;
}
match.push({ typ: exports.EnumToken.WhitespaceTokenType }, tokens.shift());
consumeWhitespace(tokens);
if (tokens.length == 0) {
// @ts-ignore
result = {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0] ?? atRule,
syntax: '@media',
error: 'expected media-condition',
tokens: []
};
break;
}
match.push({ typ: exports.EnumToken.WhitespaceTokenType });
}
if (result == null && match.length > 0) {
matched.push(match);
}
}
if (result != null) {
return result;
}
if (matched.length == 0) {
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@media',
error: 'expected media query list',
tokens: []
};
}
tokenList.length = 0;
let hasAll = false;
for (let i = 0; i < matched.length; i++) {
if (tokenList.length > 0) {
tokenList.push({ typ: exports.EnumToken.CommaTokenType });
}
if (matched[i].length == 1 && matched.length > 1 && matched[i][0].typ == exports.EnumToken.MediaFeatureTokenType && matched[i][0].val == 'all') {
hasAll = true;
continue;
}
tokenList.push(...matched[i]);
}
if (hasAll && tokenList.length == 0) {
tokenList.push({ typ: exports.EnumToken.MediaFeatureTokenType, val: 'all' });
}
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@media',
error: '',
tokens: []
};
}
function validateCustomMediaCondition(token, atRule) {
if (token.typ == exports.EnumToken.MediaFeatureNotTokenType) {
return validateMediaCondition(token.val, atRule);
}
if (token.typ != exports.EnumToken.ParensTokenType) {
return false;
}
const chi = token.chi.filter((t) => t.typ != exports.EnumToken.CommentTokenType && t.typ != exports.EnumToken.WhitespaceTokenType);
if (chi.length != 1) {
return false;
}
return chi[0].typ == exports.EnumToken.DashedIdenTokenType;
}
function validateMediaCondition(token, atRule) {
if (token.typ == exports.EnumToken.MediaFeatureNotTokenType) {
return validateMediaCondition(token.val, atRule);
}
if (token.typ != exports.EnumToken.ParensTokenType && !(['when', 'else', 'import'].includes(atRule.nam) && token.typ == exports.EnumToken.FunctionTokenType && ['media', 'supports', 'selector'].includes(token.val))) {
return false;
}
const chi = token.chi.filter((t) => t.typ != exports.EnumToken.CommentTokenType && t.typ != exports.EnumToken.WhitespaceTokenType);
if (chi.length != 1) {
return false;
}
if (chi[0].typ == exports.EnumToken.IdenTokenType) {
return true;
}
if (chi[0].typ == exports.EnumToken.MediaFeatureNotTokenType) {
return validateMediaCondition(chi[0].val, atRule);
}
if (chi[0].typ == exports.EnumToken.MediaQueryConditionTokenType) {
return chi[0].l.typ == exports.EnumToken.IdenTokenType;
}
console.error(chi[0].parent);
return false;
}
function validateMediaFeature(token) {
let val = token;
if (token.typ == exports.EnumToken.MediaFeatureOnlyTokenType || token.typ == exports.EnumToken.MediaFeatureNotTokenType) {
val = token.val;
}
return val.typ == exports.EnumToken.MediaFeatureTokenType;
}
function validateAtRuleCounterStyle(atRule, options, root) {
// media-query-list
if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@counter-style',
error: 'expected counter style name',
tokens: []
};
}
const tokens = atRule.tokens.filter((t) => ![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType].includes(t.typ));
if (tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@counter-style',
error: 'expected counter style name',
tokens
};
}
if (tokens.length > 1) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[1] ?? atRule,
syntax: '@counter-style',
error: 'unexpected token',
tokens
};
}
if (![exports.EnumToken.IdenTokenType, exports.EnumToken.DashedIdenTokenType].includes(tokens[0].typ)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: '@counter-style',
error: 'expected counter style name',
tokens
};
}
if (!('chi' in atRule)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@counter-style',
error: 'expected counter style body',
tokens
};
}
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@counter-style',
error: '',
tokens
};
}
function validateAtRulePage(atRule, options, root) {
// media-query-list
if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: null,
syntax: '@page',
error: '',
tokens: []
};
}
// page-selector-list
for (const tokens of splitTokenList(atRule.tokens)) {
if (tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0] ?? atRule,
syntax: '@page',
error: 'unexpected token',
tokens: []
};
}
// <pseudo-page>+ | <ident> <pseudo-page>*
// ident pseudo-page* | pseudo-page+
if (tokens[0].typ == exports.EnumToken.IdenTokenType) {
tokens.shift();
if (tokens.length == 0) {
continue;
}
// @ts-ignore
if (tokens[0].typ != exports.EnumToken.WhitespaceTokenType) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0] ?? atRule,
syntax: '@page',
error: 'unexpected token',
tokens: []
};
}
}
while (tokens.length > 0) {
if (tokens[0].typ == exports.EnumToken.PseudoPageTokenType) {
tokens.shift();
if (tokens.length == 0) {
continue;
}
// @ts-ignore
if (tokens[0].typ != exports.EnumToken.WhitespaceTokenType) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0] ?? atRule,
syntax: '@page',
error: 'unexpected token',
tokens: []
};
}
}
}
}
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@page',
error: '',
tokens: []
};
}
function validateAtRulePageMarginBox(atRule, options, root) {
if (Array.isArray(atRule.tokens) && atRule.tokens.length > 0) {
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: null,
syntax: '@' + atRule.nam,
error: '',
tokens: []
};
}
if (!('chi' in atRule)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: 'expected margin-box body',
tokens: []
};
}
for (const token of atRule.chi) {
if (![exports.EnumToken.DeclarationNodeType, exports.EnumToken.CommentNodeType, exports.EnumToken.WhitespaceTokenType].includes(token.typ)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: token,
syntax: 'declaration-list',
error: 'expected margin-box body',
tokens: []
};
}
}
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: null,
syntax: '@' + atRule.nam,
error: '',
tokens: []
};
}
function validateAtRuleSupports(atRule, options, root) {
// media-query-list
if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: 'expected supports query list',
tokens: []
};
}
const result = validateAtRuleSupportsConditions(atRule, atRule.tokens);
if (result) {
if (result.node == null) {
result.node = atRule;
}
return result;
}
if (!('chi' in atRule)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: 'expected at-rule body',
tokens: []
};
}
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: '',
tokens: []
};
}
function validateAtRuleSupportsConditions(atRule, tokenList) {
let result = null;
for (const tokens of splitTokenList(tokenList)) {
if (tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0] ?? atRule,
syntax: '@' + atRule.nam,
error: 'unexpected token',
tokens: []
};
}
let previousToken = null;
while (tokens.length > 0) {
result = validateSupportCondition(atRule, tokens[0]);
// supports-condition
if (result.valid == ValidationLevel.Valid) {
previousToken = tokens[0];
tokens.shift();
}
else {
result = validateSupportFeature(tokens[0]);
if ( /*result == null || */result.valid == ValidationLevel.Valid) {
previousToken = tokens[0];
tokens.shift();
}
else {
if (tokens[0].typ == exports.EnumToken.ParensTokenType) {
result = validateAtRuleSupportsConditions(atRule, tokens[0].chi);
if ( /* result == null || */result.valid == ValidationLevel.Valid) {
previousToken = tokens[0];
tokens.shift();
// continue;
}
else {
return result;
}
}
else {
return result;
}
// if (result!= null && result.valid == ValidationLevel.Drop) {
//
// return {
// valid: ValidationLevel.Drop,
// matches: [],
// node: tokens[0] ?? atRule,
// syntax: '@' + atRule.nam,
// // @ts-ignore
// error: result.error as string ?? 'unexpected token',
// tokens: []
// };
// }
}
}
if (tokens.length == 0) {
break;
}
if (!consumeWhitespace(tokens)) {
if (previousToken?.typ != exports.EnumToken.ParensTokenType) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0] ?? previousToken ?? atRule,
syntax: '@' + atRule.nam,
error: 'expected whitespace',
tokens: []
};
}
}
if (![exports.EnumToken.MediaFeatureOrTokenType, exports.EnumToken.MediaFeatureAndTokenType].includes(tokens[0].typ)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0] ?? atRule,
syntax: '@' + atRule.nam,
error: 'expected and/or',
tokens: []
};
}
if (tokens.length == 1) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0] ?? atRule,
syntax: '@' + atRule.nam,
error: 'expected supports-condition',
tokens: []
};
}
tokens.shift();
if (!consumeWhitespace(tokens)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0] ?? atRule,
syntax: '@' + atRule.nam,
error: 'expected whitespace',
tokens: []
};
}
}
}
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: '',
tokens: []
};
}
function validateSupportCondition(atRule, token) {
if (token.typ == exports.EnumToken.MediaFeatureNotTokenType) {
return validateSupportCondition(atRule, token.val);
}
if (token.typ != exports.EnumToken.ParensTokenType && !(['when', 'else'].includes(atRule.nam) && token.typ == exports.EnumToken.FunctionTokenType && ['supports', 'font-format', 'font-tech'].includes(token.val))) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: token,
syntax: '@' + atRule.nam,
error: 'expected supports condition-in-parens',
tokens: []
};
}
const chi = token.chi.filter((t) => t.typ != exports.EnumToken.CommentTokenType && t.typ != exports.EnumToken.WhitespaceTokenType);
if (chi.length != 1) {
return validateAtRuleSupportsConditions(atRule, token.chi);
}
if (chi[0].typ == exports.EnumToken.IdenTokenType) {
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: null,
syntax: '@' + atRule.nam,
error: '',
tokens: []
};
}
if (chi[0].typ == exports.EnumToken.MediaFeatureNotTokenType) {
return validateSupportCondition(atRule, chi[0].val);
}
if (chi[0].typ == exports.EnumToken.MediaQueryConditionTokenType) {
// @ts-ignore
return chi[0].l.typ == exports.EnumToken.IdenTokenType && chi[0].op.typ == exports.EnumToken.ColonTokenType ?
{
valid: ValidationLevel.Valid,
matches: [],
node: null,
syntax: 'supports-condition',
error: '',
tokens: []
} : {
valid: ValidationLevel.Drop,
matches: [],
node: token,
syntax: 'supports-condition',
error: 'expected supports condition-in-parens',
tokens: []
};
}
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: token,
syntax: 'supports-condition',
error: 'expected supports condition-in-parens',
tokens: []
};
}
function validateSupportFeature(token) {
if (token.typ == exports.EnumToken.FunctionTokenType) {
if (token.val.localeCompare('selector', undefined, { sensitivity: 'base' }) == 0) {
return validateComplexSelector(parseSelector(token.chi));
}
if (token.val.localeCompare('font-tech', undefined, { sensitivity: 'base' }) == 0) {
const chi = token.chi.filter((t) => ![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType].includes(t.typ));
// @ts-ignore
return chi.length == 1 && chi[0].typ == exports.EnumToken.IdenTokenType && colorFontTech.concat(fontFeaturesTech).some((t) => t.localeCompare(chi[0].val, undefined, { sensitivity: 'base' }) == 0) ?
{
valid: ValidationLevel.Valid,
matches: [],
node: token,
syntax: 'font-tech',
error: '',
tokens: []
} :
{
valid: ValidationLevel.Drop,
matches: [],
node: token,
syntax: 'font-tech',
error: 'expected font-tech',
tokens: []
};
}
if (token.val.localeCompare('font-format', undefined, { sensitivity: 'base' }) == 0) {
const chi = token.chi.filter((t) => ![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType].includes(t.typ));
// @ts-ignore
return chi.length == 1 && chi[0].typ == exports.EnumToken.IdenTokenType && fontFormat.some((t) => t.localeCompare(chi[0].val, undefined, { sensitivity: 'base' }) == 0) ?
{
valid: ValidationLevel.Valid,
matches: [],
node: token,
syntax: 'font-format',
error: '',
tokens: []
} :
{
valid: ValidationLevel.Drop,
matches: [],
node: token,
syntax: 'font-format',
error: 'expected font-format',
tokens: []
};
}
}
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: token,
syntax: '@supports',
error: 'expected feature',
tokens: []
};
}
function validateAtRuleImport(atRule, options, root) {
if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: null,
syntax: '@' + atRule.nam,
error: 'expected @import media query list',
tokens: []
};
}
if ('chi' in atRule) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: null,
syntax: '@' + atRule.nam,
error: 'unexpected at-rule body',
tokens: []
};
}
const tokens = atRule.tokens.filter((t) => ![exports.EnumToken.CommentTokenType].includes(t.typ));
if (tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: null,
syntax: '@' + atRule.nam,
error: 'expected @import media query list',
tokens: []
};
}
if (tokens[0].typ == exports.EnumToken.StringTokenType) {
tokens.shift();
// @ts-ignore
consumeWhitespace(tokens);
}
else if (tokens[0].typ == exports.EnumToken.UrlFunctionTokenType) {
const slice = tokens[0].chi.filter((t) => t.typ != exports.EnumToken.CommentTokenType && t.typ != exports.EnumToken.WhitespaceTokenType);
if (slice.length != 1 || ![exports.EnumToken.StringTokenType, exports.EnumToken.UrlTokenTokenType].includes(slice[0].typ)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: '@' + atRule.nam,
error: 'invalid url()',
tokens
};
}
else {
tokens.shift();
// @ts-ignore
if (!consumeWhitespace(tokens)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: '@' + atRule.nam,
error: 'expecting whitespace',
tokens
};
}
}
tokens.shift();
// @ts-ignore
consumeWhitespace(tokens);
}
else {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: '@' + atRule.nam,
error: 'expecting url() or string',
tokens
};
}
if (tokens.length > 0) {
// @ts-ignore
if (tokens[0].typ == exports.EnumToken.IdenTokenType) {
// @ts-ignore
if ('layer'.localeCompare(tokens[0].val, undefined, { sensitivity: 'base' }) == 0) {
tokens.shift();
// @ts-ignore
if (!consumeWhitespace(tokens)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: '@' + atRule.nam,
error: 'expecting whitespace',
tokens
};
}
}
}
// @ts-ignore
else if (tokens[0].typ == exports.EnumToken.FunctionTokenType) {
// @ts-ignore
if ('layer'.localeCompare(tokens[0].val, undefined, { sensitivity: 'base' }) == 0) {
const result = validateLayerName(tokens[0].chi);
if (result.valid == ValidationLevel.Drop) {
return result;
}
tokens.shift();
// @ts-ignore
consumeWhitespace(tokens);
}
// @ts-ignore
if ('supports'.localeCompare(tokens[0]?.val, undefined, { sensitivity: 'base' }) == 0) {
const result = validateAtRuleSupportsConditions(atRule, tokens[0].chi);
if (result.valid == ValidationLevel.Drop) {
return result;
}
tokens.shift();
// @ts-ignore
consumeWhitespace(tokens);
}
}
}
// if (tokens.length > 0) {
//
// // @ts-ignore
// if (tokens[0].typ == EnumToken.AtRuleTokenType) {
//
// if ((tokens[0] as AstAtRule).nam != 'supports') {
//
// // @ts-ignore
// return {
// valid: ValidationLevel.Drop,
// matches: [],
// node: tokens[0],
// syntax: '@' + atRule.nam,
// error: 'expecting @supports or media query list',
// tokens
// }
// }
//
// // @ts-ignore
// const result: ValidationSyntaxResult = validateAtRuleSupports(tokens[0] as AstAtRule, options, atRule);
//
// if (result.valid == ValidationLevel.Drop) {
//
// return result;
// }
//
// tokens.shift();
//
// // @ts-ignore
// if (!consumeWhitespace(tokens)) {
//
// // @ts-ignore
// return {
// valid: ValidationLevel.Drop,
// matches: [],
// node: tokens[0],
// syntax: '@' + atRule.nam,
// error: 'expecting whitespace',
// tokens
// }
// }
// }
// }
if (tokens.length > 0) {
return validateAtRuleMediaQueryList(tokens, atRule);
}
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: null,
syntax: '@' + atRule.nam,
error: '',
tokens: []
};
}
function validateAtRuleLayer(atRule, options, root) {
// media-query-list
if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@layer',
error: '',
tokens: []
};
}
return validateLayerName(atRule.tokens);
}
function validateAtRuleFontFeatureValues(atRule, options, root) {
if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: null,
syntax: '@' + atRule.nam,
error: 'expected at-rule prelude',
tokens: []
};
}
const result = validateFamilyName(atRule.tokens, atRule);
if (result.valid == ValidationLevel.Drop) {
return result;
}
if (!('chi' in atRule)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: 'expected at-rule body',
tokens: []
};
}
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: '',
tokens: []
};
}
function validateAtRuleNamespace(atRule, options, root) {
if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@namespace',
error: 'expected at-rule prelude',
tokens: []
};
}
if ('chi' in atRule) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@namespace',
error: 'unexpected at-rule body',
tokens: []
};
}
const tokens = atRule.tokens.slice();
consumeWhitespace(tokens);
if (tokens[0].typ == exports.EnumToken.IdenTokenType) {
tokens.shift();
consumeWhitespace(tokens);
}
if (tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@namespace',
error: 'expected string or url()',
tokens
};
}
if (tokens[0].typ != exports.EnumToken.StringTokenType) {
const result = validateURL(tokens[0]);
if (result.valid != ValidationLevel.Valid) {
return result;
}
tokens.shift();
consumeWhitespace(tokens);
}
else {
tokens.shift();
consumeWhitespace(tokens);
}
if (tokens.length > 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: '@namespace',
error: 'unexpected token',
tokens
};
}
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@namespace',
error: '',
tokens
};
}
function validateAtRuleDocument(atRule, options, root) {
if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@document',
error: 'expecting at-rule prelude',
tokens: []
};
}
const tokens = atRule.tokens.slice();
let result = null;
consumeWhitespace(tokens);
if (tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@document',
error: 'expecting at-rule prelude',
tokens
};
}
for (const t of splitTokenList(tokens)) {
if (t.length != 1) {
return {
valid: ValidationLevel.Drop,
matches: [],
node: t[0] ?? atRule,
syntax: '@document',
error: 'unexpected token',
tokens
};
}
// @ts-ignore
if ((t[0].typ != exports.EnumToken.FunctionTokenType && t[0].typ != exports.EnumToken.UrlFunctionTokenType) || !['url', 'url-prefix', 'domain', 'media-document', 'regexp'].some((f) => f.localeCompare(t[0].val, undefined, { sensitivity: 'base' }) == 0)) {
return {
valid: ValidationLevel.Drop,
matches: [],
node: t[0] ?? atRule,
syntax: '@document',
error: 'expecting any of url-prefix(), domain(), media-document(), regexp() but found ' + t[0].val,
tokens
};
}
if (t[0].typ == exports.EnumToken.UrlFunctionTokenType) {
result = validateURL(t[0]);
if (result.valid == ValidationLevel.Drop) {
return result;
}
continue;
}
const children = t[0].chi.slice();
consumeWhitespace(children);
if (children.length != 1 || (children[0].typ != exports.EnumToken.StringTokenType && children[0].typ != exports.EnumToken.UrlTokenTokenType)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: '@document',
error: 'expecting string argument',
tokens
};
}
tokens.shift();
consumeWhitespace(tokens);
}
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@document',
error: '',
tokens
};
}
function validateAtRuleKeyframes(atRule, options, root) {
if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@document',
error: 'expecting at-rule prelude',
tokens: []
};
}
const tokens = atRule.tokens.slice();
consumeWhitespace(tokens);
if (tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@keyframes',
error: 'expecting at-rule prelude',
tokens
};
}
if (![exports.EnumToken.StringTokenType, exports.EnumToken.IdenTokenType].includes(tokens[0].typ)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@keyframes',
error: 'expecting ident or string token',
tokens
};
}
tokens.shift();
consumeWhitespace(tokens);
if (tokens.length > 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: '@keyframes',
error: 'unexpected token',
tokens
};
}
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@keyframes',
error: '',
tokens
};
}
function validateAtRuleWhen(atRule, options, root) {
const slice = Array.isArray(atRule.tokens) ? atRule.tokens.slice() : [];
consumeWhitespace(slice);
if (slice.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@when',
error: '',
tokens: []
};
}
const result = validateAtRuleWhenQueryList(atRule.tokens, atRule);
if (result.valid == ValidationLevel.Drop) {
return result;
}
if (!('chi' in atRule)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@when',
error: 'expected at-rule body',
tokens: []
};
}
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@when',
error: '',
tokens: result.tokens
};
}
// media() = media( [ <mf-plain> | <mf-boolean> | <mf-range> ] )
// supports() = supports( <declaration> )
function validateAtRuleWhenQueryList(tokenList, atRule) {
const matched = [];
let result = null;
for (const split of splitTokenList(tokenList)) {
const match = [];
result = null;
consumeWhitespace(split);
if (split.length == 0) {
continue;
}
while (split.length > 0) {
if (split[0].typ != exports.EnumToken.FunctionTokenType || !['media', 'supports', 'font-tech', 'font-format'].includes(split[0].val)) {
result = {
valid: ValidationLevel.Drop,
matches: [],
node: split[0] ?? atRule,
syntax: '@when',
error: 'unexpected token',
tokens: []
};
break;
}
const chi = split[0].chi.slice();
consumeWhitespace(chi);
if (split[0].val == 'media') {
// result = valida
if (chi.length != 1 || !(validateMediaFeature(chi[0]) || validateMediaCondition(split[0], atRule))) {
result = {
valid: ValidationLevel.Drop,
matches: [],
node: split[0] ?? atRule,
syntax: 'media( [ <mf-plain> | <mf-boolean> | <mf-range> ] )',
error: 'unexpected token',
tokens: []
};
break;
}
}
else if (['supports', 'font-tech', 'font-format'].includes(split[0].val)) {
// result = valida
if (!validateSupportCondition(atRule, split[0])) {
result = {
valid: ValidationLevel.Drop,
matches: [],
node: split[0] ?? atRule,
syntax: 'media( [ <mf-plain> | <mf-boolean> | <mf-range> ] )',
error: 'unexpected token',
tokens: []
};
break;
}
}
if (match.length > 0) {
match.push({ typ: exports.EnumToken.WhitespaceTokenType });
}
match.push(split.shift());
consumeWhitespace(split);
if (split.length == 0) {
break;
}
if (![exports.EnumToken.MediaFeatureAndTokenType, exports.EnumToken.MediaFeatureOrTokenType].includes(split[0].typ)) {
result = {
valid: ValidationLevel.Drop,
matches: [],
node: split[0] ?? atRule,
syntax: '@when',
error: 'expecting and/or media-condition',
tokens: []
};
break;
}
if (match.length > 0) {
match.push({ typ: exports.EnumToken.WhitespaceTokenType });
}
match.push(split.shift());
consumeWhitespace(split);
if (split.length == 0) {
result = {
valid: ValidationLevel.Drop,
matches: [],
node: split[0] ?? atRule,
syntax: '@when',
error: 'expecting media-condition',
tokens: []
};
break;
}
}
if (result == null && match.length > 0) {
matched.push(match);
}
}
if (result != null) {
return result;
}
if (matched.length == 0) {
return {
valid: ValidationLevel.Drop,
matches: [],
// @ts-ignore
node: result?.node ?? atRule,
syntax: '@when',
error: 'invalid at-rule body',
tokens: []
};
}
tokenList.length = 0;
for (const match of matched) {
if (tokenList.length > 0) {
tokenList.push({
typ: exports.EnumToken.CommaTokenType
});
}
tokenList.push(...match);
}
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@when',
error: '',
tokens: tokenList
};
}
const validateAtRuleElse = validateAtRuleWhen;
const validateContainerScrollStateFeature = validateContainerSizeFeature;
function validateAtRuleContainer(atRule, options, root) {
// media-query-list
if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: 'expected supports query list',
tokens: []
};
}
const result = validateAtRuleContainerQueryList(atRule.tokens, atRule);
if (result.valid == ValidationLevel.Drop) {
return result;
}
if (!('chi' in atRule)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: 'expected at-rule body',
tokens: []
};
}
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: '',
tokens: []
};
}
function validateAtRuleContainerQueryList(tokens, atRule) {
if (tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: 'expected container query list',
tokens
};
}
let result = null;
let tokenType = null;
for (const queries of splitTokenList(tokens)) {
consumeWhitespace(queries);
if (queries.length == 0) {
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: 'expected container query list',
tokens
};
}
result = null;
const match = [];
let token = null;
tokenType = null;
while (queries.length > 0) {
if (queries.length == 0) {
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: 'expected container query list',
tokens
};
}
if (queries[0].typ == exports.EnumToken.IdenTokenType) {
match.push(queries.shift());
consumeWhitespace(queries);
}
if (queries.length == 0) {
break;
}
token = queries[0];
if (token.typ == exports.EnumToken.MediaFeatureNotTokenType) {
token = token.val;
}
if (token.typ != exports.EnumToken.ParensTokenType && (token.typ != exports.EnumToken.FunctionTokenType || !['scroll-state', 'style'].includes(token.val))) {
return {
valid: ValidationLevel.Drop,
matches: [],
node: queries[0],
syntax: '@' + atRule.nam,
error: 'expected container query-in-parens',
tokens
};
}
if (token.typ == exports.EnumToken.ParensTokenType) {
result = validateContainerSizeFeature(token.chi, atRule);
}
else if (token.val == 'scroll-state') {
result = validateContainerScrollStateFeature(token.chi, atRule);
}
else {
result = validateContainerStyleFeature(token.chi, atRule);
}
if (result.valid == ValidationLevel.Drop) {
return result;
}
queries.shift();
consumeWhitespace(queries);
if (queries.length == 0) {
break;
}
token = queries[0];
if (token.typ != exports.EnumToken.MediaFeatureAndTokenType && token.typ != exports.EnumToken.MediaFeatureOrTokenType) {
return {
valid: ValidationLevel.Drop,
matches: [],
node: queries[0],
syntax: '@' + atRule.nam,
error: 'expecting and/or container query token',
tokens
};
}
if (tokenType == null) {
tokenType = token.typ;
}
if (tokenType != token.typ) {
return {
valid: ValidationLevel.Drop,
matches: [],
node: queries[0],
syntax: '@' + atRule.nam,
error: 'mixing and/or not allowed at the same level',
tokens
};
}
queries.shift();
consumeWhitespace(queries);
if (queries.length == 0) {
return {
valid: ValidationLevel.Drop,
matches: [],
node: queries[0],
syntax: '@' + atRule.nam,
error: 'expected container query-in-parens',
tokens
};
}
}
}
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: '',
tokens
};
}
function validateContainerStyleFeature(tokens, atRule) {
tokens = tokens.slice();
consumeWhitespace(tokens);
if (tokens.length == 1) {
if (tokens[0].typ == exports.EnumToken.ParensTokenType) {
return validateContainerStyleFeature(tokens[0].chi, atRule);
}
if ([exports.EnumToken.DashedIdenTokenType, exports.EnumToken.IdenTokenType].includes(tokens[0].typ) ||
(tokens[0].typ == exports.EnumToken.MediaQueryConditionTokenType && tokens[0].op.typ == exports.EnumToken.ColonTokenType)) {
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: '',
tokens
};
}
}
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: 'expected container query features',
tokens
};
}
function validateContainerSizeFeature(tokens, atRule) {
tokens = tokens.slice();
consumeWhitespace(tokens);
if (tokens.length == 0) {
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: 'expected container query features',
tokens
};
}
if (tokens.length == 1) {
const token = tokens[0];
if (token.typ == exports.EnumToken.MediaFeatureNotTokenType) {
return validateContainerSizeFeature([token.val], atRule);
}
if (token.typ == exports.EnumToken.ParensTokenType) {
return validateAtRuleContainerQueryStyleInParams(token.chi, atRule);
}
if (![exports.EnumToken.DashedIdenTokenType, exports.EnumToken.MediaQueryConditionTokenType].includes(tokens[0].typ)) {
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: 'expected container query features',
tokens
};
}
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: '',
tokens
};
}
return validateAtRuleContainerQueryStyleInParams(tokens, atRule);
}
function validateAtRuleContainerQueryStyleInParams(tokens, atRule) {
tokens = tokens.slice();
consumeWhitespace(tokens);
if (tokens.length == 0) {
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: 'expected container query features',
tokens
};
}
let token = tokens[0];
let tokenType = null;
let result = null;
while (tokens.length > 0) {
token = tokens[0];
if (token.typ == exports.EnumToken.MediaFeatureNotTokenType) {
token = token.val;
}
if (tokens[0].typ != exports.EnumToken.ParensTokenType) {
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: 'expected container query-in-parens',
tokens
};
}
const slices = tokens[0].chi.slice();
consumeWhitespace(slices);
if (slices.length == 1) {
if ([exports.EnumToken.MediaFeatureNotTokenType, exports.EnumToken.ParensTokenType].includes(slices[0].typ)) {
result = validateAtRuleContainerQueryStyleInParams(slices, atRule);
if (result.valid == ValidationLevel.Drop) {
return result;
}
}
else if (![exports.EnumToken.DashedIdenTokenType, exports.EnumToken.MediaQueryConditionTokenType].includes(slices[0].typ)) {
result = {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: 'expected container query features',
tokens
};
}
}
else {
result = validateAtRuleContainerQueryStyleInParams(slices, atRule);
if (result.valid == ValidationLevel.Drop) {
return result;
}
}
tokens.shift();
consumeWhitespace(tokens);
if (tokens.length == 0) {
break;
}
if (![exports.EnumToken.MediaFeatureAndTokenType, exports.EnumToken.MediaFeatureOrTokenType].includes(tokens[0].typ)) {
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: '@' + atRule.nam,
error: 'expecting and/or container query token',
tokens
};
}
if (tokenType == null) {
tokenType = tokens[0].typ;
}
if (tokenType != tokens[0].typ) {
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: '@' + atRule.nam,
error: 'mixing and/or not allowed at the same level',
tokens
};
}
tokens.shift();
consumeWhitespace(tokens);
if (tokens.length == 0) {
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: '@' + atRule.nam,
error: 'expected container query-in-parens',
tokens
};
}
}
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: '',
tokens
};
}
function validateAtRuleCustomMedia(atRule, options, root) {
// media-query-list
if (!Array.isArray(atRule.tokens) || atRule.tokens.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Valid,
matches: [],
node: null,
syntax: null,
error: '',
tokens: []
};
}
const queries = atRule.tokens.slice();
consumeWhitespace(queries);
if (queries.length == 0 || queries[0].typ != exports.EnumToken.DashedIdenTokenType) {
return {
valid: ValidationLevel.Drop,
matches: [],
node: atRule,
syntax: '@custom-media',
error: 'expecting dashed identifier',
tokens: []
};
}
queries.shift();
const result = validateAtRuleMediaQueryList(queries, atRule);
if (result.valid == ValidationLevel.Drop) {
atRule.tokens = [];
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@custom-media',
error: '',
tokens: []
};
}
return result;
}
function validateAtRule(atRule, options, root) {
if (atRule.nam == 'charset') {
const valid = atRule.val.match(/^"[a-zA-Z][a-zA-Z0-9_-]+"$/i) != null;
return {
valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
node: atRule,
syntax: null,
error: ''
};
}
if (atRule.nam == 'keyframes') {
return validateAtRuleKeyframes(atRule);
}
if (['font-face', 'view-transition', 'starting-style'].includes(atRule.nam)) {
return {
valid: ValidationLevel.Valid,
node: atRule,
syntax: '@' + atRule.nam,
error: ''
};
}
if (atRule.nam == 'media') {
return validateAtRuleMedia(atRule);
}
if (atRule.nam == 'import') {
return validateAtRuleImport(atRule);
}
if (atRule.nam == 'supports') {
return validateAtRuleSupports(atRule);
}
if (atRule.nam == 'counter-style') {
return validateAtRuleCounterStyle(atRule);
}
if (atRule.nam == 'layer') {
return validateAtRuleLayer(atRule);
}
if (atRule.nam == 'font-feature-values') {
return validateAtRuleFontFeatureValues(atRule);
}
if (atRule.nam == 'namespace') {
return validateAtRuleNamespace(atRule);
}
if (atRule.nam == 'when') {
return validateAtRuleWhen(atRule);
}
if (atRule.nam == 'else') {
return validateAtRuleElse(atRule);
}
if (atRule.nam == 'container') {
return validateAtRuleContainer(atRule);
}
if (atRule.nam == 'document') {
return validateAtRuleDocument(atRule);
}
if (atRule.nam == 'custom-media') {
return validateAtRuleCustomMedia(atRule);
}
if (['position-try', 'property', 'font-palette-values'].includes(atRule.nam)) {
if (!('tokens' in atRule)) {
return {
valid: ValidationLevel.Drop,
node: atRule,
syntax: '@' + atRule.nam,
error: 'expected prelude'
};
}
if (!('chi' in atRule)) {
return {
valid: ValidationLevel.Drop,
node: atRule,
syntax: '@' + atRule.nam,
error: 'expected body'
};
}
const chi = atRule.tokens.filter((t) => t.typ != exports.EnumToken.WhitespaceTokenType && t.typ != exports.EnumToken.CommentTokenType);
if (chi.length != 1) {
return {
valid: ValidationLevel.Drop,
node: atRule,
syntax: '@' + atRule.nam,
error: 'expected ' + (atRule.nam == 'property' ? 'custom-property-name' : 'dashed-ident')
};
}
if (chi[0].typ != exports.EnumToken.DashedIdenTokenType) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
node: atRule,
syntax: '@' + atRule.nam,
error: 'expected ' + (atRule.nam == 'property' ? 'custom-property-name' : 'dashed-ident')
};
}
// @ts-ignore
return {
valid: ValidationLevel.Valid,
node: atRule,
syntax: '@' + atRule.nam,
error: ''
};
}
// scope
if (atRule.nam == 'page') {
return validateAtRulePage(atRule);
}
if (['top-left-corner', 'top-left', 'top-center', 'top-right', 'top-right-corner', 'bottom-left-corner', 'bottom-left', 'bottom-center', 'bottom-right', 'bottom-right-corner', 'left-top', 'left-middle', 'left-bottom', 'right-top', 'right-middle', 'right-bottom'].includes(atRule.nam)) {
if (!(root == null || (root.typ == exports.EnumToken.AtRuleNodeType && root.nam == 'page'))) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
node: atRule,
syntax: '@page',
error: 'not allowed here'
};
}
return validateAtRulePageMarginBox(atRule);
}
// handle keyframe as special case
// check if the node exists
const config = getSyntaxConfig();
let name = '@' + atRule.nam;
if (!(name in config.atRules)) {
if (name.charAt(1) == '-') {
name = name.replace(/@-[a-zA-Z]+-([a-zA-Z][a-zA-Z0-9_-]*)/, '@$1');
}
}
if (!(name in config.atRules)) {
if (options.lenient) {
return {
valid: ValidationLevel.Lenient,
node: atRule,
syntax: null,
error: ''
};
}
return {
valid: ValidationLevel.Drop,
node: atRule,
syntax: null,
error: 'unknown at-rule'
};
}
const syntax = getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, name)?.[0];
if ('chi' in syntax && !('chi' in atRule)) {
return {
valid: ValidationLevel.Drop,
node: atRule,
syntax,
error: 'missing at-rule body'
};
}
// if ('prelude' in syntax) {
//
// return validateSyntax(syntax.prelude as ValidationToken[], atRule.tokens as Token[], root, options);
// }
return {
valid: ValidationLevel.Valid,
node: null,
syntax,
error: ''
};
}
const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
const trimWhiteSpace = [exports.EnumToken.CommentTokenType, exports.EnumToken.GtTokenType, exports.EnumToken.GteTokenType, exports.EnumToken.LtTokenType, exports.EnumToken.LteTokenType, exports.EnumToken.ColumnCombinatorTokenType];
const BadTokensTypes = [
exports.EnumToken.BadCommentTokenType,
exports.EnumToken.BadCdoTokenType,
exports.EnumToken.BadUrlTokenType,
exports.EnumToken.BadStringTokenType
];
const enumTokenHints = new Set([
exports.EnumToken.WhitespaceTokenType, exports.EnumToken.SemiColonTokenType, exports.EnumToken.ColonTokenType, exports.EnumToken.BlockStartTokenType,
exports.EnumToken.BlockStartTokenType, exports.EnumToken.AttrStartTokenType, exports.EnumToken.AttrEndTokenType, exports.EnumToken.StartParensTokenType, exports.EnumToken.EndParensTokenType,
exports.EnumToken.CommaTokenType, exports.EnumToken.GtTokenType, exports.EnumToken.LtTokenType, exports.EnumToken.GteTokenType, exports.EnumToken.LteTokenType, exports.EnumToken.CommaTokenType,
exports.EnumToken.StartMatchTokenType, exports.EnumToken.EndMatchTokenType, exports.EnumToken.IncludeMatchTokenType, exports.EnumToken.DashMatchTokenType, exports.EnumToken.ContainMatchTokenType,
exports.EnumToken.EOFTokenType
]);
function reject(reason) {
throw new Error(reason ?? 'Parsing aborted');
}
/**
* parse css string
* @param iterator
* @param options
*/
async function doParse(iterator, options = {}) {
if (options.signal != null) {
options.signal.addEventListener('abort', reject);
}
options = {
src: '',
sourcemap: false,
minify: true,
pass: 1,
parseColor: true,
nestingRules: false,
resolveImport: false,
resolveUrls: false,
removeCharset: true,
removeEmpty: true,
removeDuplicateDeclarations: true,
computeShorthand: true,
computeCalcExpression: true,
inlineCssVariables: false,
setParent: true,
removePrefix: false,
validation: true,
lenient: true,
...options
};
if (options.expandNestingRules) {
options.nestingRules = false;
}
if (options.resolveImport) {
options.resolveUrls = true;
}
const startTime = performance.now();
const errors = [];
const src = options.src;
const stack = [];
const stats = {
bytesIn: 0,
importedBytesIn: 0,
parse: `0ms`,
minify: `0ms`,
total: `0ms`
};
let ast = {
typ: exports.EnumToken.StyleSheetNodeType,
chi: []
};
let tokens = [];
let map = new Map;
let context = ast;
if (options.sourcemap) {
ast.loc = {
sta: {
ind: 0,
lin: 1,
col: 1
},
src: ''
};
}
const iter = tokenize$1(iterator);
let item;
const rawTokens = [];
while (item = iter.next().value) {
stats.bytesIn = item.bytesIn;
rawTokens.push(item);
// doParse error
if (item.hint != null && BadTokensTypes.includes(item.hint)) {
// bad token
continue;
}
if (item.hint != exports.EnumToken.EOFTokenType) {
tokens.push(item);
}
if (item.token == ';' || item.token == '{') {
let node = await parseNode(tokens, context, stats, options, errors, src, map, rawTokens);
rawTokens.length = 0;
if (node != null) {
// @ts-ignore
stack.push(node);
// @ts-ignore
context = node;
}
else if (item.token == '{') {
let inBlock = 1;
do {
item = iter.next().value;
if (item == null) {
break;
}
if (item.token == '{') {
inBlock++;
}
else if (item.token == '}') {
inBlock--;
}
} while (inBlock != 0);
}
tokens = [];
map = new Map;
}
else if (item.token == '}') {
await parseNode(tokens, context, stats, options, errors, src, map, rawTokens);
rawTokens.length = 0;
const previousNode = stack.pop();
// @ts-ignore
context = stack[stack.length - 1] ?? ast;
// @ts-ignore
if (previousNode != null && previousNode.typ == exports.EnumToken.InvalidRuleTokenType) {
// @ts-ignore
const index = context.chi.findIndex(node => node == previousNode);
if (index > -1) {
// @ts-ignore
context.chi.splice(index, 1);
}
}
// @ts-ignore
if (options.removeEmpty && previousNode != null && previousNode.chi.length == 0 && context.chi[context.chi.length - 1] == previousNode) {
// @ts-ignore
context.chi.pop();
}
tokens = [];
map = new Map;
}
}
if (tokens.length > 0) {
await parseNode(tokens, context, stats, options, errors, src, map, rawTokens);
rawTokens.length = 0;
if (context != null && context.typ == exports.EnumToken.InvalidRuleTokenType) {
const index = context.chi.findIndex((node) => node == context);
if (index > -1) {
context.chi.splice(index, 1);
}
}
}
while (stack.length > 0 && context != ast) {
const previousNode = stack.pop();
// @ts-ignore
context = stack[stack.length - 1] ?? ast;
// remove empty nodes
// @ts-ignore
if (options.removeEmpty && previousNode != null && previousNode.chi.length == 0 && context.chi[context.chi.length - 1] == previousNode) {
// @ts-ignore
context.chi.pop();
continue;
}
break;
}
const endParseTime = performance.now();
if (options.expandNestingRules) {
ast = expand(ast);
}
if (options.visitor != null) {
for (const result of walk(ast)) {
if (result.node.typ == exports.EnumToken.DeclarationNodeType &&
// @ts-ignore
(typeof options.visitor.Declaration == 'function' || options.visitor.Declaration?.[result.node.nam] != null)) {
const callable = typeof options.visitor.Declaration == 'function' ? options.visitor.Declaration : options.visitor.Declaration[result.node.nam];
const results = await callable(result.node);
if (results == null || (Array.isArray(results) && results.length == 0)) {
continue;
}
// @ts-ignore
result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
}
else if (options.visitor.Rule != null && result.node.typ == exports.EnumToken.RuleNodeType) {
const results = await options.visitor.Rule(result.node);
if (results == null || (Array.isArray(results) && results.length == 0)) {
continue;
}
// @ts-ignore
result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
}
else if (options.visitor.AtRule != null &&
result.node.typ == exports.EnumToken.AtRuleNodeType &&
// @ts-ignore
(typeof options.visitor.AtRule == 'function' || options.visitor.AtRule?.[result.node.nam] != null)) {
const callable = typeof options.visitor.AtRule == 'function' ? options.visitor.AtRule : options.visitor.AtRule[result.node.nam];
const results = await callable(result.node);
if (results == null || (Array.isArray(results) && results.length == 0)) {
continue;
}
// @ts-ignore
result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
}
}
}
if (options.minify) {
if (ast.chi.length > 0) {
let passes = options.pass ?? 1;
while (passes--) {
minify(ast, options, true, errors, false);
}
}
}
const endTime = performance.now();
if (options.signal != null) {
options.signal.removeEventListener('abort', reject);
}
stats.bytesIn += stats.importedBytesIn;
return {
ast,
errors,
stats: {
...stats,
parse: `${(endParseTime - startTime).toFixed(2)}ms`,
minify: `${(endTime - endParseTime).toFixed(2)}ms`,
total: `${(endTime - startTime).toFixed(2)}ms`
}
};
}
function getLastNode(context) {
let i = context.chi.length;
while (i--) {
if ([exports.EnumToken.CommentTokenType, exports.EnumToken.CDOCOMMTokenType, exports.EnumToken.WhitespaceTokenType].includes(context.chi[i].typ)) {
continue;
}
return context.chi[i];
}
return null;
}
async function parseNode(results, context, stats, options, errors, src, map, rawTokens) {
let tokens = [];
for (const t of results) {
const node = getTokenType(t.token, t.hint);
map.set(node, t.position);
tokens.push(node);
}
let i;
let loc;
for (i = 0; i < tokens.length; i++) {
if (tokens[i].typ == exports.EnumToken.CommentTokenType || tokens[i].typ == exports.EnumToken.CDOCOMMTokenType) {
const position = map.get(tokens[i]);
if (tokens[i].typ == exports.EnumToken.CDOCOMMTokenType && context.typ != exports.EnumToken.StyleSheetNodeType) {
errors.push({
action: 'drop',
message: `CDOCOMM not allowed here ${JSON.stringify(tokens[i], null, 1)}`,
location: { src, ...position }
});
continue;
}
loc = {
sta: position,
src
};
// @ts-ignore
context.chi.push(tokens[i]);
if (options.sourcemap) {
tokens[i].loc = loc;
}
}
else if (tokens[i].typ != exports.EnumToken.WhitespaceTokenType) {
break;
}
}
tokens = tokens.slice(i);
if (tokens.length == 0) {
return null;
}
let delim = tokens.at(-1);
if (delim.typ == exports.EnumToken.SemiColonTokenType || delim.typ == exports.EnumToken.BlockStartTokenType || delim.typ == exports.EnumToken.BlockEndTokenType) {
tokens.pop();
}
else {
delim = { typ: exports.EnumToken.SemiColonTokenType };
}
// @ts-ignore
while ([exports.EnumToken.WhitespaceTokenType, exports.EnumToken.BadStringTokenType, exports.EnumToken.BadCommentTokenType].includes(tokens.at(-1)?.typ)) {
tokens.pop();
}
if (tokens.length == 0) {
return null;
}
if (tokens[0]?.typ == exports.EnumToken.AtRuleTokenType) {
const atRule = tokens.shift();
const position = map.get(atRule);
// @ts-ignore
while ([exports.EnumToken.WhitespaceTokenType].includes(tokens[0]?.typ)) {
tokens.shift();
}
if (atRule.val == 'import') {
// only @charset and @layer are accepted before @import
// @ts-ignore
if (context.chi.length > 0) {
// @ts-ignore
let i = context.chi.length;
while (i--) {
// @ts-ignore
const type = context.chi[i].typ;
if (type == exports.EnumToken.CommentNodeType) {
continue;
}
if (type != exports.EnumToken.AtRuleNodeType) {
// @ts-ignore
if (!(type == exports.EnumToken.InvalidAtRuleTokenType &&
// @ts-ignore
['charset', 'layer', 'import'].includes(context.chi[i].nam))) {
errors.push({ action: 'drop', message: 'invalid @import', location: { src, ...position } });
return null;
}
}
// @ts-ignore
const name = context.chi[i].nam;
if (name != 'charset' && name != 'import' && name != 'layer') {
errors.push({ action: 'drop', message: 'invalid @import', location: { src, ...position } });
return null;
}
break;
}
}
// @ts-ignore
if (tokens[0]?.typ != exports.EnumToken.StringTokenType && tokens[0]?.typ != exports.EnumToken.UrlFunctionTokenType) {
errors.push({
action: 'drop',
message: 'doParse: invalid @import',
location: { src, ...position }
});
return null;
}
// @ts-ignore
if (tokens[0].typ == exports.EnumToken.UrlFunctionTokenType && tokens[1]?.typ != exports.EnumToken.UrlTokenTokenType && tokens[1]?.typ != exports.EnumToken.StringTokenType) {
errors.push({
action: 'drop',
message: 'doParse: invalid @import',
location: { src, ...position }
});
return null;
}
}
if (atRule.val == 'import') {
// @ts-ignore
if (tokens[0].typ == exports.EnumToken.UrlFunctionTokenType) {
if (tokens[1].typ == exports.EnumToken.UrlTokenTokenType || tokens[1].typ == exports.EnumToken.StringTokenType) {
tokens.shift();
if (tokens[0]?.typ == exports.EnumToken.UrlTokenTokenType) {
// @ts-ignore
tokens[0].typ = exports.EnumToken.StringTokenType;
// @ts-ignore
tokens[0].val = `"${tokens[0].val}"`;
}
// @ts-ignore
while (tokens[1]?.typ == exports.EnumToken.WhitespaceTokenType || tokens[1]?.typ == exports.EnumToken.CommentTokenType) {
tokens.splice(1, 1);
}
// @ts-ignore
if (tokens[1]?.typ == exports.EnumToken.EndParensTokenType) {
tokens.splice(1, 1);
}
}
}
// @ts-ignore
if (tokens[0].typ == exports.EnumToken.StringTokenType) {
if (options.resolveImport) {
const url = tokens[0].val.slice(1, -1);
try {
// @ts-ignore
const root = await options.load(url, options.src).then((src) => {
return doParse(src, Object.assign({}, options, {
minify: false,
setParent: false,
// @ts-ignore
src: options.resolve(url, options.src).absolute
}));
});
stats.importedBytesIn += root.stats.bytesIn;
if (root.ast.chi.length > 0) {
// @todo - filter charset, layer and scope
// @ts-ignore
context.chi.push(...root.ast.chi);
}
if (root.errors.length > 0) {
errors.push(...root.errors);
}
return null;
}
catch (error) {
// @ts-ignore
errors.push({ action: 'ignore', message: 'doParse: ' + error.message, error });
}
}
}
}
// https://www.w3.org/TR/css-nesting-1/#conditionals
// allowed nesting at-rules
// there must be a top level rule in the stack
if (atRule.val == 'charset') {
let spaces = 0;
// https://developer.mozilla.org/en-US/docs/Web/CSS/@charset
for (let k = 1; k < rawTokens.length; k++) {
if (rawTokens[k].hint == exports.EnumToken.WhitespaceTokenType) {
spaces += rawTokens[k].len;
continue;
}
if (rawTokens[k].hint == exports.EnumToken.CommentTokenType) {
continue;
}
if (rawTokens[k].hint == exports.EnumToken.CDOCOMMTokenType) {
continue;
}
if (spaces > 1) {
errors.push({
action: 'drop',
message: '@charset must have only one space',
// @ts-ignore
location: { src, ...(map.get(atRule) ?? position) }
});
return null;
}
if (rawTokens[k].hint != exports.EnumToken.StringTokenType || rawTokens[k].token[0] != '"') {
errors.push({
action: 'drop',
message: '@charset expects a "<charset>"',
// @ts-ignore
location: { src, ...(map.get(atRule) ?? position) }
});
return null;
}
break;
}
if (options.removeCharset) {
return null;
}
}
const t = parseAtRulePrelude(parseTokens(tokens, { minify: options.minify }), atRule);
const raw = t.reduce((acc, curr) => {
acc.push(renderToken(curr, { removeComments: true }));
return acc;
}, []);
const node = {
typ: exports.EnumToken.AtRuleNodeType,
nam: renderToken(atRule, { removeComments: true }),
// tokens: t,
val: raw.join('')
};
Object.defineProperties(node, {
tokens: { ...definedPropertySettings, enumerable: false, value: tokens.slice() },
raw: { ...definedPropertySettings, value: raw }
});
if (delim.typ == exports.EnumToken.BlockStartTokenType) {
node.chi = [];
}
loc = {
sta: position,
src
};
if (options.sourcemap) {
node.loc = loc;
}
if (options.validation) {
let isValid = true;
if (node.nam == 'else') {
const prev = getLastNode(context);
if (prev != null && prev.typ == exports.EnumToken.AtRuleNodeType && ['when', 'else'].includes(prev.nam)) {
if (prev.nam == 'else') {
isValid = Array.isArray(prev.tokens) && prev.tokens.length > 0;
}
}
else {
isValid = false;
}
}
const valid = isValid ? validateAtRule(node, options, context) : {
valid: ValidationLevel.Drop,
node,
syntax: '@' + node.nam,
error: '@' + node.nam + ' not allowed here'};
if (valid.valid == ValidationLevel.Drop) {
errors.push({
action: 'drop',
message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
// @ts-ignore
location: { src, ...(map.get(valid.node) ?? position) }
});
// @ts-ignore
node.typ = exports.EnumToken.InvalidAtRuleTokenType;
}
else {
node.val = node.tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false, removeComments: true }), '');
}
}
// @ts-ignore
context.chi.push(node);
Object.defineProperty(node, 'parent', { ...definedPropertySettings, value: context });
return delim.typ == exports.EnumToken.BlockStartTokenType ? node : null;
}
else {
// rule
if (delim.typ == exports.EnumToken.BlockStartTokenType) {
const position = map.get(tokens[0]);
const uniq = new Map;
parseTokens(tokens, { minify: true }).reduce((acc, curr, index, array) => {
if (curr.typ == exports.EnumToken.CommentTokenType) {
return acc;
}
if (curr.typ == exports.EnumToken.WhitespaceTokenType) {
if (trimWhiteSpace.includes(array[index - 1]?.typ) ||
trimWhiteSpace.includes(array[index + 1]?.typ) ||
combinators.includes(array[index - 1]?.val) ||
combinators.includes(array[index + 1]?.val)) {
return acc;
}
}
let t = renderToken(curr, { minify: false });
if (t == ',') {
acc.push([]);
// uniqTokens.push([]);
}
else {
acc[acc.length - 1].push(t);
// uniqTokens[uniqTokens.length - 1].push(curr);
}
return acc;
}, [[]]).reduce((acc, curr) => {
let i = 0;
for (; i < curr.length; i++) {
if (i + 1 < curr.length && curr[i] == '*') {
if (curr[i] == '*') {
let index = curr[i + 1] == ' ' ? 2 : 1;
if (!['>', '~', '+'].includes(curr[index])) {
curr.splice(i, index);
}
}
}
}
acc.set(curr.join(''), curr);
return acc;
}, uniq);
const ruleType = context.typ == exports.EnumToken.AtRuleNodeType && context.nam == 'keyframes' ? exports.EnumToken.KeyFrameRuleNodeType : exports.EnumToken.RuleNodeType;
if (ruleType == exports.EnumToken.RuleNodeType) {
parseSelector(tokens);
if (options.validation) {
// @ts-ignore
const valid = validateSelector(tokens, options, context);
if (valid.valid != ValidationLevel.Valid) {
const node = {
typ: exports.EnumToken.InvalidRuleTokenType,
// @ts-ignore
sel: tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), ''),
chi: []
};
errors.push({
action: 'drop',
message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
// @ts-ignore
location: { src, ...(map.get(valid.node) ?? position) }
});
// @ts-ignore
context.chi.push(node);
Object.defineProperty(node, 'parent', { ...definedPropertySettings, value: context });
return node;
}
}
}
const node = {
typ: ruleType,
sel: [...uniq.keys()].join(','),
chi: []
};
Object.defineProperty(node, 'tokens', {
...definedPropertySettings,
enumerable: false,
value: tokens.slice()
});
let raw = [...uniq.values()];
Object.defineProperty(node, 'raw', {
enumerable: false,
configurable: true,
writable: true,
value: raw
});
loc = {
sta: position,
src
};
if (options.sourcemap) {
node.loc = loc;
}
// @ts-ignore
context.chi.push(node);
Object.defineProperty(node, 'parent', { ...definedPropertySettings, value: context });
return node;
}
else {
let name = null;
let value = null;
for (let i = 0; i < tokens.length; i++) {
if (tokens[i].typ == exports.EnumToken.CommentTokenType) {
continue;
}
if (name == null && [exports.EnumToken.IdenTokenType, exports.EnumToken.DashedIdenTokenType].includes(tokens[i].typ)) {
name = tokens.slice(0, i + 1);
}
else if (name != null && funcLike.concat([
exports.EnumToken.LiteralTokenType,
exports.EnumToken.IdenTokenType, exports.EnumToken.DashedIdenTokenType,
exports.EnumToken.PseudoClassTokenType, exports.EnumToken.PseudoClassFuncTokenType
]).includes(tokens[i].typ)) {
if (tokens[i].val.charAt(0) == ':') {
Object.assign(tokens[i], getTokenType(tokens[i].val.slice(1)));
}
if ('chi' in tokens[i]) {
tokens[i].typ = exports.EnumToken.FunctionTokenType;
}
value = parseTokens(tokens.slice(i), {
parseColor: options.parseColor,
src: options.src,
resolveUrls: options.resolveUrls,
resolve: options.resolve,
cwd: options.cwd
});
break;
}
if (tokens[i].typ == exports.EnumToken.ColonTokenType) {
name = tokens.slice(0, i);
value = parseTokens(tokens.slice(i + 1), {
parseColor: options.parseColor,
src: options.src,
resolveUrls: options.resolveUrls,
resolve: options.resolve,
cwd: options.cwd
});
break;
}
}
if (name == null) {
name = tokens;
}
const position = map.get(name[0]);
if (name.length > 0) {
for (let i = 1; i < name.length; i++) {
if (name[i].typ != exports.EnumToken.WhitespaceTokenType && name[i].typ != exports.EnumToken.CommentTokenType) {
errors.push({
action: 'drop',
message: 'doParse: invalid declaration',
location: { src, ...position }
});
return null;
}
}
}
if (value == null || value.length == 0) {
errors.push({
action: 'drop',
message: 'doParse: invalid declaration',
location: { src, ...position }
});
return null;
}
const node = {
typ: exports.EnumToken.DeclarationNodeType,
// @ts-ignore
nam: renderToken(name.shift(), { removeComments: true }),
// @ts-ignore
val: value
};
const result = parseDeclarationNode(node, errors, src, position);
if (result != null) {
// if (options.validation) {
//
// const valid: ValidationResult = validateDeclaration(result, options, context);
//
// // console.error({valid});
//
// if (valid.valid == ValidationLevel.Drop) {
//
// errors.push({
// action: 'drop',
// message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, {minify: false}), '') + '"',
// // @ts-ignore
// location: {src, ...(map.get(valid.node) ?? position)}
// });
//
// return null;
// }
// }
// @ts-ignore
context.chi.push(result);
Object.defineProperty(result, 'parent', { ...definedPropertySettings, value: context });
}
return null;
}
}
}
/**
* parse at-rule prelude
* @param tokens
* @param atRule
*/
function parseAtRulePrelude(tokens, atRule) {
// @ts-ignore
for (const { value, parent } of walkValues(tokens, null, null, true)) {
if (value.typ == exports.EnumToken.CommentTokenType ||
value.typ == exports.EnumToken.WhitespaceTokenType ||
value.typ == exports.EnumToken.CommaTokenType) {
continue;
}
if (atRule.val == 'page' && value.typ == exports.EnumToken.PseudoClassTokenType) {
if ([':left', ':right', ':first', ':blank'].includes(value.val)) {
// @ts-ignore
value.typ = exports.EnumToken.PseudoPageTokenType;
}
}
if (atRule.val == 'layer') {
if (parent == null && value.typ == exports.EnumToken.LiteralTokenType) {
if (value.val.charAt(0) == '.') {
if (isIdent(value.val.slice(1))) {
// @ts-ignore
value.typ = exports.EnumToken.ClassSelectorTokenType;
}
}
}
}
if (value.typ == exports.EnumToken.IdenTokenType) {
if (parent == null && mediaTypes.some((t) => {
if (value.val.localeCompare(t, 'en', { sensitivity: 'base' }) == 0) {
// @ts-ignore
value.typ = exports.EnumToken.MediaFeatureTokenType;
return true;
}
return false;
})) {
continue;
}
if (value.typ == exports.EnumToken.IdenTokenType && 'and'.localeCompare(value.val, 'en', { sensitivity: 'base' }) == 0) {
// @ts-ignore
value.typ = exports.EnumToken.MediaFeatureAndTokenType;
continue;
}
if (value.typ == exports.EnumToken.IdenTokenType && 'or'.localeCompare(value.val, 'en', { sensitivity: 'base' }) == 0) {
// @ts-ignore
value.typ = exports.EnumToken.MediaFeatureOrTokenType;
continue;
}
if (value.typ == exports.EnumToken.IdenTokenType &&
['not', 'only'].some((t) => t.localeCompare(value.val, 'en', { sensitivity: 'base' }) == 0)) {
// @ts-ignore
const array = parent?.chi ?? tokens;
const startIndex = array.indexOf(value);
let index = startIndex + 1;
if (index == 0) {
continue;
}
while (index < array.length && [exports.EnumToken.CommentTokenType, exports.EnumToken.WhitespaceTokenType].includes(array[index].typ)) {
index++;
}
if (array[index] == null || array[index].typ == exports.EnumToken.CommaTokenType) {
continue;
}
Object.assign(array[startIndex], {
typ: value.val.toLowerCase() == 'not' ? exports.EnumToken.MediaFeatureNotTokenType : exports.EnumToken.MediaFeatureOnlyTokenType,
val: array[index]
});
array.splice(startIndex + 1, index - startIndex);
continue;
}
}
if (value.typ == exports.EnumToken.ParensTokenType || (value.typ == exports.EnumToken.FunctionTokenType && ['media', 'supports', 'style', 'scroll-state'].includes(value.val))) {
// @todo parse range and declarations
// parseDeclaration(parent.chi);
let i;
let nameIndex = -1;
let valueIndex = -1;
const dashedIdent = value.typ == exports.EnumToken.FunctionTokenType && value.val == 'style';
for (let i = 0; i < value.chi.length; i++) {
if (value.chi[i].typ == exports.EnumToken.CommentTokenType || value.chi[i].typ == exports.EnumToken.WhitespaceTokenType) {
continue;
}
if ((dashedIdent && value.chi[i].typ == exports.EnumToken.DashedIdenTokenType) || value.chi[i].typ == exports.EnumToken.IdenTokenType || value.chi[i].typ == exports.EnumToken.FunctionTokenType || value.chi[i].typ == exports.EnumToken.ColorTokenType) {
nameIndex = i;
}
break;
}
if (nameIndex == -1) {
continue;
}
for (let i = nameIndex + 1; i < value.chi.length; i++) {
if (value.chi[i].typ == exports.EnumToken.CommentTokenType || value.chi[i].typ == exports.EnumToken.WhitespaceTokenType) {
continue;
}
valueIndex = i;
break;
}
if (valueIndex == -1) {
// @ts-ignore
// value.chi[nameIndex].typ = EnumToken.MediaFeatureTokenType;
continue;
// return tokens;
}
for (i = nameIndex + 1; i < value.chi.length; i++) {
if ([
exports.EnumToken.GtTokenType, exports.EnumToken.LtTokenType,
exports.EnumToken.GteTokenType, exports.EnumToken.LteTokenType,
exports.EnumToken.ColonTokenType
].includes(value.chi[valueIndex].typ)) {
const val = value.chi.splice(valueIndex, 1)[0];
const node = value.chi.splice(nameIndex, 1)[0];
// 'background'
// @ts-ignore
if (node.typ == exports.EnumToken.ColorTokenType && node.kin == 'dpsys') {
// @ts-ignore
delete node.kin;
node.typ = exports.EnumToken.IdenTokenType;
}
while (value.chi[0]?.typ == exports.EnumToken.WhitespaceTokenType) {
value.chi.shift();
}
const t = [{
typ: exports.EnumToken.MediaQueryConditionTokenType,
l: node,
op: { typ: val.typ },
r: value.chi.slice()
}];
value.chi.length = 0;
value.chi.push(...t);
}
}
}
}
return tokens;
}
/**
* parse selector
* @param tokens
*/
function parseSelector(tokens) {
for (const { value, previousValue, nextValue, parent } of walkValues(tokens)) {
if (value.typ == exports.EnumToken.CommentTokenType ||
value.typ == exports.EnumToken.WhitespaceTokenType ||
value.typ == exports.EnumToken.CommaTokenType ||
value.typ == exports.EnumToken.IdenTokenType ||
value.typ == exports.EnumToken.HashTokenType) {
continue;
}
if (parent == null) {
if (value.typ == exports.EnumToken.GtTokenType) {
// @ts-ignore
value.typ = exports.EnumToken.ChildCombinatorTokenType;
}
// @ts-ignore
else if (value.typ == exports.EnumToken.WhitespaceTokenType) {
if (nextValue != null && nextValue.typ == exports.EnumToken.LiteralTokenType) {
if (['>', '+', '~'].includes(nextValue.val)) {
switch (value.val) {
case '>':
// @ts-ignore
nextValue.typ = exports.EnumToken.ChildCombinatorTokenType;
break;
case '+':
// @ts-ignore
nextValue.typ = exports.EnumToken.NextSiblingCombinatorTokenType;
break;
case '~':
// @ts-ignore
nextValue.typ = exports.EnumToken.SubsequentSiblingCombinatorTokenType;
break;
}
// @ts-ignore
delete nextValue.val;
continue;
}
}
if (previousValue != null && [
exports.EnumToken.ChildCombinatorTokenType,
exports.EnumToken.DescendantCombinatorTokenType,
exports.EnumToken.NextSiblingCombinatorTokenType,
exports.EnumToken.SubsequentSiblingCombinatorTokenType,
exports.EnumToken.ColumnCombinatorTokenType,
exports.EnumToken.NameSpaceAttributeTokenType,
exports.EnumToken.CommaTokenType
].includes(previousValue.typ)) {
continue;
}
// @ts-ignore
value.typ = exports.EnumToken.DescendantCombinatorTokenType;
}
else if (value.typ == exports.EnumToken.LiteralTokenType) {
if (value.val.charAt(0) == '&') {
// @ts-ignore
value.typ = exports.EnumToken.NestingSelectorTokenType;
// @ts-ignore
delete value.val;
}
else if (value.val.charAt(0) == '.') {
if (!isIdent(value.val.slice(1))) {
// @ts-ignore
value.typ = exports.EnumToken.InvalidClassSelectorTokenType;
}
else {
// @ts-ignore
value.typ = exports.EnumToken.ClassSelectorTokenType;
}
}
// @ts-ignore
if (value.typ == exports.EnumToken.DelimTokenType) {
// @ts-ignore
value.typ = exports.EnumToken.NextSiblingCombinatorTokenType;
}
else if (['*', '>', '+', '~'].includes(value.val)) {
switch (value.val) {
case '*':
// @ts-ignore
value.typ = exports.EnumToken.UniversalSelectorTokenType;
break;
case '>':
// @ts-ignore
value.typ = exports.EnumToken.ChildCombinatorTokenType;
break;
case '+':
// @ts-ignore
value.typ = exports.EnumToken.NextSiblingCombinatorTokenType;
break;
case '~':
// @ts-ignore
value.typ = exports.EnumToken.SubsequentSiblingCombinatorTokenType;
break;
}
// @ts-ignore
// @ts-ignore
delete value.val;
}
}
else if (value.typ == exports.EnumToken.ColorTokenType) {
if (value.kin == 'lit' || value.kin == 'hex' || value.kin == 'sys' || value.kin == 'dpsys') {
if (value.kin == 'hex') {
if (!isIdent(value.val.slice(1))) {
continue;
}
// @ts-ignore
value.typ = exports.EnumToken.HashTokenType;
}
else {
// @ts-ignore
value.typ = exports.EnumToken.IdenTokenType;
}
// @ts-ignore
delete value.kin;
}
}
}
}
let i = 0;
const combinators = [
exports.EnumToken.ChildCombinatorTokenType,
exports.EnumToken.NextSiblingCombinatorTokenType,
exports.EnumToken.SubsequentSiblingCombinatorTokenType
];
for (; i < tokens.length; i++) {
if (combinators.includes(tokens[i].typ)) {
if (i + 1 < tokens.length && [exports.EnumToken.WhitespaceTokenType, exports.EnumToken.DescendantCombinatorTokenType].includes(tokens[i + 1].typ)) {
tokens.splice(i + 1, 1);
}
if (i > 0 && [exports.EnumToken.WhitespaceTokenType, exports.EnumToken.DescendantCombinatorTokenType].includes(tokens[i - 1].typ)) {
tokens.splice(i - 1, 1);
i--;
continue;
}
}
if (tokens[i].typ == exports.EnumToken.WhitespaceTokenType) {
tokens[i].typ = exports.EnumToken.DescendantCombinatorTokenType;
}
}
return tokens;
}
// export async function parseDeclarations(src: string, options: ParserOptions = {}): Promise<AstDeclaration[]> {
//
// return doParse(`.x{${src}`, options).then((result: ParseResult) => <AstDeclaration[]>(<AstRule>result.ast.chi[0]).chi.filter(t => t.typ == EnumToken.DeclarationNodeType));
// }
/**
* parse string
* @param src
* @param options
*/
function parseString(src, options = { location: false }) {
return parseTokens([...tokenize$1(src)].map(t => {
const token = getTokenType(t.token, t.hint);
if (options.location) {
Object.assign(token, { loc: t.position });
}
return token;
}));
}
function getTokenType(val, hint) {
if (hint != null) {
return enumTokenHints.has(hint) ? { typ: hint } : { typ: hint, val };
}
if (val == ' ') {
return { typ: exports.EnumToken.WhitespaceTokenType };
}
if (val == ';') {
return { typ: exports.EnumToken.SemiColonTokenType };
}
if (val == '{') {
return { typ: exports.EnumToken.BlockStartTokenType };
}
if (val == '}') {
return { typ: exports.EnumToken.BlockEndTokenType };
}
if (val == '[') {
return { typ: exports.EnumToken.AttrStartTokenType };
}
if (val == ']') {
return { typ: exports.EnumToken.AttrEndTokenType };
}
if (val == ':') {
return { typ: exports.EnumToken.ColonTokenType };
}
if (val == ')') {
return { typ: exports.EnumToken.EndParensTokenType };
}
if (val == '(') {
return { typ: exports.EnumToken.StartParensTokenType };
}
if (val == '=') {
return { typ: exports.EnumToken.DelimTokenType };
}
if (val == ';') {
return { typ: exports.EnumToken.SemiColonTokenType };
}
if (val == ',') {
return { typ: exports.EnumToken.CommaTokenType };
}
if (val == '<') {
return { typ: exports.EnumToken.LtTokenType };
}
if (val == '>') {
return { typ: exports.EnumToken.GtTokenType };
}
if (isPseudo(val)) {
return val.endsWith('(') ? {
typ: exports.EnumToken.PseudoClassFuncTokenType,
val: val.slice(0, -1),
chi: []
}
: (
// https://www.w3.org/TR/selectors-4/#single-colon-pseudos
val.startsWith('::') || pseudoElements.includes(val) ? {
typ: exports.EnumToken.PseudoElementTokenType,
val
} :
{
typ: exports.EnumToken.PseudoClassTokenType,
val
});
}
if (isAtKeyword(val)) {
return {
typ: exports.EnumToken.AtRuleTokenType,
val: val.slice(1)
};
}
if (isFunction(val)) {
val = val.slice(0, -1);
if (val == 'url') {
return {
typ: exports.EnumToken.UrlFunctionTokenType,
val,
chi: []
};
}
if (['linear-gradient', 'radial-gradient', 'repeating-linear-gradient', 'repeating-radial-gradient', 'conic-gradient', 'image', 'image-set', 'element', 'cross-fade', 'paint'].includes(val)) {
return {
typ: exports.EnumToken.ImageFunctionTokenType,
val,
chi: []
};
}
if (['ease', 'ease-in', 'ease-out', 'ease-in-out', 'linear', 'step-start', 'step-end', 'steps', 'cubic-bezier'].includes(val)) {
return {
typ: exports.EnumToken.TimingFunctionTokenType,
val,
chi: []
};
}
if (['view', 'scroll'].includes(val)) {
return {
typ: exports.EnumToken.TimelineFunctionTokenType,
val,
chi: []
};
}
return {
typ: exports.EnumToken.FunctionTokenType,
val,
chi: []
};
}
if (isNumber(val)) {
return {
typ: exports.EnumToken.NumberTokenType,
val
};
}
if (isPercentage(val)) {
return {
typ: exports.EnumToken.PercentageTokenType,
val: val.slice(0, -1)
};
}
if (isFlex(val)) {
return {
typ: exports.EnumToken.FlexTokenType,
val: val.slice(0, -2)
};
}
if (isDimension(val)) {
return parseDimension(val);
}
const v = val.toLowerCase();
if (v == 'currentcolor' || v == 'transparent' || v in COLORS_NAMES) {
return {
typ: exports.EnumToken.ColorTokenType,
val: v,
kin: 'lit'
};
}
if (isIdent(val)) {
if (systemColors.has(val.toLowerCase())) {
return {
typ: exports.EnumToken.ColorTokenType,
val,
kin: 'sys'
};
}
if (deprecatedSystemColors.has(val.toLowerCase())) {
return {
typ: exports.EnumToken.ColorTokenType,
val,
kin: 'dpsys'
};
}
return {
typ: val.startsWith('--') ? exports.EnumToken.DashedIdenTokenType : exports.EnumToken.IdenTokenType,
val
};
}
if (val.charAt(0) == '#' && isHexColor(val)) {
return {
typ: exports.EnumToken.ColorTokenType,
val,
kin: 'hex'
};
}
if (val.charAt(0) == '#' && isHash(val)) {
return {
typ: exports.EnumToken.HashTokenType,
val
};
}
if ('"\''.includes(val.charAt(0))) {
return {
typ: exports.EnumToken.UnclosedStringTokenType,
val
};
}
return {
typ: exports.EnumToken.LiteralTokenType,
val
};
}
/**
* parse token list
* @param tokens
* @param options
*/
function parseTokens(tokens, options = {}) {
for (let i = 0; i < tokens.length; i++) {
const t = tokens[i];
if (t.typ == exports.EnumToken.PseudoClassFuncTokenType) {
if (t.val.slice(1) in webkitPseudoAliasMap) {
t.val = ':' + webkitPseudoAliasMap[t.val.slice(1)];
}
}
else if (t.typ == exports.EnumToken.PseudoClassTokenType) {
if (t.val.slice(1) in webkitPseudoAliasMap) {
t.val = ':' + webkitPseudoAliasMap[t.val.slice(1)];
}
}
if (t.typ == exports.EnumToken.WhitespaceTokenType && ((i == 0 ||
i + 1 == tokens.length ||
[exports.EnumToken.CommaTokenType, exports.EnumToken.GteTokenType, exports.EnumToken.LteTokenType, exports.EnumToken.ColumnCombinatorTokenType].includes(tokens[i + 1].typ)) ||
(i > 0 && trimWhiteSpace.includes(tokens[i - 1].typ)))) {
tokens.splice(i--, 1);
continue;
}
if (t.typ == exports.EnumToken.ColonTokenType) {
const typ = tokens[i + 1]?.typ;
if (typ != null) {
if (typ == exports.EnumToken.FunctionTokenType) {
tokens[i + 1].val = ':' + (tokens[i + 1].val in webkitPseudoAliasMap ? webkitPseudoAliasMap[tokens[i + 1].val] : tokens[i + 1].val);
tokens[i + 1].typ = exports.EnumToken.PseudoClassFuncTokenType;
}
else if (typ == exports.EnumToken.IdenTokenType) {
if (tokens[i + 1].val in webkitPseudoAliasMap) {
tokens[i + 1].val = webkitPseudoAliasMap[tokens[i + 1].val];
}
tokens[i + 1].val = ':' + tokens[i + 1].val;
tokens[i + 1].typ = exports.EnumToken.PseudoClassTokenType;
}
if (typ == exports.EnumToken.FunctionTokenType || typ == exports.EnumToken.IdenTokenType) {
tokens.splice(i, 1);
i--;
}
}
continue;
}
if (t.typ == exports.EnumToken.AttrStartTokenType) {
let k = i;
let inAttr = 1;
while (++k < tokens.length) {
if (tokens[k].typ == exports.EnumToken.AttrEndTokenType) {
inAttr--;
}
else if (tokens[k].typ == exports.EnumToken.AttrStartTokenType) {
inAttr++;
}
if (inAttr == 0) {
break;
}
}
const attr = Object.assign(t, {
typ: inAttr == 0 ? exports.EnumToken.AttrTokenType : exports.EnumToken.InvalidAttrTokenType,
chi: tokens.splice(i + 1, k - i)
});
// @ts-ignore
if (attr.chi.at(-1).typ == exports.EnumToken.AttrEndTokenType) {
// @ts-ignore
attr.chi.pop();
}
// @ts-ignore
if (attr.chi.length > 1) {
/*(<AttrToken>t).chi =*/
// @ts-ignore
parseTokens(attr.chi, t.typ);
}
let m = attr.chi.length;
let val;
for (m = 0; m < attr.chi.length; m++) {
val = attr.chi[m];
if (val.typ == exports.EnumToken.StringTokenType) {
const slice = val.val.slice(1, -1);
if ((slice.charAt(0) != '-' || (slice.charAt(0) == '-' && isIdentStart(slice.charCodeAt(1)))) && isIdent(slice)) {
Object.assign(val, { typ: exports.EnumToken.IdenTokenType, val: slice });
}
}
else if (val.typ == exports.EnumToken.LiteralTokenType && val.val == '|') {
let upper = m;
let lower = m;
while (++upper < attr.chi.length) {
if (attr.chi[upper].typ == exports.EnumToken.CommentTokenType) {
continue;
}
break;
}
while (lower-- > 0) {
if (attr.chi[lower].typ == exports.EnumToken.CommentTokenType) {
continue;
}
break;
}
// @ts-ignore
attr.chi[m] = {
typ: exports.EnumToken.NameSpaceAttributeTokenType,
l: attr.chi[lower],
r: attr.chi[upper]
};
attr.chi.splice(upper, 1);
if (lower >= 0) {
attr.chi.splice(lower, 1);
m--;
}
}
else if ([
exports.EnumToken.DashMatchTokenType, exports.EnumToken.StartMatchTokenType, exports.EnumToken.ContainMatchTokenType, exports.EnumToken.EndMatchTokenType, exports.EnumToken.IncludeMatchTokenType, exports.EnumToken.DelimTokenType
].includes(attr.chi[m].typ)) {
let upper = m;
let lower = m;
while (++upper < attr.chi.length) {
if (attr.chi[upper].typ == exports.EnumToken.CommentTokenType) {
continue;
}
break;
}
while (lower-- > 0) {
if (attr.chi[lower].typ == exports.EnumToken.CommentTokenType) {
continue;
}
break;
}
val = attr.chi[lower];
if (val.typ == exports.EnumToken.StringTokenType) {
const slice = val.val.slice(1, -1);
if ((slice.charAt(0) != '-' || (slice.charAt(0) == '-' && isIdentStart(slice.charCodeAt(1)))) && isIdent(slice)) {
Object.assign(val, { typ: exports.EnumToken.IdenTokenType, val: slice });
}
}
val = attr.chi[upper];
if (val.typ == exports.EnumToken.StringTokenType) {
const slice = val.val.slice(1, -1);
if ((slice.charAt(0) != '-' || (slice.charAt(0) == '-' && isIdentStart(slice.charCodeAt(1)))) && isIdent(slice)) {
Object.assign(val, { typ: exports.EnumToken.IdenTokenType, val: slice });
}
}
// @ts-ignore
const typ = t.chi[m].typ;
// @ts-ignore
t.chi[m] = {
typ: exports.EnumToken.MatchExpressionTokenType,
op: {
// @ts-ignore
typ: typ == exports.EnumToken.DelimTokenType ? exports.EnumToken.EqualMatchTokenType : typ
},
l: t.chi[lower],
r: t.chi[upper]
};
t.chi.splice(upper, 1);
t.chi.splice(lower, 1);
upper = m;
m--;
while (upper < t.chi.length && t.chi[upper].typ == exports.EnumToken.WhitespaceTokenType) {
upper++;
}
if (upper < t.chi.length &&
t.chi[upper].typ == exports.EnumToken.Iden &&
['i', 's'].includes(t.chi[upper].val.toLowerCase())) {
t.chi[m].attr = t.chi[upper].val;
t.chi.splice(upper, 1);
}
}
}
m = t.chi.length;
while (t.chi.at(-1)?.typ == exports.EnumToken.WhitespaceTokenType) {
t.chi.pop();
}
continue;
}
if (funcLike.includes(t.typ)) {
let parens = 1;
let k = i;
while (++k < tokens.length) {
if (tokens[k].typ == exports.EnumToken.ColonTokenType) {
const typ = tokens[k + 1]?.typ;
if (typ != null) {
if (typ == exports.EnumToken.IdenTokenType) {
tokens[k + 1].typ = exports.EnumToken.PseudoClassTokenType;
tokens[k + 1].val = ':' + tokens[k + 1].val;
}
else if (typ == exports.EnumToken.FunctionTokenType) {
tokens[k + 1].typ = exports.EnumToken.PseudoClassFuncTokenType;
tokens[k + 1].val = ':' + tokens[k + 1].val;
}
if (typ == exports.EnumToken.FunctionTokenType || typ == exports.EnumToken.IdenTokenType) {
tokens.splice(k, 1);
k--;
continue;
}
}
}
if (funcLike.includes(tokens[k].typ)) {
parens++;
}
else if (tokens[k].typ == exports.EnumToken.EndParensTokenType) {
parens--;
}
if (parens == 0) {
break;
}
}
// @ts-ignore
t.chi = tokens.splice(i + 1, k - i);
// @ts-ignore
if (t.chi.at(-1)?.typ == exports.EnumToken.EndParensTokenType) {
// @ts-ignore
t.chi.pop();
}
// @ts-ignore
if (t.chi.length > 0) {
// @ts-ignore
parseTokens(t.chi, options);
}
if (t.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(t.val)) {
for (const { value, parent } of walkValues(t.chi)) {
if (value.typ == exports.EnumToken.WhitespaceTokenType) {
const p = (parent ?? t);
for (let i = 0; i < (p).chi.length; i++) {
// @ts-ignore
if (p.chi[i] == value) {
// @ts-ignore
(p).chi.splice(i, 1);
i--;
break;
}
}
}
else if (value.typ == exports.EnumToken.LiteralTokenType && ['+', '-', '/', '*'].includes(value.val)) {
// @ts-ignore
value.typ = value.val == '+' ? exports.EnumToken.Add : (value.val == '-' ? exports.EnumToken.Sub : (value.val == '*' ? exports.EnumToken.Mul : exports.EnumToken.Div));
// @ts-ignore
delete value.val;
}
}
}
else if (t.typ == exports.EnumToken.FunctionTokenType && ['minmax', 'fit-content', 'repeat'].includes(t.val)) {
// @ts-ignore
t.typ = exports.EnumToken.GridTemplateFuncTokenType;
}
else if (t.typ == exports.EnumToken.StartParensTokenType) {
// @ts-ignore
t.typ = exports.EnumToken.ParensTokenType;
}
// @ts-ignore
if (options.parseColor && t.typ == exports.EnumToken.FunctionTokenType && isColor(t)) {
// @ts-ignore
t.typ = exports.EnumToken.ColorTokenType;
// @ts-ignore
t.kin = t.val;
// @ts-ignore
if (t.chi[0].typ == exports.EnumToken.IdenTokenType) {
// @ts-ignore
if (t.chi[0].val == 'from') {
// @ts-ignore
t.cal = 'rel';
}
// @ts-ignore
else if (t.val == 'color-mix' && t.chi[0].val == 'in') {
// @ts-ignore
t.cal = 'mix';
}
else { // @ts-ignore
if (t.val == 'color') {
// @ts-ignore
t.cal = 'col';
}
}
}
const filter = [exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType];
if (t.val != 'light-dark') {
filter.push(exports.EnumToken.CommaTokenType);
}
t.chi = t.chi.filter((t) => !filter.includes(t.typ));
continue;
}
if (t.typ == exports.EnumToken.UrlFunctionTokenType) {
// @ts-ignore
if (t.chi[0]?.typ == exports.EnumToken.StringTokenType) {
// @ts-ignore
const value = t.chi[0].val.slice(1, -1);
// @ts-ignore
if (t.chi[0].val.slice(1, 5) != 'data:' && urlTokenMatcher.test(value)) {
// @ts-ignore
t.chi[0].typ = exports.EnumToken.UrlTokenTokenType;
// @ts-ignore
t.chi[0].val = options.src !== '' && options.resolveUrls ? options.resolve(value, options.src).absolute : value;
}
}
if (t.chi[0]?.typ == exports.EnumToken.UrlTokenTokenType) {
if (options.src !== '' && options.resolveUrls) {
// @ts-ignore
t.chi[0].val = options.resolve(t.chi[0].val, options.src, options.cwd).relative;
}
}
}
// @ts-ignore
if (t.chi.length > 0) {
if (t.typ == exports.EnumToken.PseudoClassFuncTokenType && t.val == ':is' && options.minify) {
//
const count = t.chi.filter((t) => t.typ != exports.EnumToken.CommentTokenType).length;
if (count == 1 ||
(i == 0 &&
(tokens[i + 1]?.typ == exports.EnumToken.CommaTokenType || tokens.length == i + 1)) ||
(tokens[i - 1]?.typ == exports.EnumToken.CommaTokenType && (tokens[i + 1]?.typ == exports.EnumToken.CommaTokenType || tokens.length == i + 1))) {
tokens.splice(i, 1, ...t.chi);
i = Math.max(0, i - t.chi.length);
}
}
}
continue;
}
if (options.parseColor) {
if (t.typ == exports.EnumToken.IdenTokenType) {
// named color
const value = t.val.toLowerCase();
if (value in COLORS_NAMES) {
Object.assign(t, {
typ: exports.EnumToken.ColorTokenType,
val: COLORS_NAMES[value].length < value.length ? COLORS_NAMES[value] : value,
kin: 'hex'
});
}
continue;
}
if (t.typ == exports.EnumToken.HashTokenType && isHexColor(t.val)) {
// hex color
// @ts-ignore
t.typ = exports.EnumToken.ColorTokenType;
// @ts-ignore
t.kin = 'hex';
}
}
}
return tokens;
}
function eq(a, b) {
if (a == null || b == null) {
return a == b;
}
if (typeof a != 'object' || typeof b != 'object') {
return a === b;
}
if (a.constructor != b.constructor) {
return false;
}
if (Array.isArray(a)) {
if (a.length != b.length) {
return false;
}
let i = 0;
for (; i < a.length; i++) {
if (!eq(a[i], b[i])) {
return false;
}
}
return true;
}
const k1 = Object.keys(a);
const k2 = Object.keys(b);
if (k1.length != k2.length) {
return false;
}
let key;
for (key of k1) {
if (!(key in b) || !eq(a[key], b[key])) {
return false;
}
}
return true;
}
var WalkerValueEvent;
(function (WalkerValueEvent) {
WalkerValueEvent[WalkerValueEvent["Enter"] = 0] = "Enter";
WalkerValueEvent[WalkerValueEvent["Leave"] = 1] = "Leave";
})(WalkerValueEvent || (WalkerValueEvent = {}));
/**
* walk ast nodes
* @param node
* @param filter
*/
function* walk(node, filter) {
const parents = [node];
const root = node;
const map = new Map;
while ((node = parents.shift())) {
let option = null;
if (filter != null) {
option = filter(node);
if (option === 'ignore') {
continue;
}
if (option === 'stop') {
break;
}
}
// @ts-ignore
if (option !== 'children') {
// @ts-ignore
yield { node, parent: map.get(node), root };
}
if (option !== 'ignore-children' && 'chi' in node) {
parents.unshift(...node.chi);
for (const child of node.chi.slice()) {
map.set(child, node);
}
}
}
}
/**
* walk ast values
* @param values
* @param root
* @param filter
* @param reverse
*/
function* walkValues(values, root = null, filter, reverse) {
// const set = new Set<Token>();
const stack = values.slice();
const map = new Map;
let previous = null;
// let parent: FunctionToken | ParensToken | BinaryExpressionToken | null = null;
if (filter != null && typeof filter == 'function') {
filter = {
event: WalkerValueEvent.Enter,
fn: filter
};
}
else if (filter == null) {
filter = {
event: WalkerValueEvent.Enter
};
}
while (stack.length > 0) {
let value = reverse ? stack.pop() : stack.shift();
let option = null;
if (filter.fn != null && filter.event == WalkerValueEvent.Enter) {
const isValid = filter.type == null || value.typ == filter.type ||
(Array.isArray(filter.type) && filter.type.includes(value.typ)) ||
(typeof filter.type == 'function' && filter.type(value));
if (isValid) {
option = filter.fn(value, map.get(value) ?? root, WalkerValueEvent.Enter);
if (option === 'ignore') {
continue;
}
if (option === 'stop') {
break;
}
// @ts-ignore
if (option != null && typeof option == 'object' && 'typ' in option) {
map.set(option, map.get(value) ?? root);
}
}
}
// @ts-ignore
if (filter.event == WalkerValueEvent.Enter && option !== 'children') {
yield {
value,
parent: map.get(value) ?? root,
previousValue: previous,
nextValue: stack[0] ?? null,
// @ts-ignore
root: root ?? null
};
}
if (option !== 'ignore-children' && 'chi' in value) {
const sliced = value.chi.slice();
for (const child of sliced) {
map.set(child, value);
}
if (reverse) {
stack.push(...sliced);
}
else {
stack.unshift(...sliced);
}
}
else if (value.typ == exports.EnumToken.BinaryExpressionTokenType) {
map.set(value.l, map.get(value) ?? root);
map.set(value.r, map.get(value) ?? root);
stack.unshift(value.l, value.r);
}
if (filter.event == WalkerValueEvent.Leave && filter.fn != null) {
const isValid = filter.type == null || value.typ == filter.type ||
(Array.isArray(filter.type) && filter.type.includes(value.typ)) ||
(typeof filter.type == 'function' && filter.type(value));
if (isValid) {
option = filter.fn(value, map.get(value), WalkerValueEvent.Leave);
// @ts-ignore
if (option != null && 'typ' in option) {
map.set(option, map.get(value) ?? root);
}
}
}
// @ts-ignore
if (filter.event == WalkerValueEvent.Leave && option !== 'children') {
yield {
value,
parent: map.get(value) ?? root,
previousValue: previous,
nextValue: stack[0] ?? null,
// @ts-ignore
root: root ?? null
};
}
previous = value;
}
}
/**
* expand nested css ast
* @param ast
*/
function expand(ast) {
//
if (![exports.EnumToken.RuleNodeType, exports.EnumToken.StyleSheetNodeType, exports.EnumToken.AtRuleNodeType].includes(ast.typ)) {
return ast;
}
if (exports.EnumToken.RuleNodeType == ast.typ) {
return {
typ: exports.EnumToken.StyleSheetNodeType,
chi: expandRule(ast)
};
}
if (!('chi' in ast)) {
return ast;
}
const result = { ...ast, chi: [] };
// @ts-ignore
for (let i = 0; i < ast.chi.length; i++) {
// @ts-ignore
const node = ast.chi[i];
if (node.typ == exports.EnumToken.RuleNodeType) {
// @ts-ignore
result.chi.push(...expandRule(node));
// i += expanded.length - 1;
}
else if (node.typ == exports.EnumToken.AtRuleNodeType && 'chi' in node) {
let hasRule = false;
let j = node.chi.length;
while (j--) {
// @ts-ignore
if (node.chi[j].typ == exports.EnumToken.RuleNodeType || node.chi[j].typ == exports.EnumToken.AtRuleNodeType) {
hasRule = true;
break;
}
}
// @ts-ignore
result.chi.push({ ...(hasRule ? expand(node) : node) });
}
else {
// @ts-ignore
result.chi.push(node);
}
}
return result;
}
function expandRule(node) {
const ast = { ...node, chi: node.chi.slice() };
const result = [];
if (ast.typ == exports.EnumToken.RuleNodeType) {
let i = 0;
for (; i < ast.chi.length; i++) {
if (ast.chi[i].typ == exports.EnumToken.RuleNodeType) {
const rule = ast.chi[i];
if (!rule.sel.includes('&')) {
const selRule = splitRule(rule.sel);
if (selRule.length > 1) {
const r = ':is(' + selRule.map(a => a.join('')).join(',') + ')';
rule.sel = splitRule(ast.sel).reduce((a, b) => a.concat([b.join('') + r]), []).join(',');
}
else {
// selRule = splitRule(selRule.reduce((acc, curr) => acc + (acc.length > 0 ? ',' : '') + curr.join(''), ''));
const arSelf = splitRule(ast.sel).filter((r) => r.every((t) => t != ':before' && t != ':after' && !t.startsWith('::'))).reduce((acc, curr) => acc.concat([curr.join('')]), []).join(',');
if (arSelf.length == 0) {
ast.chi.splice(i--, 1);
continue;
}
//
selRule.forEach(arr => combinators.includes(arr[0].charAt(0)) ? arr.unshift(arSelf) : arr.unshift(arSelf, ' '));
rule.sel = selRule.reduce((acc, curr) => {
acc.push(curr.join(''));
return acc;
}, []).join(',');
}
}
else {
let childSelectorCompound = [];
let withCompound = [];
let withoutCompound = [];
// pseudo elements cannot be used with '&'
// https://www.w3.org/TR/css-nesting-1/#example-7145ff1e
const rules = splitRule(ast.sel).filter((r) => r.every((t) => t != ':before' && t != ':after' && !t.startsWith('::')));
const parentSelector = !node.sel.includes('&');
if (rules.length == 0) {
ast.chi.splice(i--, 1);
continue;
}
for (const sel of (rule.raw ?? splitRule(rule.sel))) {
const s = sel.join('');
if (s.includes('&') || parentSelector) {
if (s.indexOf('&', 1) == -1) {
if (s.at(0) == '&') {
if (s.at(1) == ' ') {
childSelectorCompound.push(s.slice(2));
}
else {
if (s == '&' || parentSelector) {
withCompound.push(s);
}
else {
withoutCompound.push(s.slice(1));
}
}
}
else {
withoutCompound.push(s);
}
}
else {
withCompound.push(s);
}
}
else {
withoutCompound.push(s);
}
}
const selectors = [];
const selector = rules.length > 1 ? ':is(' + rules.map(a => a.join('')).join(',') + ')' : rules[0].join('');
if (childSelectorCompound.length > 0) {
if (childSelectorCompound.length == 1) {
selectors.push(replaceCompound('& ' + childSelectorCompound[0].trim(), selector));
}
else {
selectors.push(replaceCompound('& :is(' + childSelectorCompound.reduce((acc, curr) => acc + (acc.length > 0 ? ',' : '') + curr.trim(), '') + ')', selector));
}
}
if (withCompound.length > 0) {
if (withCompound.every((t) => t[0] == '&' && t.indexOf('&', 1) == -1)) {
withoutCompound.push(...withCompound.map(t => t.slice(1)));
withCompound.length = 0;
}
}
if (withoutCompound.length > 0) {
if (withoutCompound.length == 1) {
const useIs = rules.length == 1 && selector.match(/^[a-zA-Z.:]/) != null && selector.includes(' ') && withoutCompound.length == 1 && withoutCompound[0].match(/^[a-zA-Z]+$/) != null;
const compound = useIs ? ':is(&)' : '&';
selectors.push(replaceCompound(rules.length == 1 ? (useIs ? withoutCompound[0] + ':is(&)' : (selector.match(/^[.:]/) && withoutCompound[0].match(/^[a-zA-Z]+$/) ? withoutCompound[0] + compound : compound + withoutCompound[0])) : (withoutCompound[0].match(/^[a-zA-Z:]+$/) ? withoutCompound[0].trim() + compound : '&' + (withoutCompound[0].match(/^\S+$/) ? withoutCompound[0].trim() : ':is(' + withoutCompound[0].trim() + ')')), selector));
}
else {
selectors.push(replaceCompound('&:is(' + withoutCompound.reduce((acc, curr) => acc + (acc.length > 0 ? ',' : '') + curr.trim(), '') + ')', selector));
}
}
if (withCompound.length > 0) {
if (withCompound.length == 1) {
selectors.push(replaceCompound(withCompound[0], selector));
}
else {
for (const w of withCompound) {
selectors.push(replaceCompound(w, selector));
}
}
}
rule.sel = selectors.reduce((acc, curr) => curr.length == 0 ? acc : acc + (acc.length > 0 ? ',' : '') + curr, '');
}
ast.chi.splice(i--, 1);
result.push(...expandRule(rule));
}
else if (ast.chi[i].typ == exports.EnumToken.AtRuleNodeType) {
let astAtRule = ast.chi[i];
const values = [];
if (astAtRule.nam == 'scope') {
if (astAtRule.val.includes('&')) {
astAtRule.val = replaceCompound(astAtRule.val, ast.sel);
}
const slice = astAtRule.chi.slice().filter(t => t.typ == exports.EnumToken.RuleNodeType && t.sel.includes('&'));
if (slice.length > 0) {
expandRule({ ...node, chi: astAtRule.chi.slice() });
}
}
else {
// @ts-ignore
const clone = { ...ast, chi: astAtRule.chi.slice() };
// @ts-ignore
astAtRule.chi.length = 0;
for (const r of expandRule(clone)) {
if (r.typ == exports.EnumToken.AtRuleNodeType && 'chi' in r) {
if (astAtRule.val !== '' && r.val !== '') {
if (astAtRule.nam == 'media' && r.nam == 'media') {
r.val = astAtRule.val + ' and ' + r.val;
}
else if (astAtRule.nam == 'layer' && r.nam == 'layer') {
r.val = astAtRule.val + '.' + r.val;
}
}
// @ts-ignore
values.push(r);
}
else if (r.typ == exports.EnumToken.RuleNodeType) {
// @ts-ignore
astAtRule.chi.push(...expandRule(r));
}
else {
// @ts-ignore
astAtRule.chi.push(r);
}
}
}
// @ts-ignore
result.push(...(astAtRule.chi.length > 0 ? [astAtRule].concat(values) : values));
ast.chi.splice(i--, 1);
}
}
}
// @ts-ignore
return ast.chi.length > 0 ? [ast].concat(result) : result;
}
/**
* replace compound selector
* @param input
* @param replace
*/
function replaceCompound(input, replace) {
const tokens = parseString(input);
let replacement = null;
for (const t of walkValues(tokens)) {
if (t.value.typ == exports.EnumToken.LiteralTokenType) {
if (t.value.val == '&') {
if (tokens.length == 2) {
if (replacement == null) {
replacement = parseString(replace);
}
if (tokens[1].typ == exports.EnumToken.IdenTokenType) {
t.value.val = replacement.length == 1 || (!replace.includes(' ') && replace.charAt(0).match(/[:.]/)) ? tokens[1].val + replace : replaceCompoundLiteral(tokens[1].val + '&', replace);
tokens.splice(1, 1);
}
else {
t.value.val = replaceCompoundLiteral(t.value.val, replace);
}
continue;
}
const rule = splitRule(replace);
t.value.val = rule.length > 1 ? ':is(' + replace + ')' : replace;
}
else if (t.value.val.length > 1 && t.value.val.charAt(0) == '&') {
t.value.val = replaceCompoundLiteral(t.value.val, replace);
}
}
}
return tokens.reduce((acc, curr) => acc + renderToken(curr), '');
}
function replaceCompoundLiteral(selector, replace) {
const tokens = [''];
let i = 0;
for (; i < selector.length; i++) {
if (selector.charAt(i) == '&') {
tokens.push('&');
tokens.push('');
}
else {
tokens[tokens.length - 1] += selector.charAt(i);
}
}
return tokens.sort((a, b) => {
if (a == '&') {
return 1;
}
return b == '&' ? -1 : 0;
}).reduce((acc, curr) => {
if (acc.length > 0 && curr == '&' && (replace.charAt(0) != '.' || replace.includes(' '))) {
return acc + ':is(' + replace + ')';
}
return acc + (curr == '&' ? replace : curr);
}, '');
}
const config$1 = getSyntaxConfig();
class ComputePrefixFeature {
static get ordering() {
return 2;
}
static register(options) {
if (options.removePrefix) {
for (const feature of options.features) {
if (feature instanceof ComputePrefixFeature) {
return;
}
}
// @ts-ignore
options.features.push(new ComputePrefixFeature(options));
}
}
run(ast) {
// @ts-ignore
const j = ast.chi.length;
let k = 0;
// @ts-ignore
for (; k < j; k++) {
// @ts-ignore
const node = ast.chi[k];
if (node.typ == exports.EnumToken.DeclarationNodeType) {
if (node.nam.charAt(0) == '-') {
const match = node.nam.match(/^-([^-]+)-(.+)$/);
if (match != null) {
const nam = match[2];
if (nam.toLowerCase() in config$1.declarations) {
node.nam = nam;
}
}
}
if (node.nam.toLowerCase() in config$1.declarations) {
for (const { value } of walkValues(node.val)) {
if (value.typ == exports.EnumToken.IdenTokenType && value.val.charAt(0) == '-' && value.val.charAt(1) != '-') {
// @ts-ignore
const values = config$1.declarations[node.nam].ast.slice();
const match = value.val.match(/^-(.*?)-(.*)$/);
if (match != null) {
const val = matchToken({ ...value, val: match[2] }, values);
if (val != null) {
// @ts-ignore
value.val = val.val;
}
}
}
}
}
}
}
return ast;
}
}
function matchToken(token, matches) {
let result;
for (let i = 0; i < matches.length; i++) {
switch (matches[i].typ) {
case ValidationTokenEnum.Whitespace:
case ValidationTokenEnum.Comma:
break;
case ValidationTokenEnum.Keyword:
if (token.typ == exports.EnumToken.IdenTokenType && token.val == matches[i].val) {
return token;
}
break;
case ValidationTokenEnum.PropertyType:
if (['ident', 'custom-ident'].includes(matches[i].val)) {
if (token.typ == exports.EnumToken.IdenTokenType && token.val == matches[i].val) {
return token;
}
}
else {
const val = matches[i].val;
if (val in config$1.declarations || val in config$1.syntaxes) {
// @ts-ignore
result = matchToken(token, (config$1.syntaxes[val] ?? config$1.declarations[val]).ast.slice());
if (result != null) {
return result;
}
}
}
break;
case ValidationTokenEnum.PipeToken:
for (let j = 0; j < matches[i].chi.length; j++) {
result = matchToken(token, matches[i].chi[j]);
if (result != null) {
return result;
}
}
break;
case ValidationTokenEnum.ColumnToken:
case ValidationTokenEnum.AmpersandToken:
result = matchToken(token, matches[i].l);
if (result == null) {
result = matchToken(token, matches[i].r);
}
if (result != null) {
return result;
}
break;
case ValidationTokenEnum.Bracket:
result = matchToken(token, matches[i].chi);
if (result != null) {
return result;
}
break;
}
}
return null;
}
function replace(node, variableScope) {
for (const { value, parent: parentValue } of walkValues(node.val)) {
if (value?.typ == exports.EnumToken.FunctionTokenType && value.val == 'var') {
if (value.chi.length == 1 && value.chi[0].typ == exports.EnumToken.DashedIdenTokenType) {
const info = variableScope.get(value.chi[0].val);
if (info?.replaceable) {
if (parentValue != null) {
let i = 0;
for (; i < parentValue.chi.length; i++) {
if (parentValue.chi[i] == value) {
parentValue.chi.splice(i, 1, ...info.node.val);
break;
}
}
}
else {
node.val = info.node.val.slice();
}
}
}
}
}
}
class InlineCssVariablesFeature {
static get ordering() {
return 0;
}
static register(options) {
if (options.inlineCssVariables) {
for (const feature of options.features) {
if (feature instanceof InlineCssVariablesFeature) {
return;
}
}
// @ts-ignore
options.features.push(new InlineCssVariablesFeature());
}
}
run(ast, options = {}, parent, context) {
if (!('variableScope' in context)) {
context.variableScope = new Map;
}
const isRoot = parent.typ == exports.EnumToken.StyleSheetNodeType && ast.typ == exports.EnumToken.RuleNodeType && [':root', 'html'].includes(ast.sel);
const variableScope = context.variableScope;
// @ts-ignore
for (const node of ast.chi) {
if (node.typ == exports.EnumToken.CDOCOMMNodeType || node.typ == exports.EnumToken.CommentNodeType) {
continue;
}
if (node.typ != exports.EnumToken.DeclarationNodeType) {
break;
}
// css variable
if (node.nam.startsWith('--')) {
if (!variableScope.has(node.nam)) {
const info = {
globalScope: isRoot,
// @ts-ignore
parent: new Set(),
declarationCount: 1,
replaceable: isRoot,
node: node
};
info.parent.add(ast);
variableScope.set(node.nam, info);
let recursive = false;
for (const { value, parent: parentValue } of walkValues(node.val)) {
if (value?.typ == exports.EnumToken.FunctionTokenType && value.val == 'var') {
recursive = true;
break;
}
}
if (recursive) {
replace(node, variableScope);
}
}
else {
const info = variableScope.get(node.nam);
info.globalScope = isRoot;
if (!isRoot) {
++info.declarationCount;
}
if (info.replaceable) {
info.replaceable = isRoot && info.declarationCount == 1;
}
info.parent.add(ast);
info.node = node;
}
}
else {
replace(node, variableScope);
}
}
}
cleanup(ast, options = {}, context) {
const variableScope = context.variableScope;
if (variableScope == null) {
return;
}
for (const info of variableScope.values()) {
if (info.replaceable) {
let i;
// drop declarations from :root{}
for (const parent of info.parent) {
i = parent.chi?.length ?? 0;
while (i--) {
if (parent.chi[i].typ == exports.EnumToken.DeclarationNodeType && parent.chi[i].nam == info.node.nam) {
// @ts-ignore
parent.chi.splice(i++, 1, {
typ: exports.EnumToken.CommentTokenType,
val: `/* ${info.node.nam}: ${info.node.val.reduce((acc, curr) => acc + renderToken(curr), '')} */`
});
}
}
if (parent.chi?.length == 0 && 'parent' in parent) {
// @ts-ignore
for (i = 0; i < parent.parent.chi?.length; i++) {
// @ts-ignore
if (parent.parent.chi[i] == parent) {
// @ts-ignore
parent.parent.chi.splice(i, 1);
break;
}
}
}
}
}
}
}
}
function dedup(values) {
for (const value of values) {
let i = value.length;
while (i-- > 1) {
const t = value[i];
const k = value[i == 1 ? 0 : i % 2];
if (t.val == k.val && t.val == '0') {
if ((t.typ == exports.EnumToken.NumberTokenType && isLength(k)) ||
(k.typ == exports.EnumToken.NumberTokenType && isLength(t)) ||
(isLength(k) || isLength(t))) {
value.splice(i, 1);
continue;
}
}
if (eq(t, k)) {
value.splice(i, 1);
continue;
}
break;
}
}
return values;
}
class PropertySet {
config;
declarations;
constructor(config) {
this.config = config;
this.declarations = new Map;
}
add(declaration) {
if (declaration.nam == this.config.shorthand) {
this.declarations = new Map;
}
else {
// expand shorthand
if (declaration.nam != this.config.shorthand && this.declarations.has(this.config.shorthand)) {
let isValid = true;
let current = -1;
const tokens = [];
// @ts-ignore
for (let token of this.declarations.get(this.config.shorthand).val) {
// @ts-ignore
if (this.config.types.some(t => token.typ == exports.EnumToken[t]) || (token.typ == exports.EnumToken.NumberTokenType && token.val == '0' &&
(this.config.types.includes('Length') ||
this.config.types.includes('Angle') ||
this.config.types.includes('Dimension')))) {
if (tokens.length == 0) {
tokens.push([]);
current++;
}
tokens[current].push(token);
continue;
}
if (token.typ != exports.EnumToken.WhitespaceTokenType && token.typ != exports.EnumToken.CommentTokenType) {
if (token.typ == exports.EnumToken.IdenTokenType && this.config.keywords.includes(token.val)) {
if (tokens.length == 0) {
tokens.push([]);
current++;
}
tokens[current].push(token);
}
// @ts-ignore
if (token.typ == exports.EnumToken.LiteralTokenType && token.val == this.config.separator) {
tokens.push([]);
current++;
continue;
}
isValid = false;
break;
}
}
if (isValid && tokens.length > 0) {
this.declarations.delete(this.config.shorthand);
for (const values of tokens) {
this.config.properties.forEach((property, index) => {
if (!this.declarations.has(property)) {
this.declarations.set(property, {
typ: exports.EnumToken.DeclarationNodeType,
nam: property,
val: []
});
}
while (index > 0 && index >= values.length) {
if (index > 1) {
index %= 2;
}
else {
index = 0;
break;
}
}
// @ts-ignore
const val = this.declarations.get(property).val;
if (val.length > 0) {
val.push({ typ: exports.EnumToken.WhitespaceTokenType });
}
val.push({ ...values[index] });
});
}
}
this.declarations.set(declaration.nam, declaration);
return this;
}
}
this.declarations.set(declaration.nam, declaration);
return this;
}
isShortHand() {
if (this.declarations.has(this.config.shorthand)) {
return this.declarations.size == 1;
}
return this.config.properties.length == this.declarations.size;
}
[Symbol.iterator]() {
let iterator;
const declarations = this.declarations;
if (declarations.size < this.config.properties.length) {
const values = [...declarations.values()];
if (this.isShortHand()) {
const val = values[0].val.reduce((acc, curr) => {
if (![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType].includes(curr.typ)) {
acc.push(curr);
}
return acc;
}, []);
values[0].val = val.reduce((acc, curr) => {
if (acc.length > 0) {
acc.push({ typ: exports.EnumToken.WhitespaceTokenType });
}
acc.push(curr);
return acc;
}, []);
}
return values[Symbol.iterator]();
}
else {
const values = [];
this.config.properties.forEach((property) => {
let index = 0;
// @ts-ignore
for (const token of this.declarations.get(property).val) {
if (token.typ == exports.EnumToken.WhitespaceTokenType) {
continue;
}
if (values.length == index) {
values.push([]);
}
values[index].push(token);
index++;
}
});
dedup(values);
iterator = [{
typ: exports.EnumToken.DeclarationNodeType,
nam: this.config.shorthand,
val: values.reduce((acc, curr) => {
if (curr.length > 1) {
const k = curr.length * 2 - 1;
let i = 1;
while (i < k) {
curr.splice(i, 0, { typ: exports.EnumToken.WhitespaceTokenType });
i += 2;
}
}
if (acc.length > 0) {
// @ts-ignore
acc.push({ typ: exports.EnumToken.LiteralTokenType, val: this.config.separator });
}
acc.push(...curr);
return acc;
}, [])
}][Symbol.iterator]();
}
return iterator;
}
}
const propertiesConfig = getConfig();
class PropertyMap {
config;
declarations;
requiredCount;
pattern;
constructor(config) {
const values = Object.values(config.properties);
this.requiredCount = values.reduce((acc, curr) => curr.required ? ++acc : acc, 0) || values.length;
this.config = config;
this.declarations = new Map;
this.pattern = config.pattern.split(/\s/);
}
add(declaration) {
if (declaration.nam == this.config.shorthand) {
this.declarations = new Map;
this.declarations.set(declaration.nam, declaration);
this.matchTypes(declaration);
}
else {
const separator = this.config.separator != null ? {
...this.config.separator,
// @ts-ignore
typ: exports.EnumToken[this.config.separator.typ]
} : null;
// expand shorthand
if (declaration.nam != this.config.shorthand && this.declarations.has(this.config.shorthand)) {
const tokens = {};
const values = [];
// @ts-ignore
this.declarations.get(this.config.shorthand).val.slice().reduce((acc, curr) => {
// @ts-ignore
if (separator != null && separator.typ == curr.typ && separator.val == curr.val) {
acc.push([]);
return acc;
}
// @ts-ignore
acc.at(-1).push(curr);
return acc;
}, [[]]).
// @ts-ignore
reduce((acc, list, current) => {
values.push(...this.pattern.reduce((acc, property) => {
// let current: number = 0;
const props = this.config.properties[property];
for (let i = 0; i < acc.length; i++) {
if (acc[i].typ == exports.EnumToken.CommentTokenType || acc[i].typ == exports.EnumToken.WhitespaceTokenType) {
acc.splice(i, 1);
i--;
continue;
}
// @ts-ignore
if (('propertyName' in acc[i] && acc[i].propertyName == property) || matchType(acc[i], props)) {
if ('prefix' in props && props.previous != null && !(props.previous in tokens)) {
return acc;
}
if (!(property in tokens)) {
tokens[property] = [[acc[i]]];
}
else {
if (current == tokens[property].length) {
tokens[property].push([acc[i]]);
}
else {
tokens[property][current].push({ typ: exports.EnumToken.WhitespaceTokenType }, acc[i]);
}
}
acc.splice(i, 1);
i--;
// @ts-ignore
if ('prefix' in props && acc[i]?.typ == exports.EnumToken[props.prefix.typ]) {
// @ts-ignore
if (acc[i].typ == exports.EnumToken[props.prefix.typ] && acc[i].val == this.config.properties[property].prefix.val) {
acc.splice(i, 1);
i--;
}
}
if (props.multiple) {
continue;
}
return acc;
}
else {
if (property in tokens && tokens[property].length > current) {
return acc;
}
}
}
if (property in tokens && tokens[property].length > current) {
return acc;
}
// default
if (props.default.length > 0) {
const defaults = parseString(props.default[0]);
if (!(property in tokens)) {
tokens[property] = [
[...defaults]
];
}
else {
if (current == tokens[property].length) {
tokens[property].push([]);
tokens[property][current].push(...defaults);
}
else {
tokens[property][current].push({ typ: exports.EnumToken.WhitespaceTokenType }, ...defaults);
}
}
}
return acc;
}, list));
return values;
}, []);
if (values.length == 0) {
this.declarations = Object.entries(tokens).reduce((acc, curr) => {
acc.set(curr[0], {
typ: exports.EnumToken.DeclarationNodeType,
nam: curr[0],
val: curr[1].reduce((acc, curr) => {
if (acc.length > 0) {
acc.push({ ...separator });
}
acc.push(...curr);
return acc;
}, [])
});
return acc;
}, new Map);
}
}
// @ts-ignore
const config = propertiesConfig.properties[declaration.nam];
let property = declaration.nam;
if (config != null) {
property = config.shorthand;
let value = this.declarations.get(property);
if (!(value instanceof PropertySet)) {
// @ts-ignore
this.declarations.set(property, new PropertySet(propertiesConfig.properties[config.shorthand]));
// Token[]
if (value != null) {
// @ts-ignore
this.declarations.get(property).add(value);
}
}
this.declarations.get(property).add(declaration);
}
else {
this.declarations.set(declaration.nam, declaration);
}
}
return this;
}
[Symbol.iterator]() {
let iterable;
let requiredCount = 0;
let property;
let isShorthand = true;
for (property of Object.keys(this.config.properties)) {
if (this.config.properties[property].required) {
if (!this.declarations.has(property)) {
isShorthand = false;
break;
}
else {
const val = this.declarations.get(property);
if (val instanceof PropertySet && !val.isShortHand()) {
isShorthand = false;
break;
}
else {
requiredCount++;
}
}
}
}
if (requiredCount == 0) {
requiredCount = this.declarations.size;
}
if (!isShorthand || requiredCount < this.requiredCount) {
if (isShorthand && this.declarations.has(this.config.shorthand)) {
const cache = new Map();
const removeDefaults = (declaration) => {
let i;
let t;
let map = new Map();
let value = [];
let values = [];
// @ts-ignore
let typ = (exports.EnumToken[this.config.separator?.typ] ?? exports.EnumToken.CommaTokenType);
// @ts-ignore
const sep = this.config.separator == null ? null : {
...this.config.separator,
typ: exports.EnumToken[this.config.separator.typ]
};
// @ts-ignore
const separator = this.config.separator ? renderToken({
...this.config.separator,
typ: exports.EnumToken[this.config.separator.typ]
}) : ',';
this.matchTypes(declaration);
values.push(value);
for (i = 0; i < declaration.val.length; i++) {
t = declaration.val[i];
if (!cache.has(t)) {
cache.set(t, renderToken(t, { minify: true }));
}
if (t.typ == typ && separator == cache.get(t)) {
this.removeDefaults(map, value);
value = [];
values.push(value);
map.clear();
continue;
}
value.push(t);
// @ts-ignore
if ('propertyName' in t) {
// @ts-ignore
if (!map.has(t.propertyName)) {
// @ts-ignore
map.set(t.propertyName, { t: [t], value: [cache.get(t)] });
}
else {
// @ts-ignore
const v = map.get(t.propertyName);
v.t.push(t);
v.value.push(cache.get(t));
}
}
}
this.removeDefaults(map, value);
declaration.val = values.reduce((acc, curr) => {
if (sep != null && acc.length > 0) {
acc.push({ ...sep });
}
for (const cr of curr) {
if (cr.typ == exports.EnumToken.WhitespaceTokenType && acc.at(-1)?.typ == cr.typ) {
continue;
}
acc.push(cr);
}
return acc;
}, []);
while (declaration.val.at(-1)?.typ == exports.EnumToken.WhitespaceTokenType) {
declaration.val.pop();
}
while (declaration.val.at(0)?.typ == exports.EnumToken.WhitespaceTokenType) {
declaration.val.shift();
}
return declaration;
};
const values = [...this.declarations.values()].reduce((acc, curr) => {
if (curr instanceof PropertySet) {
acc.push(...curr);
}
else {
acc.push(curr);
}
return acc;
}, []);
let isImportant = false;
const filtered = values.map(removeDefaults).filter((x) => x.val.filter((t) => {
if (t.typ == exports.EnumToken.ImportantTokenType) {
isImportant = true;
}
return ![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.ImportantTokenType].includes(t.typ);
}).length > 0);
if (filtered.length == 0 && this.config.default.length > 0) {
filtered.push({
typ: exports.EnumToken.DeclarationNodeType,
nam: this.config.shorthand,
val: parseString(this.config.default[0])
});
if (isImportant) {
filtered[0].val.push({
typ: exports.EnumToken.ImportantTokenType
});
}
}
return (filtered.length > 0 ? filtered : values)[Symbol.iterator]();
}
for (const declaration of this.declarations.values()) {
if (declaration instanceof PropertySet) {
continue;
}
const config = declaration.nam == this.config.shorthand ? this.config : this.config.properties[declaration.nam] ?? this.config;
if (!('mapping' in config)) {
continue;
}
// @ts-ignore
for (const [key, val] of Object.entries(config.mapping)) {
const keys = parseString(key);
if (keys.length != declaration.val.length) {
continue;
}
if (eq(declaration.val, keys)) {
declaration.val = parseString(val);
break;
}
}
}
// @ts-ignore
iterable = this.declarations.values();
}
else {
let count = 0;
let match;
const separator = this.config.separator != null ? {
...this.config.separator,
// @ts-ignore
typ: exports.EnumToken[this.config.separator.typ]
} : null;
const tokens = {};
// @ts-ignore
Object.entries(this.config.properties).reduce((acc, curr) => {
if (!this.declarations.has(curr[0])) {
if (curr[1].required) {
acc.push(curr[0]);
}
return acc;
}
let current = 0;
const props = this.config.properties[curr[0]];
const properties = this.declarations.get(curr[0]);
for (const declaration of [(properties instanceof PropertySet ? [...properties][0] : properties)]) {
// @ts-ignore
for (const val of declaration.val) {
// @ts-ignore
if (separator != null && separator.typ == val.typ && separator.val == val.val) {
current++;
if (tokens[curr[0]].length == current) {
tokens[curr[0]].push([]);
}
continue;
}
if (val.typ == exports.EnumToken.WhitespaceTokenType || val.typ == exports.EnumToken.CommentTokenType) {
continue;
}
// @ts-ignore
if (props.multiple && props.separator != null &&
// @ts-ignore
exports.EnumToken[props.separator.typ] == val.typ &&
// @ts-ignore
props.separator.val == val.val) {
continue;
}
// @ts-ignore
match = val.typ == exports.EnumToken.CommentTokenType || matchType(val, curr[1]);
if (isShorthand) {
isShorthand = match;
}
// @ts-ignore
if (('propertyName' in val && val.propertyName == property) || match) {
if (!(curr[0] in tokens)) {
tokens[curr[0]] = [[]];
}
// is default value
tokens[curr[0]][current].push(val);
}
else {
acc.push(curr[0]);
break;
}
}
}
if (count == 0) {
count = current;
}
return acc;
}, []);
count++;
if (!isShorthand || Object.entries(this.config.properties).some((entry) => {
// missing required property
return entry[1].required && !(entry[0] in tokens);
}) ||
// @ts-ignore
!Object.values(tokens).every((v) => v.filter((t) => t.typ != exports.EnumToken.CommentTokenType).length == count)) {
// @ts-ignore
iterable = this.declarations.values();
}
else {
let values = Object.entries(tokens).reduce((acc, curr) => {
const props = this.config.properties[curr[0]];
for (let i = 0; i < curr[1].length; i++) {
if (acc.length == i) {
acc.push([]);
}
let values = curr[1][i].reduce((acc, curr) => {
if (acc.length > 0) {
acc.push({ typ: exports.EnumToken.WhitespaceTokenType });
}
acc.push(curr);
return acc;
}, []);
if (props.default.includes(curr[1][i].reduce((acc, curr) => acc + renderToken(curr) + ' ', '').trimEnd())) {
if (!this.config.properties[curr[0]].required) {
continue;
}
}
// remove default values
let doFilterDefault = true;
if (curr[0] in propertiesConfig.properties) {
for (let v of values) {
if (![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType, exports.EnumToken.IdenTokenType].includes(v.typ)
|| (v.typ == exports.EnumToken.IdenTokenType && !this.config.properties[curr[0]].default.includes(v.val))) {
doFilterDefault = false;
break;
}
}
}
// remove default values
const filtered = values.filter((val) => {
if (val.typ == exports.EnumToken.WhitespaceTokenType || val.typ == exports.EnumToken.CommentTokenType) {
return false;
}
return !doFilterDefault || !(val.typ == exports.EnumToken.IdenTokenType && props.default.includes(val.val));
});
if (filtered.length > 0 || !(this.requiredCount == requiredCount && this.config.properties[curr[0]].required)) {
values = filtered;
}
if (values.length > 0) {
if ('mapping' in props) {
// @ts-ignore
if (!('constraints' in props) || !('max' in props.constraints) || values.length <= props.constraints.mapping.max) {
let i = values.length;
while (i--) {
// @ts-ignore
if (values[i].typ == exports.EnumToken.IdenTokenType && values[i].val in props.mapping) {
// @ts-ignore
values.splice(i, 1, ...parseString(props.mapping[values[i].val]));
}
}
}
}
if ('prefix' in props) {
// @ts-ignore
acc[i].push({ ...props.prefix, typ: exports.EnumToken[props.prefix.typ] });
}
else if (acc[i].length > 0) {
acc[i].push({ typ: exports.EnumToken.WhitespaceTokenType });
}
acc[i].push(...values.reduce((acc, curr) => {
if (acc.length > 0) {
// @ts-ignore
acc.push({
...((props.separator && {
...props.separator,
// @ts-ignore
typ: exports.EnumToken[props.separator.typ]
}) ?? { typ: exports.EnumToken.WhitespaceTokenType })
});
}
// @ts-ignore
acc.push(curr);
return acc;
}, []));
}
}
return acc;
}, []).reduce((acc, curr) => {
if (acc.length > 0) {
acc.push({ ...separator });
}
if (curr.length == 0 && this.config.default.length > 0) {
curr.push(...parseString(this.config.default[0]).reduce((acc, curr) => {
if (acc.length > 0) {
acc.push({ typ: exports.EnumToken.WhitespaceTokenType });
}
acc.push(curr);
return acc;
}, []));
}
acc.push(...curr);
return acc;
}, []);
if (this.config.mapping != null) {
const val = values.reduce((acc, curr) => acc + renderToken(curr, {
removeComments: true,
minify: true
}), '');
if (val in this.config.mapping) {
values.length = 0;
values.push({
typ: ['"', "'"].includes(val.charAt(0)) ? exports.EnumToken.StringTokenType : exports.EnumToken.IdenTokenType,
// @ts-ignore
val: this.config.mapping[val]
});
}
}
// @ts-ignore
if (values.length == 1 &&
// @ts-ignore
typeof values[0].val == 'string' &&
this.config.default.includes(values[0].val.toLowerCase()) &&
this.config.default[0] != values[0].val.toLowerCase()) {
// @ts-ignore/
values = parseString(this.config.default[0]);
}
iterable = [{
typ: exports.EnumToken.DeclarationNodeType,
nam: this.config.shorthand,
val: values
}][Symbol.iterator]();
}
}
const iterators = [];
return {
// @ts-ignore
next() {
let v = iterable.next();
// @ts-ignore
while (v.done || v.value instanceof PropertySet) {
if (v.value instanceof PropertySet) {
// @ts-ignore
iterators.push(iterable);
iterable = v.value[Symbol.iterator]();
v = iterable.next();
}
if (v.done) {
if (iterators.length > 0) {
// @ts-ignore
iterable = iterators.pop();
v = iterable.next();
}
if (v.done && iterators.length == 0) {
break;
}
}
}
return v;
}
};
}
matchTypes(declaration) {
const patterns = this.pattern.slice();
const values = [...declaration.val];
let i;
let j;
const map = new Map;
for (i = 0; i < patterns.length; i++) {
for (j = 0; j < values.length; j++) {
if (!map.has(patterns[i])) {
// @ts-ignore
map.set(patterns[i], this.config.properties?.[patterns[i]]?.constraints?.mapping?.max ?? 1);
}
let count = map.get(patterns[i]);
if (count > 0 && matchType(values[j], this.config.properties[patterns[i]])) {
Object.defineProperty(values[j], 'propertyName', {
enumerable: false,
writable: true,
value: patterns[i]
});
map.set(patterns[i], --count);
values.splice(j--, 1);
}
}
}
if (this.config.set != null) {
for (const [key, val] of Object.entries(this.config.set)) {
if (map.has(key)) {
for (const v of val) {
// missing
if (map.get(v) == 1) {
let i = declaration.val.length;
while (i--) {
// @ts-ignore
if (declaration.val[i].propertyName == key) {
const val = { ...declaration.val[i] };
Object.defineProperty(val, 'propertyName', {
enumerable: false,
writable: true,
value: v
});
declaration.val.splice(i, 0, val, { typ: exports.EnumToken.WhitespaceTokenType });
}
}
}
}
}
}
}
}
removeDefaults(map, value) {
for (const [key, val] of map) {
const config = this.config.properties[key];
if (config == null) {
continue;
}
const v = val.value.join(' ');
if (config.default.includes(v) || (value.length == 1 && this.config.default.includes(v))) {
for (const token of value) {
if (val.t.includes(token)) {
let index = value.indexOf(token);
value.splice(index, 1);
if (config.prefix != null) {
while (index-- > 0) {
if (value[index].typ == exports.EnumToken.WhitespaceTokenType) {
continue;
}
// @ts-ignore@
if (value[index].typ == exports.EnumToken[config.prefix.typ] &&
// @ts-ignore
value[index].val == config.prefix.val) {
value.splice(index, 1);
break;
}
}
}
}
}
}
}
}
}
const config = getConfig();
class PropertyList {
options = { removeDuplicateDeclarations: true, computeShorthand: true };
declarations;
constructor(options = {}) {
this.options = options;
this.declarations = new Map;
}
set(nam, value) {
return this.add({
typ: exports.EnumToken.DeclarationNodeType,
nam,
val: Array.isArray(value) ? value : parseString(String(value))
});
}
add(declaration) {
if (declaration.typ != exports.EnumToken.DeclarationNodeType || !this.options.removeDuplicateDeclarations) {
this.declarations.set(Number(Math.random().toString().slice(2)).toString(36), declaration);
return this;
}
if (!this.options.computeShorthand) {
this.declarations.set(declaration.nam, declaration);
return this;
}
let propertyName = declaration.nam;
let shortHandType;
let shorthand;
if (propertyName in config.properties) {
// @ts-ignore
if ('map' in config.properties[propertyName]) {
shortHandType = 'map';
// @ts-ignore
shorthand = config.properties[propertyName].map;
}
else {
shortHandType = 'set';
// @ts-ignore
shorthand = config.properties[propertyName].shorthand;
}
}
else if (propertyName in config.map) {
shortHandType = 'map';
// @ts-ignore
shorthand = config.map[propertyName].shorthand;
}
// @ts-ignore
if (shortHandType == 'map') {
// @ts-ignore
if (!this.declarations.has(shorthand)) {
// @ts-ignore
this.declarations.set(shorthand, new PropertyMap(config.map[shorthand]));
}
// @ts-ignore
this.declarations.get(shorthand).add(declaration);
// return this;
}
// @ts-ignore
else if (shortHandType == 'set') {
// @ts-ignore
// const shorthand: string = <string>config.properties[propertyName].shorthand;
if (!this.declarations.has(shorthand)) {
// @ts-ignore
this.declarations.set(shorthand, new PropertySet(config.properties[shorthand]));
}
// @ts-ignore
this.declarations.get(shorthand).add(declaration);
// return this;
}
else {
this.declarations.set(propertyName, declaration);
}
return this;
}
[Symbol.iterator]() {
let iterator = this.declarations.values();
const iterators = [];
return {
next() {
let value = iterator.next();
while ((value.done && iterators.length > 0) ||
value.value instanceof PropertySet ||
value.value instanceof PropertyMap) {
if (value.value instanceof PropertySet || value.value instanceof PropertyMap) {
iterators.unshift(iterator);
// @ts-ignore
iterator = value.value[Symbol.iterator]();
value = iterator.next();
}
if (value.done && iterators.length > 0) {
iterator = iterators.shift();
value = iterator.next();
}
}
return value;
}
};
}
}
class ComputeShorthandFeature {
static get ordering() {
return 2;
}
static register(options) {
if (options.computeShorthand) {
for (const feature of options.features) {
if (feature instanceof ComputeShorthandFeature) {
return;
}
}
// @ts-ignore
options.features.push(new ComputeShorthandFeature(options));
}
}
run(ast, options = {}, parent, context) {
// @ts-ignore
const j = ast.chi.length;
let k = 0;
let properties = new PropertyList(options);
// @ts-ignore
for (; k < j; k++) {
// @ts-ignore
const node = ast.chi[k];
if (node.typ == exports.EnumToken.CommentNodeType || node.typ == exports.EnumToken.DeclarationNodeType) {
properties.add(node);
continue;
}
break;
}
// @ts-ignore
ast.chi = [...properties].concat(ast.chi.slice(k));
return ast;
}
}
class ComputeCalcExpressionFeature {
static get ordering() {
return 1;
}
static register(options) {
if (options.computeCalcExpression) {
for (const feature of options.features) {
if (feature instanceof ComputeCalcExpressionFeature) {
return;
}
}
// @ts-ignore
options.features.push(new ComputeCalcExpressionFeature());
}
}
run(ast) {
if (!('chi' in ast)) {
return;
}
// @ts-ignore
for (const node of ast.chi) {
if (node.typ != exports.EnumToken.DeclarationNodeType) {
continue;
}
const set = new Set;
for (const { value, parent } of walkValues(node.val, node, {
event: WalkerValueEvent.Enter,
fn(node, parent, event) {
if (parent != null &&
parent.typ == exports.EnumToken.DeclarationNodeType &&
parent.val.length == 1 &&
node.typ == exports.EnumToken.FunctionTokenType &&
mathFuncs.includes(node.val) &&
node.chi.length == 1 &&
node.chi[0].typ == exports.EnumToken.IdenTokenType) {
return 'ignore';
}
if ((node.typ == exports.EnumToken.FunctionTokenType && node.val == 'var') || (!mathFuncs.includes(parent.val) && [exports.EnumToken.ColorTokenType, exports.EnumToken.DeclarationNodeType, exports.EnumToken.RuleNodeType, exports.EnumToken.AtRuleNodeType, exports.EnumToken.StyleSheetNodeType].includes(parent?.typ))) {
return null;
}
// @ts-ignore
const slice = (node.typ == exports.EnumToken.FunctionTokenType ? node.chi : (node.typ == exports.EnumToken.DeclarationNodeType ? node.val : node.chi))?.slice();
if (slice != null && node.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(node.val)) {
// @ts-ignore
const cp = (node.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(node.val) && node.val != 'calc' ? [node] : (node.typ == exports.EnumToken.DeclarationNodeType ? node.val : node.chi)).slice();
const values = evaluate(cp);
const key = 'chi' in node ? 'chi' : 'val';
const str1 = renderToken({ ...node, [key]: slice });
const str2 = renderToken(node); // values.reduce((acc: string, curr: Token): string => acc + renderToken(curr), '');
if (str1.length <= str2.length) {
// @ts-ignore
node[key] = slice;
}
else {
// @ts-ignore
node[key] = values;
}
return 'ignore';
}
return null;
}
})) {
if (value != null && value.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(value.val)) {
if (!set.has(value)) {
set.add(value);
if (parent != null) {
// @ts-ignore
const cp = value.typ == exports.EnumToken.FunctionTokenType && mathFuncs.includes(value.val) && value.val != 'calc' ? [value] : (value.typ == exports.EnumToken.DeclarationNodeType ? value.val : value.chi);
const values = evaluate(cp);
// @ts-ignore
const children = parent.typ == exports.EnumToken.DeclarationNodeType ? parent.val : parent.chi;
if (values.length == 1 && values[0].typ != exports.EnumToken.BinaryExpressionTokenType) {
if (parent.typ == exports.EnumToken.BinaryExpressionTokenType) {
if (parent.l == value) {
parent.l = values[0];
}
else {
parent.r = values[0];
}
}
else {
for (let i = 0; i < children.length; i++) {
if (children[i] == value) {
// @ts-ignore
children.splice(i, 1, !(parent.typ == exports.EnumToken.FunctionTokenType && parent.val == 'calc') && typeof values[0].val != 'string' ? {
typ: exports.EnumToken.FunctionTokenType,
val: 'calc',
chi: values
} : values[0]);
break;
}
}
}
}
else {
for (let i = 0; i < children.length; i++) {
if (children[i] == value) {
if (parent.typ == exports.EnumToken.FunctionTokenType && parent.val == 'calc') {
children.splice(i, 1, ...values);
}
else {
children.splice(i, 1, {
typ: exports.EnumToken.FunctionTokenType,
val: 'calc',
chi: values
});
}
break;
}
}
}
}
}
}
}
}
}
}
var allFeatures = /*#__PURE__*/Object.freeze({
__proto__: null,
ComputeCalcExpressionFeature: ComputeCalcExpressionFeature,
ComputePrefixFeature: ComputePrefixFeature,
ComputeShorthandFeature: ComputeShorthandFeature,
InlineCssVariablesFeature: InlineCssVariablesFeature
});
const combinators = ['+', '>', '~', '||', '|'];
const definedPropertySettings = { configurable: true, enumerable: false, writable: true };
const notEndingWith = ['(', '['].concat(combinators);
// @ts-ignore
const features = Object.values(allFeatures).sort((a, b) => a.ordering - b.ordering);
/**
* minify ast
* @param ast
* @param options
* @param recursive
* @param errors
* @param nestingContent
* @param context
*/
function minify(ast, options = {}, recursive = false, errors, nestingContent, context = {}) {
if (!('nodes' in context)) {
context.nodes = new Set;
}
if (context.nodes.has(ast)) {
return ast;
}
context.nodes.add(ast);
if (!('features' in options)) {
// @ts-ignore
options = {
removeDuplicateDeclarations: true,
computeShorthand: true,
computeCalcExpression: true,
removePrefix: false,
features: [], ...options
};
// @ts-ignore
for (const feature of features) {
feature.register(options);
}
}
function reducer(acc, curr, index, array) {
// trim :is()
if (array.length == 1 && array[0][0] == ':is(' && array[0].at(-1) == ')') {
curr = curr.slice(1, -1);
}
if (curr[0] == '&') {
if (curr[1] == ' ' && !isIdent(curr[2]) && !isFunction(curr[2])) {
curr.splice(0, 2);
}
else if (combinators.includes(curr[1])) {
curr.shift();
}
}
else if (ast.typ == exports.EnumToken.RuleNodeType && (isIdent(curr[0]) || isFunction(curr[0]))) {
curr.unshift('&', ' ');
}
acc.push(curr.join(''));
return acc;
}
// @ts-ignore
if ('chi' in ast && ast.chi.length > 0) {
if (!nestingContent) {
nestingContent = options.nestingRules && ast.typ == exports.EnumToken.RuleNodeType;
}
let i = 0;
let previous;
let node;
let nodeIndex;
// @ts-ignore
for (; i < ast.chi.length; i++) {
// @ts-ignore
if (ast.chi[i].typ == exports.EnumToken.CommentNodeType) {
continue;
}
// @ts-ignore
node = ast.chi[i];
// @ts-ignore
if (previous == node) {
// @ts-ignore
ast.chi.splice(i, 1);
i--;
continue;
}
if (node.typ == exports.EnumToken.AtRuleNodeType && node.nam == 'font-face') {
continue;
}
if (node.typ == exports.EnumToken.AtRuleNodeType) {
// @ts-ignore
if (node.nam == 'media' && ['all', '', null].includes(node.val)) {
// @ts-ignore
ast.chi?.splice(i, 1, ...node.chi);
i--;
continue;
}
// @ts-ignore
if (previous?.typ == exports.EnumToken.AtRuleNodeType &&
previous.nam == node.nam &&
previous.val == node.val) {
if ('chi' in node) {
// @ts-ignore
previous.chi.push(...node.chi);
}
ast?.chi?.splice(i--, 1);
continue;
}
// @ts-ignore
if (!hasDeclaration(node)) {
minify(node, options, recursive, errors, nestingContent, context);
}
previous = node;
nodeIndex = i;
continue;
}
// @ts-ignore
if (node.typ == exports.EnumToken.RuleNodeType) {
reduceRuleSelector(node);
let wrapper;
let match;
// @ts-ignore
if (options.nestingRules) {
// @ts-ignore
if (previous?.typ == exports.EnumToken.RuleNodeType) {
// @ts-ignore
reduceRuleSelector(previous);
// @ts-ignore
match = matchSelectors(previous.raw, node.raw, ast.typ, errors);
// @ts-ignore
if (match != null) {
// @ts-ignore
wrapper = wrapNodes(previous, node, match, ast, reducer, i, nodeIndex);
nodeIndex = i - 1;
// @ts-ignore
previous = ast.chi[nodeIndex];
}
}
// @ts-ignore
if (wrapper != null) {
// @ts-ignore
while (i < ast.chi.length) {
// @ts-ignore
const nextNode = ast.chi[i];
// @ts-ignore
if (nextNode.typ != exports.EnumToken.RuleNodeType) {
break;
}
reduceRuleSelector(nextNode);
// @ts-ignore
match = matchSelectors(wrapper.raw, nextNode.raw, ast.typ, errors);
// @ts-ignore
if (match == null) {
break;
}
// @ts-ignore
wrapper = wrapNodes(wrapper, nextNode, match, ast, reducer, i, nodeIndex);
}
nodeIndex = --i;
// @ts-ignore
previous = ast.chi[nodeIndex];
minify(wrapper, options, recursive, errors, nestingContent, context);
continue;
}
// @ts-ignore
else if (node.optimized != null &&
// @ts-ignore
node.optimized.match &&
// @ts-ignore
node.optimized.selector.length > 1) {
// @ts-ignore
wrapper = { ...node, chi: [], sel: node.optimized.optimized[0] };
// @ts-ignore
Object.defineProperty(wrapper, 'raw', {
...definedPropertySettings,
// @ts-ignore
value: [[node.optimized.optimized[0]]]
});
// @ts-ignore
node.sel = node.optimized.selector.reduce(reducer, []).join(',');
// @ts-ignore
node.raw = node.optimized.selector.slice();
// @ts-ignore
wrapper.chi.push(node);
// @ts-ignore
ast.chi.splice(i, 1, wrapper);
node = wrapper;
}
}
// @ts-ignore
else if (node.optimized?.match) {
let wrap = true;
// @ts-ignore
const selector = node.optimized.selector.reduce((acc, curr) => {
if (curr[0] == '&' && curr.length > 1) {
if (curr[1] == ' ') {
curr.splice(0, 2);
}
else {
if (ast.typ != exports.EnumToken.RuleNodeType && combinators.includes(curr[1])) {
wrap = false;
}
else {
curr.splice(0, 1);
}
}
}
else if (combinators.includes(curr[0])) {
curr.unshift('&');
wrap = false;
}
// @ts-ignore
acc.push(curr);
return acc;
}, []);
if (!wrap) {
wrap = selector.some((s) => s[0] != '&');
}
let rule = selector.map(s => {
if (s[0] == '&') {
// @ts-ignore
s[0] = node.optimized.optimized[0];
}
return s.join('');
}).join(',');
// @ts-ignore
let sel = wrap ? node.optimized.optimized.join('') + `:is(${rule})` : rule;
if (rule.includes('&')) {
// @ts-ignore
rule = replaceCompound(rule, node.optimized.optimized[0]);
}
if (sel.length < node.sel.length) {
node.sel = sel;
}
}
}
// @ts-ignore
if (previous != null) {
// @ts-ignore
if ('chi' in previous && ('chi' in node)) {
// @ts-ignore
if (previous.typ == node.typ) {
let shouldMerge = true;
// @ts-ignore
let k = previous.chi.length;
while (k-- > 0) {
// @ts-ignore
if (previous.chi[k].typ == exports.EnumToken.CommentNodeType) {
continue;
}
// @ts-ignore
shouldMerge = previous.chi[k].typ == exports.EnumToken.DeclarationNodeType;
break;
}
if (shouldMerge) {
// @ts-ignore
if (((node.typ == exports.EnumToken.RuleNodeType || node.typ == exports.EnumToken.KeyFrameRuleNodeType) && node.sel == previous.sel) ||
// @ts-ignore
(node.typ == exports.EnumToken.AtRuleNodeType) && node.val != 'font-face' && node.val == previous.val) {
// @ts-ignore
node.chi.unshift(...previous.chi);
// @ts-ignore
ast.chi.splice(nodeIndex, 1);
// @ts-ignore
if (!hasDeclaration(node)) {
// @ts-ignore
// minifyRule(node, <MinifyOptions>options, ast, context);
// } else {
minify(node, options, recursive, errors, nestingContent, context);
}
i--;
previous = node;
nodeIndex = i;
continue;
}
else if (node.typ == previous?.typ && [exports.EnumToken.KeyFrameRuleNodeType, exports.EnumToken.RuleNodeType].includes(node.typ)) {
const intersect = diff(previous, node, reducer, options);
if (intersect != null) {
if (intersect.node1.chi.length == 0) {
// @ts-ignore
ast.chi.splice(i--, 1);
// @ts-ignore
// node = ast.chi[i];
}
else {
// @ts-ignore
ast.chi.splice(i--, 1, intersect.node1);
// node = ast.chi intersect.node1;
}
if (intersect.node2.chi.length == 0) {
// @ts-ignore
ast.chi.splice(nodeIndex, 1, intersect.result);
i--;
// @ts-ignore
if (nodeIndex == i) {
nodeIndex = i;
}
}
else {
// @ts-ignore
ast.chi.splice(nodeIndex, 1, intersect.result, intersect.node2);
// @ts-ignore
i = (nodeIndex ?? 0) + 1;
}
reduceRuleSelector(intersect.result);
// @ts-ignore
if (node != ast.chi[i]) {
// @ts-ignore
node = ast.chi[i];
}
previous = intersect.result;
nodeIndex = i;
}
}
}
}
// @ts-ignore
if (recursive && previous != node) {
// @ts-ignore
if (!hasDeclaration(previous)) {
// @ts-ignore
// minifyRule(previous, <MinifyOptions>options, ast, context);
// } else {
minify(previous, options, recursive, errors, nestingContent, context);
}
}
}
else {
if ('chi' in previous) {
// @ts-ignore
if (!hasDeclaration(previous)) {
// @ts-ignore
// minifyRule(previous, <MinifyOptions>options, ast, context);
// } else {
minify(previous, options, recursive, errors, nestingContent, context);
}
}
}
}
if (!nestingContent &&
// @ts-ignore
previous != null &&
// previous.optimized != null &&
previous.typ == exports.EnumToken.RuleNodeType &&
previous.sel.includes('&')) {
fixSelector(previous);
}
previous = node;
nodeIndex = i;
}
// @ts-ignore
if (recursive && node != null && ('chi' in node)) {
// @ts-ignore
if (!node.chi.some(n => n.typ == exports.EnumToken.DeclarationNodeType)) {
// @ts-ignore
if (!(node.typ == exports.EnumToken.AtRuleNodeType && node.nam != 'font-face')) {
minify(node, options, recursive, errors, nestingContent, context);
}
}
}
if (!nestingContent &&
// @ts-ignore
node != null &&
// previous.optimized != null &&
node.typ == exports.EnumToken.RuleNodeType &&
node.sel.includes('&')) {
fixSelector(node);
}
}
if (ast.typ == exports.EnumToken.StyleSheetNodeType) {
let parent;
let parents = [ast];
while (parents.length > 0) {
parent = parents.shift();
// @ts-ignore
for (let k = 0; k < parent.chi.length; k++) {
// @ts-ignore
const node = parent.chi[k];
if (!('chi' in node) || node.typ == exports.EnumToken.StyleSheetNodeType || (node.typ == exports.EnumToken.AtRuleNodeType && node.nam == 'font-face')) {
continue;
}
// @ts-ignore
if (node.chi.length > 0) {
parents.push(node);
Object.defineProperty(node, 'parent', { ...definedPropertySettings, value: parent });
for (const feature of options.features) {
feature.run(node, options, parent, context);
}
}
// @ts-ignore
if (options.removeEmpty && node.chi.length == 0) {
// @ts-ignore
parent.chi.splice(k, 1);
k--;
}
}
}
for (const feature of options.features) {
if ('cleanup' in feature) {
// @ts-ignore
feature.cleanup(ast, options, context);
}
}
}
return ast;
}
function hasDeclaration(node) {
// @ts-ignore
for (let i = 0; i < node.chi?.length; i++) {
// @ts-ignore
if (node.chi[i].typ == exports.EnumToken.CommentNodeType) {
continue;
}
// @ts-ignore
return node.chi[i].typ == exports.EnumToken.DeclarationNodeType;
}
return true;
}
function reduceSelector(selector) {
if (selector.length == 0) {
return null;
}
selector = selector.reduce((acc, curr) => {
// @ts-ignore
if (curr.length > 0 && curr.at(-1).startsWith(':is(')) {
// @ts-ignore
const rules = splitRule(curr.at(-1).slice(4, -1)).map(x => {
if (x[0] == '&' && x.length > 1) {
return x.slice(x[1] == ' ' ? 2 : 1);
}
return x;
});
const part = curr.slice(0, -1);
for (const rule of rules) {
acc.push(part.concat(rule));
}
return acc;
}
acc.push(curr);
return acc;
}, []);
const optimized = [];
const k = selector.reduce((acc, curr) => acc == 0 ? curr.length : (curr.length == 0 ? acc : Math.min(acc, curr.length)), 0);
let i = 0;
let j;
let match;
for (; i < k; i++) {
const item = selector[0][i];
match = true;
for (j = 1; j < selector.length; j++) {
if (item != selector[j][i]) {
match = false;
break;
}
}
if (!match) {
break;
}
optimized.push(item);
}
while (optimized.length > 0) {
const last = optimized.at(-1);
if ((last == ' ' || combinators.includes(last))) {
optimized.pop();
continue;
}
break;
}
selector.forEach((selector) => selector.splice(0, optimized.length));
// combinator
if (combinators.includes(optimized.at(-1))) {
const combinator = optimized.pop();
selector.forEach((selector) => selector.unshift(combinator));
}
let reducible = optimized.length == 1;
if (optimized[0] == '&') {
if (optimized[1] == ' ') {
optimized.splice(0, 2);
}
}
if (optimized.length == 0 ||
(optimized[0].charAt(0) == '&' ||
selector.length == 1)) {
return {
match: false,
optimized,
selector: selector.map((selector) => selector[0] == '&' && selector[1] == ' ' ? selector.slice(2) : (selector)),
reducible: selector.length > 1 && selector.every((selector) => !combinators.includes(selector[0]))
};
}
return {
match: true,
optimized,
selector: selector.reduce((acc, curr) => {
let hasCompound = true;
if (hasCompound && curr.length > 0) {
hasCompound = !['&'].concat(combinators).includes(curr[0].charAt(0));
}
// @ts-ignore
if (hasCompound && curr[0] == ' ') {
hasCompound = false;
curr.unshift('&');
}
if (curr.length == 0) {
curr.push('&');
hasCompound = false;
}
if (reducible) {
const chr = curr[0].charAt(0);
// @ts-ignore
reducible = chr == '.' || chr == ':' || isIdentStart(chr.codePointAt(0));
}
acc.push(hasCompound ? ['&'].concat(curr) : curr);
return acc;
}, []),
reducible: selector.every((selector) => !['>', '+', '~', '&'].includes(selector[0]))
};
}
/**
* split selector string
* @param buffer
*/
function splitRule(buffer) {
const result = [[]];
let str = '';
for (let i = 0; i < buffer.length; i++) {
let chr = buffer.charAt(i);
if (isWhiteSpace(chr.charCodeAt(0))) {
let k = i;
while (k + 1 < buffer.length) {
if (isWhiteSpace(buffer[k + 1].charCodeAt(0))) {
k++;
continue;
}
break;
}
if (str !== '') {
// @ts-ignore
result.at(-1).push(str);
str = '';
}
// @ts-ignore
if (result.at(-1).length > 0) {
// @ts-ignore
result.at(-1).push(' ');
}
i = k;
continue;
}
if (chr == ',') {
if (str !== '') {
// @ts-ignore
result.at(-1).push(str);
str = '';
}
result.push([]);
continue;
}
if (chr == ':') {
if (str !== '') {
// @ts-ignore
result.at(-1).push(str);
str = '';
}
if (buffer.charAt(i + 1) == ':') {
chr += buffer.charAt(++i);
}
str += chr;
continue;
}
str += chr;
if (chr == '\\') {
str += buffer.charAt(++i);
continue;
}
if (chr == '"' || chr == "'") {
let k = i;
while (++k < buffer.length) {
chr = buffer.charAt(k);
str += chr;
if (chr == '//') {
str += buffer.charAt(++k);
continue;
}
if (chr == buffer.charAt(i)) {
break;
}
}
continue;
}
if (chr == '(' || chr == '[') {
const open = chr;
const close = chr == '(' ? ')' : ']';
let inParens = 1;
let k = i;
while (++k < buffer.length) {
chr = buffer.charAt(k);
if (chr == '\\') {
str += buffer.slice(k, k + 2);
k++;
continue;
}
str += chr;
if (chr == open) {
inParens++;
}
else if (chr == close) {
inParens--;
}
if (inParens == 0) {
break;
}
}
i = k;
}
}
if (str !== '') {
// @ts-ignore
result.at(-1).push(str);
}
return result;
}
function matchSelectors(selector1, selector2, parentType, errors) {
let match = [[]];
const j = Math.min(selector1.reduce((acc, curr) => Math.min(acc, curr.length), selector1.length > 0 ? selector1[0].length : 0), selector2.reduce((acc, curr) => Math.min(acc, curr.length), selector2.length > 0 ? selector2[0].length : 0));
let i = 0;
let k;
let l;
let token;
let matching = true;
let matchFunction = 0;
let inAttr = 0;
for (; i < j; i++) {
k = 0;
token = selector1[0][i];
for (; k < selector1.length; k++) {
if (selector1[k][i] != token) {
matching = false;
break;
}
}
if (matching) {
l = 0;
for (; l < selector2.length; l++) {
if (selector2[l][i] != token) {
matching = false;
break;
}
}
}
if (!matching) {
break;
}
if (token == ',') {
match.push([]);
}
else {
if (token.endsWith('(')) {
matchFunction++;
}
if (token.endsWith('[')) {
inAttr++;
}
else if (token == ')') {
matchFunction--;
}
else if (token == ']') {
inAttr--;
}
match.at(-1).push(token);
}
}
// invalid function
if (matchFunction != 0 || inAttr != 0) {
return null;
}
if (parentType != exports.EnumToken.RuleNodeType) {
for (const part of match) {
if (part.length > 0 && combinators.includes(part[0].charAt(0))) {
return null;
}
}
}
if (match.length > 1) {
errors?.push({
action: 'ignore',
message: `minify: unsupported multilevel matching\n${JSON.stringify({
match,
selector1,
selector2
}, null, 1)}`
});
return null;
}
for (const part of match) {
while (part.length > 0) {
const token = part.at(-1);
if (token == ' ' || combinators.includes(token) || notEndingWith.includes(token.at(-1))) {
part.pop();
continue;
}
break;
}
}
if (match.every(t => t.length == 0)) {
return null;
}
if (eq([['&']], match)) {
return null;
}
function reduce(acc, curr) {
if (acc === null) {
return null;
}
let hasCompoundSelector = true;
curr = curr.slice(match[0].length);
while (curr.length > 0) {
if (curr[0] == ' ') {
hasCompoundSelector = false;
curr.unshift('&');
continue;
}
break;
}
// invalid function match
if (curr.length > 0 && curr[0].endsWith('(') && curr.at(-1) != ')') {
return null;
}
if (curr.length == 1 && combinators.includes(curr[0].charAt(0))) {
return null;
}
if (hasCompoundSelector && curr.length > 0) {
hasCompoundSelector = !['&'].concat(combinators).includes(curr[0].charAt(0));
}
if (curr[0] == ':is(') {
let inFunction = 0;
let canReduce = true;
const isCompound = curr.reduce((acc, token, index) => {
if (index == 0) {
inFunction++;
canReduce = curr[1] == '&';
}
else if (token.endsWith('(')) {
if (inFunction == 0) {
canReduce = false;
}
inFunction++;
}
else if (token == ')') {
inFunction--;
}
else if (token == ',') {
if (!canReduce) {
canReduce = curr[index + 1] == '&';
}
acc.push([]);
}
else
acc.at(-1)?.push(token);
return acc;
}, [[]]);
if (inFunction > 0) {
canReduce = false;
}
if (canReduce) {
curr = isCompound.reduce((acc, curr) => {
if (acc.length > 0) {
acc.push(',');
}
acc.push(...curr);
return acc;
}, []);
}
}
// @todo: check hasCompoundSelector && curr[0] == '&' && curr[1] == ' '
acc.push(match.length == 0 ? ['&'] : (hasCompoundSelector && curr[0] != '&' && (curr.length == 0 || !combinators.includes(curr[0].charAt(0))) ? ['&'].concat(curr) : curr));
return acc;
}
// @ts-ignore
selector1 = selector1.reduce(reduce, []);
// @ts-ignore
selector2 = selector2.reduce(reduce, []);
return selector1 == null || selector2 == null ? null : {
eq: eq(selector1, selector2),
match,
selector1,
selector2
};
}
function fixSelector(node) {
// @ts-ignore
if (node.sel.includes('&')) {
const attributes = parseString(node.sel);
for (const attr of walkValues(attributes)) {
if (attr.value.typ == exports.EnumToken.PseudoClassFuncTokenType && attr.value.val == ':is') {
let i = attr.value.chi.length;
while (i--) {
if (attr.value.chi[i].typ == exports.EnumToken.LiteralTokenType && attr.value.chi[i].val == '&') {
attr.value.chi.splice(i, 1);
}
}
}
}
node.sel = attributes.reduce((acc, curr) => acc + renderToken(curr), '');
}
}
function wrapNodes(previous, node, match, ast, reducer, i, nodeIndex) {
// @ts-ignore
let pSel = match.selector1.reduce(reducer, []).join(',');
// @ts-ignore
let nSel = match.selector2.reduce(reducer, []).join(',');
// @ts-ignore
const wrapper = { ...previous, chi: [], sel: match.match.reduce(reducer, []).join(',') };
// @ts-ignore
Object.defineProperty(wrapper, 'raw', {
...definedPropertySettings,
// @ts-ignore
value: match.match.map(t => t.slice())
});
if (pSel == '&' || pSel === '') {
// @ts-ignore
wrapper.chi.push(...previous.chi);
// @ts-ignore
if ((nSel == '&' || nSel === '')) {
// @ts-ignore
wrapper.chi.push(...node.chi);
}
else {
// @ts-ignore
wrapper.chi.push(node);
}
}
else {
// @ts-ignore
wrapper.chi.push(previous, node);
}
// @ts-ignore
ast.chi.splice(i, 1, wrapper);
// @ts-ignore
ast.chi.splice(nodeIndex, 1);
// @ts-ignore
previous.sel = pSel;
// @ts-ignore
previous.raw = match.selector1;
// @ts-ignore
node.sel = nSel;
// @ts-ignore
node.raw = match.selector2;
reduceRuleSelector(wrapper);
return wrapper;
}
function diff(n1, n2, reducer, options = {}) {
let node1 = n1;
let node2 = n2;
let exchanged = false;
if (node1.chi.length > node2.chi.length) {
const t = node1;
node1 = node2;
node2 = t;
exchanged = true;
}
let i = node1.chi.length;
let j = node2.chi.length;
if (i == 0 || j == 0) {
// @ts-ignore
return null;
}
// @ts-ignore
const raw1 = node1.raw;
// @ts-ignore
const raw2 = node2.raw;
if (raw1 != null && raw2 != null) {
const prefixes1 = new Set;
const prefixes2 = new Set;
for (const token1 of raw1) {
for (const t of token1) {
if (t[0] == ':') {
const matches = t.match(/::?-([a-z]+)-/);
if (matches == null) {
continue;
}
prefixes1.add(matches[1]);
if (prefixes1.size > 1) {
break;
}
}
}
if (prefixes1.size > 1) {
break;
}
}
for (const token2 of raw2) {
for (const t of token2) {
if (t[0] == ':') {
const matches = t.match(/::?-([a-z]+)-/);
if (matches == null) {
continue;
}
prefixes2.add(matches[1]);
if (prefixes2.size > 1) {
break;
}
}
}
if (prefixes2.size > 1) {
break;
}
}
if (prefixes1.size != prefixes2.size) {
return null;
}
for (const prefix of prefixes1) {
if (!prefixes2.has(prefix)) {
return null;
}
}
}
// @ts-ignore
node1 = { ...node1, chi: node1.chi.slice() };
node2 = { ...node2, chi: node2.chi.slice() };
if (raw1 != null) {
Object.defineProperty(node1, 'raw', { ...definedPropertySettings, value: raw1 });
}
if (raw2 != null) {
Object.defineProperty(node2, 'raw', { ...definedPropertySettings, value: raw2 });
}
const intersect = [];
while (i--) {
if (node1.chi[i].typ == exports.EnumToken.CommentNodeType) {
continue;
}
j = node2.chi.length;
if (j == 0) {
break;
}
while (j--) {
if (node2.chi[j].typ == exports.EnumToken.CommentNodeType) {
continue;
}
if (node1.chi[i].nam == node2.chi[j].nam) {
if (eq(node1.chi[i], node2.chi[j])) {
intersect.push(node1.chi[i]);
node1.chi.splice(i, 1);
node2.chi.splice(j, 1);
break;
}
}
}
}
// @ts-ignore
const result = (intersect.length == 0 ? null : {
...node1,
// @ts-ignore
sel: [...new Set([...(n1?.raw?.reduce(reducer, []) ?? splitRule(n1.sel)).concat(n2?.raw?.reduce(reducer, []) ?? splitRule(n2.sel))])].join(','),
chi: intersect.reverse()
});
if (result == null || [n1, n2].reduce((acc, curr) => curr.chi.length == 0 ? acc : acc + doRender(curr, options).code.length, 0) <= [node1, node2, result].reduce((acc, curr) => curr.chi.length == 0 ? acc : acc + doRender(curr, options).code.length, 0)) {
// @ts-ignore
return null;
}
return { result, node1: exchanged ? node2 : node1, node2: exchanged ? node1 : node2 };
}
function reduceRuleSelector(node) {
if (node.raw == null) {
Object.defineProperty(node, 'raw', { ...definedPropertySettings, value: splitRule(node.sel) });
}
// @ts-ignore
// if (node.raw != null) {
// @ts-ignore
let optimized = reduceSelector(node.raw.reduce((acc, curr) => {
acc.push(curr.slice());
return acc;
}, []));
if (optimized != null) {
Object.defineProperty(node, 'optimized', { ...definedPropertySettings, value: optimized });
}
if (optimized != null && optimized.match && optimized.reducible && optimized.selector.length > 1) {
for (const selector of optimized.selector) {
if (selector.length > 1 && selector[0] == '&' &&
(combinators.includes(selector[1]) || !/^[a-zA-Z:]/.test(selector[1]))) {
selector.shift();
}
}
const unique = new Set;
const raw = [
[
optimized.optimized[0], ':is('
].concat(optimized.selector.reduce((acc, curr) => {
const sig = curr.join('');
if (!unique.has(sig)) {
if (acc.length > 0) {
acc.push(',');
}
unique.add(sig);
acc.push(...curr);
}
return acc;
}, [])).concat(')')
];
const sel = raw[0].join('');
if (sel.length < node.sel.length) {
node.sel = sel;
// node.raw = raw;
Object.defineProperty(node, 'raw', { ...definedPropertySettings, value: raw });
}
}
}
const matchUrl = /^(https?:)?\/\//;
function dirname(path) {
if (path == '/' || path === '') {
return path;
}
let i = 0;
let parts = [''];
for (; i < path.length; i++) {
const chr = path.charAt(i);
if (chr == '/') {
parts.push('');
}
else if (chr == '?' || chr == '#') {
break;
}
else {
parts[parts.length - 1] += chr;
}
}
parts.pop();
return parts.length == 0 ? '/' : parts.join('/');
}
function splitPath(result) {
const parts = [''];
let i = 0;
for (; i < result.length; i++) {
const chr = result.charAt(i);
if (chr == '/') {
parts.push('');
}
else if (chr == '?' || chr == '#') {
break;
}
else {
parts[parts.length - 1] += chr;
}
}
let k = -1;
while (++k < parts.length) {
if (parts[k] == '.') {
parts.splice(k--, 1);
}
else if (parts[k] == '..') {
parts.splice(k - 1, 2);
k -= 2;
}
}
return { parts, i };
}
function resolve(url, currentDirectory, cwd) {
if (matchUrl.test(url)) {
return {
absolute: url,
relative: url
};
}
if (matchUrl.test(currentDirectory)) {
const path = new URL(url, currentDirectory).href;
return {
absolute: path,
relative: path
};
}
let result;
if (url.charAt(0) == '/') {
result = url;
}
else if (currentDirectory.charAt(0) == '/') {
result = dirname(currentDirectory) + '/' + url;
}
else if (currentDirectory === '' || dirname(currentDirectory) === '') {
result = url;
}
else {
result = dirname(currentDirectory) + '/' + url;
}
let { parts, i } = splitPath(result);
if (parts.length == 0) {
const path = result.charAt(0) == '/' ? '/' : '';
return {
absolute: path,
relative: path
};
}
const absolute = parts.join('/');
const { parts: dirs } = splitPath(cwd ?? currentDirectory);
for (const p of dirs) {
if (parts[0] == p) {
parts.shift();
}
else {
parts.unshift('..');
}
}
return {
absolute,
relative: parts.join('/') + (i < result.length ? result.slice(i) : '')
};
}
function parseResponse(response) {
if (!response.ok) {
throw new Error(`${response.status} ${response.statusText} ${response.url}`);
}
return response.text();
}
async function load(url, currentFile) {
let t;
if (matchUrl.test(url)) {
t = new URL(url);
}
else if (matchUrl.test(currentFile)) {
t = new URL(url, currentFile);
}
else {
const path = resolve(url, currentFile).absolute;
// @ts-ignore
t = new URL(path, self.origin);
}
// @ts-ignore
return fetch(t, t.origin != self.origin ? { mode: 'cors' } : {}).then(parseResponse);
}
/**
* render ast node
*/
function render(data, options = {}) {
return doRender(data, Object.assign(options, {
load,
resolve,
dirname,
cwd: options.cwd ?? self.location.pathname.endsWith('/') ? self.location.pathname : dirname(self.location.pathname)
}));
}
/**
* parse css
*/
async function parse(iterator, opt = {}) {
return doParse(iterator, Object.assign(opt, {
load,
resolve,
dirname,
cwd: opt.cwd ?? self.location.pathname.endsWith('/') ? self.location.pathname : dirname(self.location.pathname)
}));
}
/**
* parse and render css
*/
async function transform(css, options = {}) {
options = { minify: true, removeEmpty: true, removeCharset: true, ...options };
const startTime = performance.now();
return parse(css, options).then((parseResult) => {
const rendered = render(parseResult.ast, options);
return {
...parseResult,
...rendered,
errors: parseResult.errors.concat(rendered.errors),
stats: {
bytesOut: rendered.code.length,
...parseResult.stats,
render: rendered.stats.total,
total: `${(performance.now() - startTime).toFixed(2)}ms`
}
};
});
}
exports.dirname = dirname;
exports.expand = expand;
exports.load = load;
exports.minify = minify;
exports.parse = parse;
exports.parseString = parseString;
exports.parseTokens = parseTokens;
exports.render = render;
exports.renderToken = renderToken;
exports.resolve = resolve;
exports.transform = transform;
exports.walk = walk;
exports.walkValues = walkValues;
}));