astro-reactive-form/apps/landing-page/.netlify/functions-internal/chunks/pages/index_b8dca542.mjs
2023-09-25 16:43:32 +02:00

66133 lines
1.8 MiB
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* empty css */import require$$0$a from 'os';
import 'fs';
import 'url';
import 'path';
import require$$0$5 from '@trysound/sax';
import require$$0$6 from 'domelementtype';
import require$$1$2 from 'boolbase';
import require$$0$7 from 'css-what';
import require$$0$8 from 'nth-check';
import require$$0$9 from 'source-map-js/lib/source-map-generator.js';
import { c as createAstro, d as createComponent, r as renderTemplate, m as maybeRenderHead, s as spreadAttributes, f as addAttribute, u as unescapeHTML, g as renderComponent, F as Fragment, h as renderHead } from '../astro_bfe7ba8a.mjs';
import { IconSet } from '@iconify/tools';
import 'clsx';
import 'html-escaper';
const __vite_glob_1_0 = "<svg viewBox=\"0 0 627 894\" fill=\"none\">\n <path\n fill-rule=\"evenodd\"\n clip-rule=\"evenodd\"\n d=\"M445.433 22.9832C452.722 32.0324 456.439 44.2432 463.873 68.6647L626.281 602.176C566.234 571.026 500.957 548.56 432.115 536.439L326.371 179.099C324.641 173.252 319.27 169.241 313.173 169.241C307.06 169.241 301.68 173.273 299.963 179.14L195.5 536.259C126.338 548.325 60.7632 570.832 0.459473 602.095L163.664 68.5412C171.121 44.1617 174.85 31.9718 182.14 22.9393C188.575 14.9651 196.946 8.77213 206.454 4.95048C217.224 0.621582 229.971 0.621582 255.466 0.621582H372.034C397.562 0.621582 410.326 0.621582 421.106 4.95951C430.622 8.78908 438.998 14.9946 445.433 22.9832Z\"\n fill=\"currentColor\"\n />\n <path\n fill-rule=\"evenodd\"\n clip-rule=\"evenodd\"\n d=\"M464.867 627.566C438.094 650.46 384.655 666.073 323.101 666.073C247.551 666.073 184.229 642.553 167.426 610.921C161.419 629.05 160.072 649.798 160.072 663.052C160.072 663.052 156.114 728.134 201.38 773.401C201.38 749.896 220.435 730.842 243.939 730.842C284.226 730.842 284.181 765.99 284.144 794.506C284.143 795.36 284.142 796.209 284.142 797.051C284.142 840.333 310.595 877.436 348.215 893.075C342.596 881.518 339.444 868.54 339.444 854.825C339.444 813.545 363.679 798.175 391.845 780.311C414.255 766.098 439.155 750.307 456.315 718.629C465.268 702.101 470.352 683.17 470.352 663.052C470.352 650.68 468.43 638.757 464.867 627.566Z\"\n fill=\"#FF5D01\"\n />\n</svg>\n";
const __vite_glob_1_1 = "<!-- source: https://github.com/basmilius/weather-icons -->\n<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n viewBox=\"0 0 512 512\"\n>\n <defs>\n <linearGradient\n id=\"a\"\n x1=\"54.33\"\n y1=\"29.03\"\n x2=\"187.18\"\n y2=\"259.13\"\n gradientUnits=\"userSpaceOnUse\"\n >\n <stop offset=\"0\" stop-color=\"currentColor\" />\n <stop offset=\"0.45\" stop-color=\"currentColor\" />\n <stop offset=\"1\" stop-color=\"currentColor\" />\n </linearGradient>\n <linearGradient\n id=\"b\"\n x1=\"294\"\n y1=\"112.82\"\n x2=\"330\"\n y2=\"175.18\"\n gradientUnits=\"userSpaceOnUse\"\n >\n <stop offset=\"0\" stop-color=\"currentColor\" />\n <stop offset=\"0.45\" stop-color=\"currentColor\" />\n <stop offset=\"1\" stop-color=\"currentColor\" />\n </linearGradient>\n <linearGradient\n id=\"c\"\n x1=\"295.52\"\n y1=\"185.86\"\n x2=\"316.48\"\n y2=\"222.14\"\n xlink:href=\"#b\"\n />\n <linearGradient\n id=\"d\"\n x1=\"356.29\"\n y1=\"194.78\"\n x2=\"387.71\"\n y2=\"249.22\"\n xlink:href=\"#b\"\n />\n <symbol id=\"e\" viewBox=\"0 0 270 270\" overflow=\"visible\">\n <!-- moon -->\n <path\n d=\"M252.25,168.63C178.13,168.63,118,109.35,118,36.21A130.48,130.48,0,0,1,122.47,3C55.29,10.25,3,66.37,3,134.58,3,207.71,63.09,267,137.21,267,199.69,267,252,224.82,267,167.79A135.56,135.56,0,0,1,252.25,168.63Z\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"6\"\n fill=\"url(#a)\"\n >\n <animateTransform\n attributeName=\"transform\"\n additive=\"sum\"\n type=\"rotate\"\n values=\"-15 135 135; 9 135 135; -15 135 135\"\n dur=\"6s\"\n repeatCount=\"indefinite\"\n />\n </path>\n </symbol>\n </defs>\n\n <!-- star-1 -->\n <path\n d=\"M282.83,162.84l24.93-6.42a1.78,1.78,0,0,1,1.71.46l18.37,18a1.8,1.8,0,0,0,3-1.73l-6.42-24.93a1.78,1.78,0,0,1,.46-1.71l18-18.37a1.8,1.8,0,0,0-1.73-3l-24.93,6.42a1.78,1.78,0,0,1-1.71-.46l-18.37-18a1.8,1.8,0,0,0-3,1.73l6.42,24.93a1.78,1.78,0,0,1-.46,1.71l-18,18.37A1.8,1.8,0,0,0,282.83,162.84Z\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n fill=\"url(#b)\"\n >\n <animateTransform\n attributeName=\"transform\"\n additive=\"sum\"\n type=\"rotate\"\n values=\"-15 312 144; 15 312 144; -15 312 144\"\n dur=\"6s\"\n calcMode=\"spline\"\n keySplines=\".42, 0, .58, 1; .42, 0, .58, 1\"\n repeatCount=\"indefinite\"\n />\n\n <animate\n attributeName=\"opacity\"\n values=\"1; .75; 1; .75; 1; .75; 1\"\n dur=\"6s\"\n />\n </path>\n\n <!-- star-2 -->\n <path\n d=\"M285.4,193.44l12,12.25a1.19,1.19,0,0,1,.3,1.14l-4.28,16.62a1.2,1.2,0,0,0,2,1.15l12.25-12a1.19,1.19,0,0,1,1.14-.3l16.62,4.28a1.2,1.2,0,0,0,1.15-2l-12-12.25a1.19,1.19,0,0,1-.3-1.14l4.28-16.62a1.2,1.2,0,0,0-2-1.15l-12.25,12a1.19,1.19,0,0,1-1.14.3l-16.62-4.28A1.2,1.2,0,0,0,285.4,193.44Z\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n fill=\"url(#c)\"\n >\n <animateTransform\n attributeName=\"transform\"\n additive=\"sum\"\n type=\"rotate\"\n values=\"-15 306 204; 15 306 204; -15 306 204\"\n begin=\"-.33s\"\n dur=\"6s\"\n calcMode=\"spline\"\n keySplines=\".42, 0, .58, 1; .42, 0, .58, 1\"\n repeatCount=\"indefinite\"\n />\n\n <animate\n attributeName=\"opacity\"\n values=\"1; .75; 1; .75; 1; .75; 1\"\n begin=\"-.33s\"\n dur=\"6s\"\n />\n </path>\n\n <!-- star-3 -->\n <path\n d=\"M337.32,223.73l24.8,6.9a1.83,1.83,0,0,1,1.25,1.25l6.9,24.8a1.79,1.79,0,0,0,3.46,0l6.9-24.8a1.83,1.83,0,0,1,1.25-1.25l24.8-6.9a1.79,1.79,0,0,0,0-3.46l-24.8-6.9a1.83,1.83,0,0,1-1.25-1.25l-6.9-24.8a1.79,1.79,0,0,0-3.46,0l-6.9,24.8a1.83,1.83,0,0,1-1.25,1.25l-24.8,6.9A1.79,1.79,0,0,0,337.32,223.73Z\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n fill=\"url(#d)\"\n >\n <animateTransform\n attributeName=\"transform\"\n additive=\"sum\"\n type=\"rotate\"\n values=\"-15 372 222; 15 372 222; -15 372 222\"\n begin=\"-.67s\"\n dur=\"6s\"\n calcMode=\"spline\"\n keySplines=\".42, 0, .58, 1; .42, 0, .58, 1\"\n repeatCount=\"indefinite\"\n />\n\n <animate\n attributeName=\"opacity\"\n values=\"1; .75; 1; .75; 1; .75; 1\"\n begin=\"-.67s\"\n dur=\"6s\"\n />\n </path>\n\n <use\n width=\"270\"\n height=\"270\"\n transform=\"translate(121 121)\"\n xlink:href=\"#e\"\n />\n</svg>\n";
const __vite_glob_1_2 = "<!-- source: https://github.com/basmilius/weather-icons -->\n<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n viewBox=\"0 0 512 512\"\n>\n <defs>\n <linearGradient\n id=\"a\"\n x1=\"149.99\"\n y1=\"119.24\"\n x2=\"234.01\"\n y2=\"264.76\"\n gradientUnits=\"userSpaceOnUse\"\n >\n <stop offset=\"0\" stop-color=\"currentColor\" />\n <stop offset=\"0.45\" stop-color=\"currentColor\" />\n <stop offset=\"1\" stop-color=\"currentColor\" />\n </linearGradient>\n <symbol id=\"b\" viewBox=\"0 0 384 384\">\n <!-- core -->\n <circle\n cx=\"192\"\n cy=\"192\"\n r=\"84\"\n stroke=\"currentColor\"\n stroke-miterlimit=\"10\"\n stroke-width=\"6\"\n fill=\"url(#a)\"\n />\n\n <!-- rays -->\n <path\n d=\"M192,61.66V12m0,360V322.34M284.17,99.83l35.11-35.11M64.72,319.28l35.11-35.11m0-184.34L64.72,64.72M319.28,319.28l-35.11-35.11M61.66,192H12m360,0H322.34\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-miterlimit=\"10\"\n stroke-width=\"24\"\n >\n <animateTransform\n attributeName=\"transform\"\n additive=\"sum\"\n type=\"rotate\"\n values=\"0 192 192; 45 192 192\"\n dur=\"6s\"\n repeatCount=\"indefinite\"\n />\n </path>\n </symbol>\n </defs>\n <use width=\"384\" height=\"384\" transform=\"translate(64 64)\" xlink:href=\"#b\" />\n</svg>\n";
const __vite_glob_1_3 = "<svg viewBox=\"0 0 1847 457\" fill=\"none\">\n <path\n d=\"M134.148 456.833C202.08 456.833 253.03 432.665 273.93 391.516C273.93 411.111 275.23 431.36 278.5 447.036H390.19C384.97 424.173 382.36 392.82 382.36 351.671V251.081C382.36 155.717 326.18 110.648 201.43 110.648C92.3441 110.648 19.188 155.717 10.697 229.527H126.963C130.882 197.521 157.66 179.885 201.43 179.885C244.53 179.885 268.7 197.521 268.7 234.1V243.896L150.48 254.347C92.997 260.227 60.338 270.023 37.477 285.7C13.31 302.028 0.898987 326.851 0.898987 357.549C0.898987 418.948 51.847 456.833 134.148 456.833ZM177.26 388.902C139.37 388.902 116.512 373.88 116.512 349.712C116.512 324.892 135.45 311.827 183.14 305.949L270.66 296.805V316.4C270.66 360.163 232.78 388.902 177.26 388.902Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M625.77 456.833C739.43 456.833 797.56 414.377 797.56 345.793C797.56 288.966 764.9 257.613 685.87 247.162L587.23 236.059C559.15 232.138 547.39 224.953 547.39 209.277C547.39 190.336 566.33 181.844 609.44 181.844C668.88 181.844 710.03 195.561 743.35 222.342L796.25 169.434C759.67 131.55 696.32 110.648 617.94 110.648C507.55 110.648 446.15 149.838 446.15 215.809C446.15 273.289 484.03 305.295 562.41 315.745L651.25 326.196C686.52 330.769 696.97 337.302 696.97 354.283C696.97 373.88 677.37 384.331 631.65 384.331C563.72 384.331 518 366.041 487.3 332.076L427.21 381.717C467.05 431.36 534.98 456.833 625.77 456.833Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M889.78 194.255V332.076C889.78 413.07 935.5 454.221 1033.48 454.221C1063.53 454.221 1087.04 450.955 1109.25 444.423V359.508C1097.49 362.122 1083.12 364.734 1064.18 364.734C1023.03 364.734 1002.78 346.446 1002.78 307.908V194.255H1109.9V120.445H1002.78V0.914001L889.78 42.717V120.445H816.62V194.255H889.78Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M1272.13 120.445H1168.93V447.036H1281.93V324.892C1281.93 289.618 1289.77 257.613 1311.33 237.364C1328.31 221.687 1352.48 213.198 1386.44 213.198C1398.85 213.198 1408.65 214.502 1419.75 215.809V113.26C1412.57 111.954 1407.34 111.954 1398.2 111.954C1333.53 111.954 1289.77 149.185 1272.13 209.932V120.445Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M1643.05 456.833C1762.59 456.833 1846.85 393.475 1846.85 283.088C1846.85 173.353 1762.59 110.648 1643.05 110.648C1522.87 110.648 1438.61 173.353 1438.61 283.088C1438.61 393.475 1522.87 456.833 1643.05 456.833ZM1643.05 381.717C1588.19 381.717 1553.57 346.446 1553.57 283.088C1553.57 219.728 1588.19 185.763 1643.05 185.763C1697.27 185.763 1731.89 219.728 1731.89 283.088C1731.89 346.446 1697.27 381.717 1643.05 381.717Z\"\n fill=\"currentColor\"\n />\n</svg>\n";
const SPRITESHEET_NAMESPACE = `astroicon`;
const baseURL = ({}).ASTRO_ICON_API ?? "https://api.iconify.design/";
const requests = /* @__PURE__ */ new Map();
const fetchCache = /* @__PURE__ */ new Map();
async function get(pack, name) {
const url = new URL(`./${pack}.json?icons=${name}`, baseURL).toString();
if (requests.has(url)) {
return await requests.get(url);
}
if (fetchCache.has(url)) {
return fetchCache.get(url);
}
let request = async () => {
const res = await fetch(url);
if (!res.ok) {
throw new Error(await res.text());
}
const svg = new IconSet(await res.json()).toString(name);
fetchCache.set(url, svg);
requests.delete(url);
return svg;
};
let promise = request();
requests.set(url, promise);
return await promise;
}
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
var svgo = {};
var parser$4 = {};
var _collections = {};
(function (exports) {
// https://www.w3.org/TR/SVG11/intro.html#Definitions
/**
* @type {Record<string, Array<string>>}
*/
exports.elemsGroups = {
animation: [
'animate',
'animateColor',
'animateMotion',
'animateTransform',
'set',
],
descriptive: ['desc', 'metadata', 'title'],
shape: ['circle', 'ellipse', 'line', 'path', 'polygon', 'polyline', 'rect'],
structural: ['defs', 'g', 'svg', 'symbol', 'use'],
paintServer: [
'solidColor',
'linearGradient',
'radialGradient',
'meshGradient',
'pattern',
'hatch',
],
nonRendering: [
'linearGradient',
'radialGradient',
'pattern',
'clipPath',
'mask',
'marker',
'symbol',
'filter',
'solidColor',
],
container: [
'a',
'defs',
'g',
'marker',
'mask',
'missing-glyph',
'pattern',
'svg',
'switch',
'symbol',
'foreignObject',
],
textContent: [
'altGlyph',
'altGlyphDef',
'altGlyphItem',
'glyph',
'glyphRef',
'textPath',
'text',
'tref',
'tspan',
],
textContentChild: ['altGlyph', 'textPath', 'tref', 'tspan'],
lightSource: [
'feDiffuseLighting',
'feSpecularLighting',
'feDistantLight',
'fePointLight',
'feSpotLight',
],
filterPrimitive: [
'feBlend',
'feColorMatrix',
'feComponentTransfer',
'feComposite',
'feConvolveMatrix',
'feDiffuseLighting',
'feDisplacementMap',
'feDropShadow',
'feFlood',
'feFuncA',
'feFuncB',
'feFuncG',
'feFuncR',
'feGaussianBlur',
'feImage',
'feMerge',
'feMergeNode',
'feMorphology',
'feOffset',
'feSpecularLighting',
'feTile',
'feTurbulence',
],
};
exports.textElems = exports.elemsGroups.textContent.concat('title');
exports.pathElems = ['path', 'glyph', 'missing-glyph'];
// https://www.w3.org/TR/SVG11/intro.html#Definitions
/**
* @type {Record<string, Array<string>>}
*/
exports.attrsGroups = {
animationAddition: ['additive', 'accumulate'],
animationAttributeTarget: ['attributeType', 'attributeName'],
animationEvent: ['onbegin', 'onend', 'onrepeat', 'onload'],
animationTiming: [
'begin',
'dur',
'end',
'min',
'max',
'restart',
'repeatCount',
'repeatDur',
'fill',
],
animationValue: [
'calcMode',
'values',
'keyTimes',
'keySplines',
'from',
'to',
'by',
],
conditionalProcessing: [
'requiredFeatures',
'requiredExtensions',
'systemLanguage',
],
core: ['id', 'tabindex', 'xml:base', 'xml:lang', 'xml:space'],
graphicalEvent: [
'onfocusin',
'onfocusout',
'onactivate',
'onclick',
'onmousedown',
'onmouseup',
'onmouseover',
'onmousemove',
'onmouseout',
'onload',
],
presentation: [
'alignment-baseline',
'baseline-shift',
'clip',
'clip-path',
'clip-rule',
'color',
'color-interpolation',
'color-interpolation-filters',
'color-profile',
'color-rendering',
'cursor',
'direction',
'display',
'dominant-baseline',
'enable-background',
'fill',
'fill-opacity',
'fill-rule',
'filter',
'flood-color',
'flood-opacity',
'font-family',
'font-size',
'font-size-adjust',
'font-stretch',
'font-style',
'font-variant',
'font-weight',
'glyph-orientation-horizontal',
'glyph-orientation-vertical',
'image-rendering',
'letter-spacing',
'lighting-color',
'marker-end',
'marker-mid',
'marker-start',
'mask',
'opacity',
'overflow',
'paint-order',
'pointer-events',
'shape-rendering',
'stop-color',
'stop-opacity',
'stroke',
'stroke-dasharray',
'stroke-dashoffset',
'stroke-linecap',
'stroke-linejoin',
'stroke-miterlimit',
'stroke-opacity',
'stroke-width',
'text-anchor',
'text-decoration',
'text-overflow',
'text-rendering',
'transform',
'transform-origin',
'unicode-bidi',
'vector-effect',
'visibility',
'word-spacing',
'writing-mode',
],
xlink: [
'xlink:href',
'xlink:show',
'xlink:actuate',
'xlink:type',
'xlink:role',
'xlink:arcrole',
'xlink:title',
],
documentEvent: [
'onunload',
'onabort',
'onerror',
'onresize',
'onscroll',
'onzoom',
],
filterPrimitive: ['x', 'y', 'width', 'height', 'result'],
transferFunction: [
'type',
'tableValues',
'slope',
'intercept',
'amplitude',
'exponent',
'offset',
],
};
/**
* @type {Record<string, Record<string, string>>}
*/
exports.attrsGroupsDefaults = {
core: { 'xml:space': 'default' },
presentation: {
clip: 'auto',
'clip-path': 'none',
'clip-rule': 'nonzero',
mask: 'none',
opacity: '1',
'stop-color': '#000',
'stop-opacity': '1',
'fill-opacity': '1',
'fill-rule': 'nonzero',
fill: '#000',
stroke: 'none',
'stroke-width': '1',
'stroke-linecap': 'butt',
'stroke-linejoin': 'miter',
'stroke-miterlimit': '4',
'stroke-dasharray': 'none',
'stroke-dashoffset': '0',
'stroke-opacity': '1',
'paint-order': 'normal',
'vector-effect': 'none',
display: 'inline',
visibility: 'visible',
'marker-start': 'none',
'marker-mid': 'none',
'marker-end': 'none',
'color-interpolation': 'sRGB',
'color-interpolation-filters': 'linearRGB',
'color-rendering': 'auto',
'shape-rendering': 'auto',
'text-rendering': 'auto',
'image-rendering': 'auto',
'font-style': 'normal',
'font-variant': 'normal',
'font-weight': 'normal',
'font-stretch': 'normal',
'font-size': 'medium',
'font-size-adjust': 'none',
kerning: 'auto',
'letter-spacing': 'normal',
'word-spacing': 'normal',
'text-decoration': 'none',
'text-anchor': 'start',
'text-overflow': 'clip',
'writing-mode': 'lr-tb',
'glyph-orientation-vertical': 'auto',
'glyph-orientation-horizontal': '0deg',
direction: 'ltr',
'unicode-bidi': 'normal',
'dominant-baseline': 'auto',
'alignment-baseline': 'baseline',
'baseline-shift': 'baseline',
},
transferFunction: {
slope: '1',
intercept: '0',
amplitude: '1',
exponent: '1',
offset: '0',
},
};
// https://www.w3.org/TR/SVG11/eltindex.html
/**
* @type {Record<string, {
* attrsGroups: Array<string>,
* attrs?: Array<string>,
* defaults?: Record<string, string>,
* contentGroups?: Array<string>,
* content?: Array<string>,
* }>}
*/
exports.elems = {
a: {
attrsGroups: [
'conditionalProcessing',
'core',
'graphicalEvent',
'presentation',
'xlink',
],
attrs: [
'class',
'style',
'externalResourcesRequired',
'transform',
'target',
],
defaults: {
target: '_self',
},
contentGroups: [
'animation',
'descriptive',
'shape',
'structural',
'paintServer',
],
content: [
'a',
'altGlyphDef',
'clipPath',
'color-profile',
'cursor',
'filter',
'font',
'font-face',
'foreignObject',
'image',
'marker',
'mask',
'pattern',
'script',
'style',
'switch',
'text',
'view',
// not spec compliant
'tspan',
],
},
altGlyph: {
attrsGroups: [
'conditionalProcessing',
'core',
'graphicalEvent',
'presentation',
'xlink',
],
attrs: [
'class',
'style',
'externalResourcesRequired',
'x',
'y',
'dx',
'dy',
'glyphRef',
'format',
'rotate',
],
},
altGlyphDef: {
attrsGroups: ['core'],
content: ['glyphRef'],
},
altGlyphItem: {
attrsGroups: ['core'],
content: ['glyphRef', 'altGlyphItem'],
},
animate: {
attrsGroups: [
'conditionalProcessing',
'core',
'animationAddition',
'animationAttributeTarget',
'animationEvent',
'animationTiming',
'animationValue',
'presentation',
'xlink',
],
attrs: ['externalResourcesRequired'],
contentGroups: ['descriptive'],
},
animateColor: {
attrsGroups: [
'conditionalProcessing',
'core',
'animationEvent',
'xlink',
'animationAttributeTarget',
'animationTiming',
'animationValue',
'animationAddition',
'presentation',
],
attrs: ['externalResourcesRequired'],
contentGroups: ['descriptive'],
},
animateMotion: {
attrsGroups: [
'conditionalProcessing',
'core',
'animationEvent',
'xlink',
'animationTiming',
'animationValue',
'animationAddition',
],
attrs: [
'externalResourcesRequired',
'path',
'keyPoints',
'rotate',
'origin',
],
defaults: {
rotate: '0',
},
contentGroups: ['descriptive'],
content: ['mpath'],
},
animateTransform: {
attrsGroups: [
'conditionalProcessing',
'core',
'animationEvent',
'xlink',
'animationAttributeTarget',
'animationTiming',
'animationValue',
'animationAddition',
],
attrs: ['externalResourcesRequired', 'type'],
contentGroups: ['descriptive'],
},
circle: {
attrsGroups: [
'conditionalProcessing',
'core',
'graphicalEvent',
'presentation',
],
attrs: [
'class',
'style',
'externalResourcesRequired',
'transform',
'cx',
'cy',
'r',
],
defaults: {
cx: '0',
cy: '0',
},
contentGroups: ['animation', 'descriptive'],
},
clipPath: {
attrsGroups: ['conditionalProcessing', 'core', 'presentation'],
attrs: [
'class',
'style',
'externalResourcesRequired',
'transform',
'clipPathUnits',
],
defaults: {
clipPathUnits: 'userSpaceOnUse',
},
contentGroups: ['animation', 'descriptive', 'shape'],
content: ['text', 'use'],
},
'color-profile': {
attrsGroups: ['core', 'xlink'],
attrs: ['local', 'name', 'rendering-intent'],
defaults: {
name: 'sRGB',
'rendering-intent': 'auto',
},
contentGroups: ['descriptive'],
},
cursor: {
attrsGroups: ['core', 'conditionalProcessing', 'xlink'],
attrs: ['externalResourcesRequired', 'x', 'y'],
defaults: {
x: '0',
y: '0',
},
contentGroups: ['descriptive'],
},
defs: {
attrsGroups: [
'conditionalProcessing',
'core',
'graphicalEvent',
'presentation',
],
attrs: ['class', 'style', 'externalResourcesRequired', 'transform'],
contentGroups: [
'animation',
'descriptive',
'shape',
'structural',
'paintServer',
],
content: [
'a',
'altGlyphDef',
'clipPath',
'color-profile',
'cursor',
'filter',
'font',
'font-face',
'foreignObject',
'image',
'marker',
'mask',
'pattern',
'script',
'style',
'switch',
'text',
'view',
],
},
desc: {
attrsGroups: ['core'],
attrs: ['class', 'style'],
},
ellipse: {
attrsGroups: [
'conditionalProcessing',
'core',
'graphicalEvent',
'presentation',
],
attrs: [
'class',
'style',
'externalResourcesRequired',
'transform',
'cx',
'cy',
'rx',
'ry',
],
defaults: {
cx: '0',
cy: '0',
},
contentGroups: ['animation', 'descriptive'],
},
feBlend: {
attrsGroups: ['core', 'presentation', 'filterPrimitive'],
attrs: [
'class',
'style',
// TODO: in - 'If no value is provided and this is the first filter primitive,
// then this filter primitive will use SourceGraphic as its input'
'in',
'in2',
'mode',
],
defaults: {
mode: 'normal',
},
content: ['animate', 'set'],
},
feColorMatrix: {
attrsGroups: ['core', 'presentation', 'filterPrimitive'],
attrs: ['class', 'style', 'in', 'type', 'values'],
defaults: {
type: 'matrix',
},
content: ['animate', 'set'],
},
feComponentTransfer: {
attrsGroups: ['core', 'presentation', 'filterPrimitive'],
attrs: ['class', 'style', 'in'],
content: ['feFuncA', 'feFuncB', 'feFuncG', 'feFuncR'],
},
feComposite: {
attrsGroups: ['core', 'presentation', 'filterPrimitive'],
attrs: ['class', 'style', 'in', 'in2', 'operator', 'k1', 'k2', 'k3', 'k4'],
defaults: {
operator: 'over',
k1: '0',
k2: '0',
k3: '0',
k4: '0',
},
content: ['animate', 'set'],
},
feConvolveMatrix: {
attrsGroups: ['core', 'presentation', 'filterPrimitive'],
attrs: [
'class',
'style',
'in',
'order',
'kernelMatrix',
// TODO: divisor - 'The default value is the sum of all values in kernelMatrix,
// with the exception that if the sum is zero, then the divisor is set to 1'
'divisor',
'bias',
// TODO: targetX - 'By default, the convolution matrix is centered in X over each
// pixel of the input image (i.e., targetX = floor ( orderX / 2 ))'
'targetX',
'targetY',
'edgeMode',
// TODO: kernelUnitLength - 'The first number is the <dx> value. The second number
// is the <dy> value. If the <dy> value is not specified, it defaults to the same value as <dx>'
'kernelUnitLength',
'preserveAlpha',
],
defaults: {
order: '3',
bias: '0',
edgeMode: 'duplicate',
preserveAlpha: 'false',
},
content: ['animate', 'set'],
},
feDiffuseLighting: {
attrsGroups: ['core', 'presentation', 'filterPrimitive'],
attrs: [
'class',
'style',
'in',
'surfaceScale',
'diffuseConstant',
'kernelUnitLength',
],
defaults: {
surfaceScale: '1',
diffuseConstant: '1',
},
contentGroups: ['descriptive'],
content: [
// TODO: 'exactly one light source element, in any order'
'feDistantLight',
'fePointLight',
'feSpotLight',
],
},
feDisplacementMap: {
attrsGroups: ['core', 'presentation', 'filterPrimitive'],
attrs: [
'class',
'style',
'in',
'in2',
'scale',
'xChannelSelector',
'yChannelSelector',
],
defaults: {
scale: '0',
xChannelSelector: 'A',
yChannelSelector: 'A',
},
content: ['animate', 'set'],
},
feDistantLight: {
attrsGroups: ['core'],
attrs: ['azimuth', 'elevation'],
defaults: {
azimuth: '0',
elevation: '0',
},
content: ['animate', 'set'],
},
feFlood: {
attrsGroups: ['core', 'presentation', 'filterPrimitive'],
attrs: ['class', 'style'],
content: ['animate', 'animateColor', 'set'],
},
feFuncA: {
attrsGroups: ['core', 'transferFunction'],
content: ['set', 'animate'],
},
feFuncB: {
attrsGroups: ['core', 'transferFunction'],
content: ['set', 'animate'],
},
feFuncG: {
attrsGroups: ['core', 'transferFunction'],
content: ['set', 'animate'],
},
feFuncR: {
attrsGroups: ['core', 'transferFunction'],
content: ['set', 'animate'],
},
feGaussianBlur: {
attrsGroups: ['core', 'presentation', 'filterPrimitive'],
attrs: ['class', 'style', 'in', 'stdDeviation'],
defaults: {
stdDeviation: '0',
},
content: ['set', 'animate'],
},
feImage: {
attrsGroups: ['core', 'presentation', 'filterPrimitive', 'xlink'],
attrs: [
'class',
'style',
'externalResourcesRequired',
'preserveAspectRatio',
'href',
'xlink:href',
],
defaults: {
preserveAspectRatio: 'xMidYMid meet',
},
content: ['animate', 'animateTransform', 'set'],
},
feMerge: {
attrsGroups: ['core', 'presentation', 'filterPrimitive'],
attrs: ['class', 'style'],
content: ['feMergeNode'],
},
feMergeNode: {
attrsGroups: ['core'],
attrs: ['in'],
content: ['animate', 'set'],
},
feMorphology: {
attrsGroups: ['core', 'presentation', 'filterPrimitive'],
attrs: ['class', 'style', 'in', 'operator', 'radius'],
defaults: {
operator: 'erode',
radius: '0',
},
content: ['animate', 'set'],
},
feOffset: {
attrsGroups: ['core', 'presentation', 'filterPrimitive'],
attrs: ['class', 'style', 'in', 'dx', 'dy'],
defaults: {
dx: '0',
dy: '0',
},
content: ['animate', 'set'],
},
fePointLight: {
attrsGroups: ['core'],
attrs: ['x', 'y', 'z'],
defaults: {
x: '0',
y: '0',
z: '0',
},
content: ['animate', 'set'],
},
feSpecularLighting: {
attrsGroups: ['core', 'presentation', 'filterPrimitive'],
attrs: [
'class',
'style',
'in',
'surfaceScale',
'specularConstant',
'specularExponent',
'kernelUnitLength',
],
defaults: {
surfaceScale: '1',
specularConstant: '1',
specularExponent: '1',
},
contentGroups: [
'descriptive',
// TODO: exactly one 'light source element'
'lightSource',
],
},
feSpotLight: {
attrsGroups: ['core'],
attrs: [
'x',
'y',
'z',
'pointsAtX',
'pointsAtY',
'pointsAtZ',
'specularExponent',
'limitingConeAngle',
],
defaults: {
x: '0',
y: '0',
z: '0',
pointsAtX: '0',
pointsAtY: '0',
pointsAtZ: '0',
specularExponent: '1',
},
content: ['animate', 'set'],
},
feTile: {
attrsGroups: ['core', 'presentation', 'filterPrimitive'],
attrs: ['class', 'style', 'in'],
content: ['animate', 'set'],
},
feTurbulence: {
attrsGroups: ['core', 'presentation', 'filterPrimitive'],
attrs: [
'class',
'style',
'baseFrequency',
'numOctaves',
'seed',
'stitchTiles',
'type',
],
defaults: {
baseFrequency: '0',
numOctaves: '1',
seed: '0',
stitchTiles: 'noStitch',
type: 'turbulence',
},
content: ['animate', 'set'],
},
filter: {
attrsGroups: ['core', 'presentation', 'xlink'],
attrs: [
'class',
'style',
'externalResourcesRequired',
'x',
'y',
'width',
'height',
'filterRes',
'filterUnits',
'primitiveUnits',
'href',
'xlink:href',
],
defaults: {
primitiveUnits: 'userSpaceOnUse',
x: '-10%',
y: '-10%',
width: '120%',
height: '120%',
},
contentGroups: ['descriptive', 'filterPrimitive'],
content: ['animate', 'set'],
},
font: {
attrsGroups: ['core', 'presentation'],
attrs: [
'class',
'style',
'externalResourcesRequired',
'horiz-origin-x',
'horiz-origin-y',
'horiz-adv-x',
'vert-origin-x',
'vert-origin-y',
'vert-adv-y',
],
defaults: {
'horiz-origin-x': '0',
'horiz-origin-y': '0',
},
contentGroups: ['descriptive'],
content: ['font-face', 'glyph', 'hkern', 'missing-glyph', 'vkern'],
},
'font-face': {
attrsGroups: ['core'],
attrs: [
'font-family',
'font-style',
'font-variant',
'font-weight',
'font-stretch',
'font-size',
'unicode-range',
'units-per-em',
'panose-1',
'stemv',
'stemh',
'slope',
'cap-height',
'x-height',
'accent-height',
'ascent',
'descent',
'widths',
'bbox',
'ideographic',
'alphabetic',
'mathematical',
'hanging',
'v-ideographic',
'v-alphabetic',
'v-mathematical',
'v-hanging',
'underline-position',
'underline-thickness',
'strikethrough-position',
'strikethrough-thickness',
'overline-position',
'overline-thickness',
],
defaults: {
'font-style': 'all',
'font-variant': 'normal',
'font-weight': 'all',
'font-stretch': 'normal',
'unicode-range': 'U+0-10FFFF',
'units-per-em': '1000',
'panose-1': '0 0 0 0 0 0 0 0 0 0',
slope: '0',
},
contentGroups: ['descriptive'],
content: [
// TODO: "at most one 'font-face-src' element"
'font-face-src',
],
},
// TODO: empty content
'font-face-format': {
attrsGroups: ['core'],
attrs: ['string'],
},
'font-face-name': {
attrsGroups: ['core'],
attrs: ['name'],
},
'font-face-src': {
attrsGroups: ['core'],
content: ['font-face-name', 'font-face-uri'],
},
'font-face-uri': {
attrsGroups: ['core', 'xlink'],
attrs: ['href', 'xlink:href'],
content: ['font-face-format'],
},
foreignObject: {
attrsGroups: [
'core',
'conditionalProcessing',
'graphicalEvent',
'presentation',
],
attrs: [
'class',
'style',
'externalResourcesRequired',
'transform',
'x',
'y',
'width',
'height',
],
defaults: {
x: '0',
y: '0',
},
},
g: {
attrsGroups: [
'conditionalProcessing',
'core',
'graphicalEvent',
'presentation',
],
attrs: ['class', 'style', 'externalResourcesRequired', 'transform'],
contentGroups: [
'animation',
'descriptive',
'shape',
'structural',
'paintServer',
],
content: [
'a',
'altGlyphDef',
'clipPath',
'color-profile',
'cursor',
'filter',
'font',
'font-face',
'foreignObject',
'image',
'marker',
'mask',
'pattern',
'script',
'style',
'switch',
'text',
'view',
],
},
glyph: {
attrsGroups: ['core', 'presentation'],
attrs: [
'class',
'style',
'd',
'horiz-adv-x',
'vert-origin-x',
'vert-origin-y',
'vert-adv-y',
'unicode',
'glyph-name',
'orientation',
'arabic-form',
'lang',
],
defaults: {
'arabic-form': 'initial',
},
contentGroups: [
'animation',
'descriptive',
'shape',
'structural',
'paintServer',
],
content: [
'a',
'altGlyphDef',
'clipPath',
'color-profile',
'cursor',
'filter',
'font',
'font-face',
'foreignObject',
'image',
'marker',
'mask',
'pattern',
'script',
'style',
'switch',
'text',
'view',
],
},
glyphRef: {
attrsGroups: ['core', 'presentation'],
attrs: [
'class',
'style',
'd',
'horiz-adv-x',
'vert-origin-x',
'vert-origin-y',
'vert-adv-y',
],
contentGroups: [
'animation',
'descriptive',
'shape',
'structural',
'paintServer',
],
content: [
'a',
'altGlyphDef',
'clipPath',
'color-profile',
'cursor',
'filter',
'font',
'font-face',
'foreignObject',
'image',
'marker',
'mask',
'pattern',
'script',
'style',
'switch',
'text',
'view',
],
},
hatch: {
attrsGroups: ['core', 'presentation', 'xlink'],
attrs: [
'class',
'style',
'x',
'y',
'pitch',
'rotate',
'hatchUnits',
'hatchContentUnits',
'transform',
],
defaults: {
hatchUnits: 'objectBoundingBox',
hatchContentUnits: 'userSpaceOnUse',
x: '0',
y: '0',
pitch: '0',
rotate: '0',
},
contentGroups: ['animation', 'descriptive'],
content: ['hatchPath'],
},
hatchPath: {
attrsGroups: ['core', 'presentation', 'xlink'],
attrs: ['class', 'style', 'd', 'offset'],
defaults: {
offset: '0',
},
contentGroups: ['animation', 'descriptive'],
},
hkern: {
attrsGroups: ['core'],
attrs: ['u1', 'g1', 'u2', 'g2', 'k'],
},
image: {
attrsGroups: [
'core',
'conditionalProcessing',
'graphicalEvent',
'xlink',
'presentation',
],
attrs: [
'class',
'style',
'externalResourcesRequired',
'preserveAspectRatio',
'transform',
'x',
'y',
'width',
'height',
'href',
'xlink:href',
],
defaults: {
x: '0',
y: '0',
preserveAspectRatio: 'xMidYMid meet',
},
contentGroups: ['animation', 'descriptive'],
},
line: {
attrsGroups: [
'conditionalProcessing',
'core',
'graphicalEvent',
'presentation',
],
attrs: [
'class',
'style',
'externalResourcesRequired',
'transform',
'x1',
'y1',
'x2',
'y2',
],
defaults: {
x1: '0',
y1: '0',
x2: '0',
y2: '0',
},
contentGroups: ['animation', 'descriptive'],
},
linearGradient: {
attrsGroups: ['core', 'presentation', 'xlink'],
attrs: [
'class',
'style',
'externalResourcesRequired',
'x1',
'y1',
'x2',
'y2',
'gradientUnits',
'gradientTransform',
'spreadMethod',
'href',
'xlink:href',
],
defaults: {
x1: '0',
y1: '0',
x2: '100%',
y2: '0',
spreadMethod: 'pad',
},
contentGroups: ['descriptive'],
content: ['animate', 'animateTransform', 'set', 'stop'],
},
marker: {
attrsGroups: ['core', 'presentation'],
attrs: [
'class',
'style',
'externalResourcesRequired',
'viewBox',
'preserveAspectRatio',
'refX',
'refY',
'markerUnits',
'markerWidth',
'markerHeight',
'orient',
],
defaults: {
markerUnits: 'strokeWidth',
refX: '0',
refY: '0',
markerWidth: '3',
markerHeight: '3',
},
contentGroups: [
'animation',
'descriptive',
'shape',
'structural',
'paintServer',
],
content: [
'a',
'altGlyphDef',
'clipPath',
'color-profile',
'cursor',
'filter',
'font',
'font-face',
'foreignObject',
'image',
'marker',
'mask',
'pattern',
'script',
'style',
'switch',
'text',
'view',
],
},
mask: {
attrsGroups: ['conditionalProcessing', 'core', 'presentation'],
attrs: [
'class',
'style',
'externalResourcesRequired',
'x',
'y',
'width',
'height',
'mask-type',
'maskUnits',
'maskContentUnits',
],
defaults: {
maskUnits: 'objectBoundingBox',
maskContentUnits: 'userSpaceOnUse',
x: '-10%',
y: '-10%',
width: '120%',
height: '120%',
},
contentGroups: [
'animation',
'descriptive',
'shape',
'structural',
'paintServer',
],
content: [
'a',
'altGlyphDef',
'clipPath',
'color-profile',
'cursor',
'filter',
'font',
'font-face',
'foreignObject',
'image',
'marker',
'mask',
'pattern',
'script',
'style',
'switch',
'text',
'view',
],
},
metadata: {
attrsGroups: ['core'],
},
'missing-glyph': {
attrsGroups: ['core', 'presentation'],
attrs: [
'class',
'style',
'd',
'horiz-adv-x',
'vert-origin-x',
'vert-origin-y',
'vert-adv-y',
],
contentGroups: [
'animation',
'descriptive',
'shape',
'structural',
'paintServer',
],
content: [
'a',
'altGlyphDef',
'clipPath',
'color-profile',
'cursor',
'filter',
'font',
'font-face',
'foreignObject',
'image',
'marker',
'mask',
'pattern',
'script',
'style',
'switch',
'text',
'view',
],
},
mpath: {
attrsGroups: ['core', 'xlink'],
attrs: ['externalResourcesRequired', 'href', 'xlink:href'],
contentGroups: ['descriptive'],
},
path: {
attrsGroups: [
'conditionalProcessing',
'core',
'graphicalEvent',
'presentation',
],
attrs: [
'class',
'style',
'externalResourcesRequired',
'transform',
'd',
'pathLength',
],
contentGroups: ['animation', 'descriptive'],
},
pattern: {
attrsGroups: ['conditionalProcessing', 'core', 'presentation', 'xlink'],
attrs: [
'class',
'style',
'externalResourcesRequired',
'viewBox',
'preserveAspectRatio',
'x',
'y',
'width',
'height',
'patternUnits',
'patternContentUnits',
'patternTransform',
'href',
'xlink:href',
],
defaults: {
patternUnits: 'objectBoundingBox',
patternContentUnits: 'userSpaceOnUse',
x: '0',
y: '0',
width: '0',
height: '0',
preserveAspectRatio: 'xMidYMid meet',
},
contentGroups: [
'animation',
'descriptive',
'paintServer',
'shape',
'structural',
],
content: [
'a',
'altGlyphDef',
'clipPath',
'color-profile',
'cursor',
'filter',
'font',
'font-face',
'foreignObject',
'image',
'marker',
'mask',
'pattern',
'script',
'style',
'switch',
'text',
'view',
],
},
polygon: {
attrsGroups: [
'conditionalProcessing',
'core',
'graphicalEvent',
'presentation',
],
attrs: [
'class',
'style',
'externalResourcesRequired',
'transform',
'points',
],
contentGroups: ['animation', 'descriptive'],
},
polyline: {
attrsGroups: [
'conditionalProcessing',
'core',
'graphicalEvent',
'presentation',
],
attrs: [
'class',
'style',
'externalResourcesRequired',
'transform',
'points',
],
contentGroups: ['animation', 'descriptive'],
},
radialGradient: {
attrsGroups: ['core', 'presentation', 'xlink'],
attrs: [
'class',
'style',
'externalResourcesRequired',
'cx',
'cy',
'r',
'fx',
'fy',
'fr',
'gradientUnits',
'gradientTransform',
'spreadMethod',
'href',
'xlink:href',
],
defaults: {
gradientUnits: 'objectBoundingBox',
cx: '50%',
cy: '50%',
r: '50%',
},
contentGroups: ['descriptive'],
content: ['animate', 'animateTransform', 'set', 'stop'],
},
meshGradient: {
attrsGroups: ['core', 'presentation', 'xlink'],
attrs: ['class', 'style', 'x', 'y', 'gradientUnits', 'transform'],
contentGroups: ['descriptive', 'paintServer', 'animation'],
content: ['meshRow'],
},
meshRow: {
attrsGroups: ['core', 'presentation'],
attrs: ['class', 'style'],
contentGroups: ['descriptive'],
content: ['meshPatch'],
},
meshPatch: {
attrsGroups: ['core', 'presentation'],
attrs: ['class', 'style'],
contentGroups: ['descriptive'],
content: ['stop'],
},
rect: {
attrsGroups: [
'conditionalProcessing',
'core',
'graphicalEvent',
'presentation',
],
attrs: [
'class',
'style',
'externalResourcesRequired',
'transform',
'x',
'y',
'width',
'height',
'rx',
'ry',
],
defaults: {
x: '0',
y: '0',
},
contentGroups: ['animation', 'descriptive'],
},
script: {
attrsGroups: ['core', 'xlink'],
attrs: ['externalResourcesRequired', 'type', 'href', 'xlink:href'],
},
set: {
attrsGroups: [
'conditionalProcessing',
'core',
'animation',
'xlink',
'animationAttributeTarget',
'animationTiming',
],
attrs: ['externalResourcesRequired', 'to'],
contentGroups: ['descriptive'],
},
solidColor: {
attrsGroups: ['core', 'presentation'],
attrs: ['class', 'style'],
contentGroups: ['paintServer'],
},
stop: {
attrsGroups: ['core', 'presentation'],
attrs: ['class', 'style', 'offset', 'path'],
content: ['animate', 'animateColor', 'set'],
},
style: {
attrsGroups: ['core'],
attrs: ['type', 'media', 'title'],
defaults: {
type: 'text/css',
},
},
svg: {
attrsGroups: [
'conditionalProcessing',
'core',
'documentEvent',
'graphicalEvent',
'presentation',
],
attrs: [
'class',
'style',
'x',
'y',
'width',
'height',
'viewBox',
'preserveAspectRatio',
'zoomAndPan',
'version',
'baseProfile',
'contentScriptType',
'contentStyleType',
],
defaults: {
x: '0',
y: '0',
width: '100%',
height: '100%',
preserveAspectRatio: 'xMidYMid meet',
zoomAndPan: 'magnify',
version: '1.1',
baseProfile: 'none',
contentScriptType: 'application/ecmascript',
contentStyleType: 'text/css',
},
contentGroups: [
'animation',
'descriptive',
'shape',
'structural',
'paintServer',
],
content: [
'a',
'altGlyphDef',
'clipPath',
'color-profile',
'cursor',
'filter',
'font',
'font-face',
'foreignObject',
'image',
'marker',
'mask',
'pattern',
'script',
'style',
'switch',
'text',
'view',
],
},
switch: {
attrsGroups: [
'conditionalProcessing',
'core',
'graphicalEvent',
'presentation',
],
attrs: ['class', 'style', 'externalResourcesRequired', 'transform'],
contentGroups: ['animation', 'descriptive', 'shape'],
content: [
'a',
'foreignObject',
'g',
'image',
'svg',
'switch',
'text',
'use',
],
},
symbol: {
attrsGroups: ['core', 'graphicalEvent', 'presentation'],
attrs: [
'class',
'style',
'externalResourcesRequired',
'preserveAspectRatio',
'viewBox',
'refX',
'refY',
],
defaults: {
refX: '0',
refY: '0',
},
contentGroups: [
'animation',
'descriptive',
'shape',
'structural',
'paintServer',
],
content: [
'a',
'altGlyphDef',
'clipPath',
'color-profile',
'cursor',
'filter',
'font',
'font-face',
'foreignObject',
'image',
'marker',
'mask',
'pattern',
'script',
'style',
'switch',
'text',
'view',
],
},
text: {
attrsGroups: [
'conditionalProcessing',
'core',
'graphicalEvent',
'presentation',
],
attrs: [
'class',
'style',
'externalResourcesRequired',
'transform',
'lengthAdjust',
'x',
'y',
'dx',
'dy',
'rotate',
'textLength',
],
defaults: {
x: '0',
y: '0',
lengthAdjust: 'spacing',
},
contentGroups: ['animation', 'descriptive', 'textContentChild'],
content: ['a'],
},
textPath: {
attrsGroups: [
'conditionalProcessing',
'core',
'graphicalEvent',
'presentation',
'xlink',
],
attrs: [
'class',
'style',
'externalResourcesRequired',
'href',
'xlink:href',
'startOffset',
'method',
'spacing',
'd',
],
defaults: {
startOffset: '0',
method: 'align',
spacing: 'exact',
},
contentGroups: ['descriptive'],
content: [
'a',
'altGlyph',
'animate',
'animateColor',
'set',
'tref',
'tspan',
],
},
title: {
attrsGroups: ['core'],
attrs: ['class', 'style'],
},
tref: {
attrsGroups: [
'conditionalProcessing',
'core',
'graphicalEvent',
'presentation',
'xlink',
],
attrs: [
'class',
'style',
'externalResourcesRequired',
'href',
'xlink:href',
],
contentGroups: ['descriptive'],
content: ['animate', 'animateColor', 'set'],
},
tspan: {
attrsGroups: [
'conditionalProcessing',
'core',
'graphicalEvent',
'presentation',
],
attrs: [
'class',
'style',
'externalResourcesRequired',
'x',
'y',
'dx',
'dy',
'rotate',
'textLength',
'lengthAdjust',
],
contentGroups: ['descriptive'],
content: [
'a',
'altGlyph',
'animate',
'animateColor',
'set',
'tref',
'tspan',
],
},
use: {
attrsGroups: [
'core',
'conditionalProcessing',
'graphicalEvent',
'presentation',
'xlink',
],
attrs: [
'class',
'style',
'externalResourcesRequired',
'transform',
'x',
'y',
'width',
'height',
'href',
'xlink:href',
],
defaults: {
x: '0',
y: '0',
},
contentGroups: ['animation', 'descriptive'],
},
view: {
attrsGroups: ['core'],
attrs: [
'externalResourcesRequired',
'viewBox',
'preserveAspectRatio',
'zoomAndPan',
'viewTarget',
],
contentGroups: ['descriptive'],
},
vkern: {
attrsGroups: ['core'],
attrs: ['u1', 'g1', 'u2', 'g2', 'k'],
},
};
// https://wiki.inkscape.org/wiki/index.php/Inkscape-specific_XML_attributes
exports.editorNamespaces = [
'http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd',
'http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd',
'http://www.inkscape.org/namespaces/inkscape',
'http://www.bohemiancoding.com/sketch/ns',
'http://ns.adobe.com/AdobeIllustrator/10.0/',
'http://ns.adobe.com/Graphs/1.0/',
'http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/',
'http://ns.adobe.com/Variables/1.0/',
'http://ns.adobe.com/SaveForWeb/1.0/',
'http://ns.adobe.com/Extensibility/1.0/',
'http://ns.adobe.com/Flows/1.0/',
'http://ns.adobe.com/ImageReplacement/1.0/',
'http://ns.adobe.com/GenericCustomNamespace/1.0/',
'http://ns.adobe.com/XPath/1.0/',
'http://schemas.microsoft.com/visio/2003/SVGExtensions/',
'http://taptrix.com/vectorillustrator/svg_extensions',
'http://www.figma.com/figma/ns',
'http://purl.org/dc/elements/1.1/',
'http://creativecommons.org/ns#',
'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
'http://www.serif.com/',
'http://www.vector.evaxdesign.sk',
];
// https://www.w3.org/TR/SVG11/linking.html#processingIRI
exports.referencesProps = [
'clip-path',
'color-profile',
'fill',
'filter',
'marker-start',
'marker-mid',
'marker-end',
'mask',
'stroke',
'style',
];
// https://www.w3.org/TR/SVG11/propidx.html
exports.inheritableAttrs = [
'clip-rule',
'color',
'color-interpolation',
'color-interpolation-filters',
'color-profile',
'color-rendering',
'cursor',
'direction',
'dominant-baseline',
'fill',
'fill-opacity',
'fill-rule',
'font',
'font-family',
'font-size',
'font-size-adjust',
'font-stretch',
'font-style',
'font-variant',
'font-weight',
'glyph-orientation-horizontal',
'glyph-orientation-vertical',
'image-rendering',
'letter-spacing',
'marker',
'marker-end',
'marker-mid',
'marker-start',
'paint-order',
'pointer-events',
'shape-rendering',
'stroke',
'stroke-dasharray',
'stroke-dashoffset',
'stroke-linecap',
'stroke-linejoin',
'stroke-miterlimit',
'stroke-opacity',
'stroke-width',
'text-anchor',
'text-rendering',
'transform',
'visibility',
'word-spacing',
'writing-mode',
];
exports.presentationNonInheritableGroupAttrs = [
'display',
'clip-path',
'filter',
'mask',
'opacity',
'text-decoration',
'transform',
'unicode-bidi',
];
/**
* https://www.w3.org/TR/SVG11/single-page.html#types-ColorKeywords
*
* @type {Record<string, string>}
*/
exports.colorsNames = {
aliceblue: '#f0f8ff',
antiquewhite: '#faebd7',
aqua: '#0ff',
aquamarine: '#7fffd4',
azure: '#f0ffff',
beige: '#f5f5dc',
bisque: '#ffe4c4',
black: '#000',
blanchedalmond: '#ffebcd',
blue: '#00f',
blueviolet: '#8a2be2',
brown: '#a52a2a',
burlywood: '#deb887',
cadetblue: '#5f9ea0',
chartreuse: '#7fff00',
chocolate: '#d2691e',
coral: '#ff7f50',
cornflowerblue: '#6495ed',
cornsilk: '#fff8dc',
crimson: '#dc143c',
cyan: '#0ff',
darkblue: '#00008b',
darkcyan: '#008b8b',
darkgoldenrod: '#b8860b',
darkgray: '#a9a9a9',
darkgreen: '#006400',
darkgrey: '#a9a9a9',
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: '#f0f',
gainsboro: '#dcdcdc',
ghostwhite: '#f8f8ff',
gold: '#ffd700',
goldenrod: '#daa520',
gray: '#808080',
green: '#008000',
greenyellow: '#adff2f',
grey: '#808080',
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',
lightgreen: '#90ee90',
lightgrey: '#d3d3d3',
lightpink: '#ffb6c1',
lightsalmon: '#ffa07a',
lightseagreen: '#20b2aa',
lightskyblue: '#87cefa',
lightslategray: '#789',
lightslategrey: '#789',
lightsteelblue: '#b0c4de',
lightyellow: '#ffffe0',
lime: '#0f0',
limegreen: '#32cd32',
linen: '#faf0e6',
magenta: '#f0f',
maroon: '#800000',
mediumaquamarine: '#66cdaa',
mediumblue: '#0000cd',
mediumorchid: '#ba55d3',
mediumpurple: '#9370db',
mediumseagreen: '#3cb371',
mediumslateblue: '#7b68ee',
mediumspringgreen: '#00fa9a',
mediumturquoise: '#48d1cc',
mediumvioletred: '#c71585',
midnightblue: '#191970',
mintcream: '#f5fffa',
mistyrose: '#ffe4e1',
moccasin: '#ffe4b5',
navajowhite: '#ffdead',
navy: '#000080',
oldlace: '#fdf5e6',
olive: '#808000',
olivedrab: '#6b8e23',
orange: '#ffa500',
orangered: '#ff4500',
orchid: '#da70d6',
palegoldenrod: '#eee8aa',
palegreen: '#98fb98',
paleturquoise: '#afeeee',
palevioletred: '#db7093',
papayawhip: '#ffefd5',
peachpuff: '#ffdab9',
peru: '#cd853f',
pink: '#ffc0cb',
plum: '#dda0dd',
powderblue: '#b0e0e6',
purple: '#800080',
rebeccapurple: '#639',
red: '#f00',
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: '#fff',
whitesmoke: '#f5f5f5',
yellow: '#ff0',
yellowgreen: '#9acd32',
};
/**
* @type {Record<string, string>}
*/
exports.colorsShortNames = {
'#f0ffff': 'azure',
'#f5f5dc': 'beige',
'#ffe4c4': 'bisque',
'#a52a2a': 'brown',
'#ff7f50': 'coral',
'#ffd700': 'gold',
'#808080': 'gray',
'#008000': 'green',
'#4b0082': 'indigo',
'#fffff0': 'ivory',
'#f0e68c': 'khaki',
'#faf0e6': 'linen',
'#800000': 'maroon',
'#000080': 'navy',
'#808000': 'olive',
'#ffa500': 'orange',
'#da70d6': 'orchid',
'#cd853f': 'peru',
'#ffc0cb': 'pink',
'#dda0dd': 'plum',
'#800080': 'purple',
'#f00': 'red',
'#ff0000': 'red',
'#fa8072': 'salmon',
'#a0522d': 'sienna',
'#c0c0c0': 'silver',
'#fffafa': 'snow',
'#d2b48c': 'tan',
'#008080': 'teal',
'#ff6347': 'tomato',
'#ee82ee': 'violet',
'#f5deb3': 'wheat',
};
// https://www.w3.org/TR/SVG11/single-page.html#types-DataTypeColor
exports.colorsProps = [
'color',
'fill',
'stroke',
'stop-color',
'flood-color',
'lighting-color',
];
} (_collections));
/**
* @typedef {import('./types').XastNode} XastNode
* @typedef {import('./types').XastInstruction} XastInstruction
* @typedef {import('./types').XastDoctype} XastDoctype
* @typedef {import('./types').XastComment} XastComment
* @typedef {import('./types').XastRoot} XastRoot
* @typedef {import('./types').XastElement} XastElement
* @typedef {import('./types').XastCdata} XastCdata
* @typedef {import('./types').XastText} XastText
* @typedef {import('./types').XastParent} XastParent
* @typedef {import('./types').XastChild} XastChild
*/
// @ts-ignore sax will be replaced with something else later
const SAX = require$$0$5;
const { textElems: textElems$1 } = _collections;
class SvgoParserError extends Error {
/**
* @param message {string}
* @param line {number}
* @param column {number}
* @param source {string}
* @param file {void | string}
*/
constructor(message, line, column, source, file) {
super(message);
this.name = 'SvgoParserError';
this.message = `${file || '<input>'}:${line}:${column}: ${message}`;
this.reason = message;
this.line = line;
this.column = column;
this.source = source;
if (Error.captureStackTrace) {
Error.captureStackTrace(this, SvgoParserError);
}
}
toString() {
const lines = this.source.split(/\r?\n/);
const startLine = Math.max(this.line - 3, 0);
const endLine = Math.min(this.line + 2, lines.length);
const lineNumberWidth = String(endLine).length;
const startColumn = Math.max(this.column - 54, 0);
const endColumn = Math.max(this.column + 20, 80);
const code = lines
.slice(startLine, endLine)
.map((line, index) => {
const lineSlice = line.slice(startColumn, endColumn);
let ellipsisPrefix = '';
let ellipsisSuffix = '';
if (startColumn !== 0) {
ellipsisPrefix = startColumn > line.length - 1 ? ' ' : '…';
}
if (endColumn < line.length - 1) {
ellipsisSuffix = '…';
}
const number = startLine + 1 + index;
const gutter = ` ${number.toString().padStart(lineNumberWidth)} | `;
if (number === this.line) {
const gutterSpacing = gutter.replace(/[^|]/g, ' ');
const lineSpacing = (
ellipsisPrefix + line.slice(startColumn, this.column - 1)
).replace(/[^\t]/g, ' ');
const spacing = gutterSpacing + lineSpacing;
return `>${gutter}${ellipsisPrefix}${lineSlice}${ellipsisSuffix}\n ${spacing}^`;
}
return ` ${gutter}${ellipsisPrefix}${lineSlice}${ellipsisSuffix}`;
})
.join('\n');
return `${this.name}: ${this.message}\n\n${code}\n`;
}
}
const entityDeclaration = /<!ENTITY\s+(\S+)\s+(?:'([^']+)'|"([^"]+)")\s*>/g;
const config$4 = {
strict: true,
trim: false,
normalize: false,
lowercase: true,
xmlns: true,
position: true,
};
/**
* Convert SVG (XML) string to SVG-as-JS object.
*
* @type {(data: string, from?: string) => XastRoot}
*/
const parseSvg$1 = (data, from) => {
const sax = SAX.parser(config$4.strict, config$4);
/**
* @type {XastRoot}
*/
const root = { type: 'root', children: [] };
/**
* @type {XastParent}
*/
let current = root;
/**
* @type {Array<XastParent>}
*/
const stack = [root];
/**
* @type {(node: XastChild) => void}
*/
const pushToContent = (node) => {
// TODO remove legacy parentNode in v4
Object.defineProperty(node, 'parentNode', {
writable: true,
value: current,
});
current.children.push(node);
};
/**
* @type {(doctype: string) => void}
*/
sax.ondoctype = (doctype) => {
/**
* @type {XastDoctype}
*/
const node = {
type: 'doctype',
// TODO parse doctype for name, public and system to match xast
name: 'svg',
data: {
doctype,
},
};
pushToContent(node);
const subsetStart = doctype.indexOf('[');
if (subsetStart >= 0) {
entityDeclaration.lastIndex = subsetStart;
let entityMatch = entityDeclaration.exec(data);
while (entityMatch != null) {
sax.ENTITIES[entityMatch[1]] = entityMatch[2] || entityMatch[3];
entityMatch = entityDeclaration.exec(data);
}
}
};
/**
* @type {(data: { name: string, body: string }) => void}
*/
sax.onprocessinginstruction = (data) => {
/**
* @type {XastInstruction}
*/
const node = {
type: 'instruction',
name: data.name,
value: data.body,
};
pushToContent(node);
};
/**
* @type {(comment: string) => void}
*/
sax.oncomment = (comment) => {
/**
* @type {XastComment}
*/
const node = {
type: 'comment',
value: comment.trim(),
};
pushToContent(node);
};
/**
* @type {(cdata: string) => void}
*/
sax.oncdata = (cdata) => {
/**
* @type {XastCdata}
*/
const node = {
type: 'cdata',
value: cdata,
};
pushToContent(node);
};
/**
* @type {(data: { name: string, attributes: Record<string, { value: string }>}) => void}
*/
sax.onopentag = (data) => {
/**
* @type {XastElement}
*/
let element = {
type: 'element',
name: data.name,
attributes: {},
children: [],
};
for (const [name, attr] of Object.entries(data.attributes)) {
element.attributes[name] = attr.value;
}
pushToContent(element);
current = element;
stack.push(element);
};
/**
* @type {(text: string) => void}
*/
sax.ontext = (text) => {
if (current.type === 'element') {
// prevent trimming of meaningful whitespace inside textual tags
if (textElems$1.includes(current.name)) {
/**
* @type {XastText}
*/
const node = {
type: 'text',
value: text,
};
pushToContent(node);
} else if (/\S/.test(text)) {
/**
* @type {XastText}
*/
const node = {
type: 'text',
value: text.trim(),
};
pushToContent(node);
}
}
};
sax.onclosetag = () => {
stack.pop();
current = stack[stack.length - 1];
};
/**
* @type {(e: any) => void}
*/
sax.onerror = (e) => {
const error = new SvgoParserError(
e.reason,
e.line + 1,
e.column,
data,
from
);
if (e.message.indexOf('Unexpected end') === -1) {
throw error;
}
};
sax.write(data).close();
return root;
};
parser$4.parseSvg = parseSvg$1;
var stringifier = {};
/**
* @typedef {import('./types').XastParent} XastParent
* @typedef {import('./types').XastRoot} XastRoot
* @typedef {import('./types').XastElement} XastElement
* @typedef {import('./types').XastInstruction} XastInstruction
* @typedef {import('./types').XastDoctype} XastDoctype
* @typedef {import('./types').XastText} XastText
* @typedef {import('./types').XastCdata} XastCdata
* @typedef {import('./types').XastComment} XastComment
* @typedef {import('./types').StringifyOptions} StringifyOptions
*/
const { textElems } = _collections;
/**
* @typedef {{
* indent: string,
* textContext: null | XastElement,
* indentLevel: number,
* }} State
*/
/**
* @typedef {Required<StringifyOptions>} Options
*/
/**
* @type {(char: string) => string}
*/
const encodeEntity = (char) => {
return entities[char];
};
/**
* @type {Options}
*/
const defaults = {
doctypeStart: '<!DOCTYPE',
doctypeEnd: '>',
procInstStart: '<?',
procInstEnd: '?>',
tagOpenStart: '<',
tagOpenEnd: '>',
tagCloseStart: '</',
tagCloseEnd: '>',
tagShortStart: '<',
tagShortEnd: '/>',
attrStart: '="',
attrEnd: '"',
commentStart: '<!--',
commentEnd: '-->',
cdataStart: '<![CDATA[',
cdataEnd: ']]>',
textStart: '',
textEnd: '',
indent: 4,
regEntities: /[&'"<>]/g,
regValEntities: /[&"<>]/g,
encodeEntity: encodeEntity,
pretty: false,
useShortTags: true,
eol: 'lf',
finalNewline: false,
};
/**
* @type {Record<string, string>}
*/
const entities = {
'&': '&amp;',
"'": '&apos;',
'"': '&quot;',
'>': '&gt;',
'<': '&lt;',
};
/**
* convert XAST to SVG string
*
* @type {(data: XastRoot, config: StringifyOptions) => string}
*/
const stringifySvg$1 = (data, userOptions = {}) => {
/**
* @type {Options}
*/
const config = { ...defaults, ...userOptions };
const indent = config.indent;
let newIndent = ' ';
if (typeof indent === 'number' && Number.isNaN(indent) === false) {
newIndent = indent < 0 ? '\t' : ' '.repeat(indent);
} else if (typeof indent === 'string') {
newIndent = indent;
}
/**
* @type {State}
*/
const state = {
indent: newIndent,
textContext: null,
indentLevel: 0,
};
const eol = config.eol === 'crlf' ? '\r\n' : '\n';
if (config.pretty) {
config.doctypeEnd += eol;
config.procInstEnd += eol;
config.commentEnd += eol;
config.cdataEnd += eol;
config.tagShortEnd += eol;
config.tagOpenEnd += eol;
config.tagCloseEnd += eol;
config.textEnd += eol;
}
let svg = stringifyNode(data, config, state);
if (config.finalNewline && svg.length > 0 && svg[svg.length - 1] !== '\n') {
svg += eol;
}
return svg;
};
stringifier.stringifySvg = stringifySvg$1;
/**
* @type {(node: XastParent, config: Options, state: State) => string}
*/
const stringifyNode = (data, config, state) => {
let svg = '';
state.indentLevel += 1;
for (const item of data.children) {
if (item.type === 'element') {
svg += stringifyElement(item, config, state);
}
if (item.type === 'text') {
svg += stringifyText(item, config, state);
}
if (item.type === 'doctype') {
svg += stringifyDoctype(item, config);
}
if (item.type === 'instruction') {
svg += stringifyInstruction(item, config);
}
if (item.type === 'comment') {
svg += stringifyComment(item, config);
}
if (item.type === 'cdata') {
svg += stringifyCdata(item, config, state);
}
}
state.indentLevel -= 1;
return svg;
};
/**
* create indent string in accordance with the current node level.
*
* @type {(config: Options, state: State) => string}
*/
const createIndent = (config, state) => {
let indent = '';
if (config.pretty && state.textContext == null) {
indent = state.indent.repeat(state.indentLevel - 1);
}
return indent;
};
/**
* @type {(node: XastDoctype, config: Options) => string}
*/
const stringifyDoctype = (node, config) => {
return config.doctypeStart + node.data.doctype + config.doctypeEnd;
};
/**
* @type {(node: XastInstruction, config: Options) => string}
*/
const stringifyInstruction = (node, config) => {
return (
config.procInstStart + node.name + ' ' + node.value + config.procInstEnd
);
};
/**
* @type {(node: XastComment, config: Options) => string}
*/
const stringifyComment = (node, config) => {
return config.commentStart + node.value + config.commentEnd;
};
/**
* @type {(node: XastCdata, config: Options, state: State) => string}
*/
const stringifyCdata = (node, config, state) => {
return (
createIndent(config, state) +
config.cdataStart +
node.value +
config.cdataEnd
);
};
/**
* @type {(node: XastElement, config: Options, state: State) => string}
*/
const stringifyElement = (node, config, state) => {
// empty element and short tag
if (node.children.length === 0) {
if (config.useShortTags) {
return (
createIndent(config, state) +
config.tagShortStart +
node.name +
stringifyAttributes(node, config) +
config.tagShortEnd
);
} else {
return (
createIndent(config, state) +
config.tagShortStart +
node.name +
stringifyAttributes(node, config) +
config.tagOpenEnd +
config.tagCloseStart +
node.name +
config.tagCloseEnd
);
}
// non-empty element
} else {
let tagOpenStart = config.tagOpenStart;
let tagOpenEnd = config.tagOpenEnd;
let tagCloseStart = config.tagCloseStart;
let tagCloseEnd = config.tagCloseEnd;
let openIndent = createIndent(config, state);
let closeIndent = createIndent(config, state);
if (state.textContext) {
tagOpenStart = defaults.tagOpenStart;
tagOpenEnd = defaults.tagOpenEnd;
tagCloseStart = defaults.tagCloseStart;
tagCloseEnd = defaults.tagCloseEnd;
openIndent = '';
} else if (textElems.includes(node.name)) {
tagOpenEnd = defaults.tagOpenEnd;
tagCloseStart = defaults.tagCloseStart;
closeIndent = '';
state.textContext = node;
}
const children = stringifyNode(node, config, state);
if (state.textContext === node) {
state.textContext = null;
}
return (
openIndent +
tagOpenStart +
node.name +
stringifyAttributes(node, config) +
tagOpenEnd +
children +
closeIndent +
tagCloseStart +
node.name +
tagCloseEnd
);
}
};
/**
* @type {(node: XastElement, config: Options) => string}
*/
const stringifyAttributes = (node, config) => {
let attrs = '';
for (const [name, value] of Object.entries(node.attributes)) {
// TODO remove attributes without values support in v3
if (value !== undefined) {
const encodedValue = value
.toString()
.replace(config.regValEntities, config.encodeEntity);
attrs += ' ' + name + config.attrStart + encodedValue + config.attrEnd;
} else {
attrs += ' ' + name;
}
}
return attrs;
};
/**
* @type {(node: XastText, config: Options, state: State) => string}
*/
const stringifyText = (node, config, state) => {
return (
createIndent(config, state) +
config.textStart +
node.value.replace(config.regEntities, config.encodeEntity) +
(state.textContext ? '' : config.textEnd)
);
};
var builtin$1 = {};
var plugins = {};
var xast = {};
var lib$4 = {};
var lib$3 = {};
var stringify = {};
var lib$2 = {};
var node$2 = {};
var __extends = (commonjsGlobal && commonjsGlobal.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign$1 = (commonjsGlobal && commonjsGlobal.__assign) || function () {
__assign$1 = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign$1.apply(this, arguments);
};
Object.defineProperty(node$2, "__esModule", { value: true });
node$2.cloneNode = node$2.hasChildren = node$2.isDocument = node$2.isDirective = node$2.isComment = node$2.isText = node$2.isCDATA = node$2.isTag = node$2.Element = node$2.Document = node$2.CDATA = node$2.NodeWithChildren = node$2.ProcessingInstruction = node$2.Comment = node$2.Text = node$2.DataNode = node$2.Node = void 0;
var domelementtype_1$1 = require$$0$6;
/**
* This object will be used as the prototype for Nodes when creating a
* DOM-Level-1-compliant structure.
*/
var Node = /** @class */ (function () {
function Node() {
/** Parent of the node */
this.parent = null;
/** Previous sibling */
this.prev = null;
/** Next sibling */
this.next = null;
/** The start index of the node. Requires `withStartIndices` on the handler to be `true. */
this.startIndex = null;
/** The end index of the node. Requires `withEndIndices` on the handler to be `true. */
this.endIndex = null;
}
Object.defineProperty(Node.prototype, "parentNode", {
// Read-write aliases for properties
/**
* Same as {@link parent}.
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
*/
get: function () {
return this.parent;
},
set: function (parent) {
this.parent = parent;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Node.prototype, "previousSibling", {
/**
* Same as {@link prev}.
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
*/
get: function () {
return this.prev;
},
set: function (prev) {
this.prev = prev;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Node.prototype, "nextSibling", {
/**
* Same as {@link next}.
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
*/
get: function () {
return this.next;
},
set: function (next) {
this.next = next;
},
enumerable: false,
configurable: true
});
/**
* Clone this node, and optionally its children.
*
* @param recursive Clone child nodes as well.
* @returns A clone of the node.
*/
Node.prototype.cloneNode = function (recursive) {
if (recursive === void 0) { recursive = false; }
return cloneNode(this, recursive);
};
return Node;
}());
node$2.Node = Node;
/**
* A node that contains some data.
*/
var DataNode = /** @class */ (function (_super) {
__extends(DataNode, _super);
/**
* @param data The content of the data node
*/
function DataNode(data) {
var _this = _super.call(this) || this;
_this.data = data;
return _this;
}
Object.defineProperty(DataNode.prototype, "nodeValue", {
/**
* Same as {@link data}.
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
*/
get: function () {
return this.data;
},
set: function (data) {
this.data = data;
},
enumerable: false,
configurable: true
});
return DataNode;
}(Node));
node$2.DataNode = DataNode;
/**
* Text within the document.
*/
var Text = /** @class */ (function (_super) {
__extends(Text, _super);
function Text() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.type = domelementtype_1$1.ElementType.Text;
return _this;
}
Object.defineProperty(Text.prototype, "nodeType", {
get: function () {
return 3;
},
enumerable: false,
configurable: true
});
return Text;
}(DataNode));
node$2.Text = Text;
/**
* Comments within the document.
*/
var Comment$a = /** @class */ (function (_super) {
__extends(Comment, _super);
function Comment() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.type = domelementtype_1$1.ElementType.Comment;
return _this;
}
Object.defineProperty(Comment.prototype, "nodeType", {
get: function () {
return 8;
},
enumerable: false,
configurable: true
});
return Comment;
}(DataNode));
node$2.Comment = Comment$a;
/**
* Processing instructions, including doc types.
*/
var ProcessingInstruction = /** @class */ (function (_super) {
__extends(ProcessingInstruction, _super);
function ProcessingInstruction(name, data) {
var _this = _super.call(this, data) || this;
_this.name = name;
_this.type = domelementtype_1$1.ElementType.Directive;
return _this;
}
Object.defineProperty(ProcessingInstruction.prototype, "nodeType", {
get: function () {
return 1;
},
enumerable: false,
configurable: true
});
return ProcessingInstruction;
}(DataNode));
node$2.ProcessingInstruction = ProcessingInstruction;
/**
* A `Node` that can have children.
*/
var NodeWithChildren = /** @class */ (function (_super) {
__extends(NodeWithChildren, _super);
/**
* @param children Children of the node. Only certain node types can have children.
*/
function NodeWithChildren(children) {
var _this = _super.call(this) || this;
_this.children = children;
return _this;
}
Object.defineProperty(NodeWithChildren.prototype, "firstChild", {
// Aliases
/** First child of the node. */
get: function () {
var _a;
return (_a = this.children[0]) !== null && _a !== void 0 ? _a : null;
},
enumerable: false,
configurable: true
});
Object.defineProperty(NodeWithChildren.prototype, "lastChild", {
/** Last child of the node. */
get: function () {
return this.children.length > 0
? this.children[this.children.length - 1]
: null;
},
enumerable: false,
configurable: true
});
Object.defineProperty(NodeWithChildren.prototype, "childNodes", {
/**
* Same as {@link children}.
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
*/
get: function () {
return this.children;
},
set: function (children) {
this.children = children;
},
enumerable: false,
configurable: true
});
return NodeWithChildren;
}(Node));
node$2.NodeWithChildren = NodeWithChildren;
var CDATA = /** @class */ (function (_super) {
__extends(CDATA, _super);
function CDATA() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.type = domelementtype_1$1.ElementType.CDATA;
return _this;
}
Object.defineProperty(CDATA.prototype, "nodeType", {
get: function () {
return 4;
},
enumerable: false,
configurable: true
});
return CDATA;
}(NodeWithChildren));
node$2.CDATA = CDATA;
/**
* The root node of the document.
*/
var Document = /** @class */ (function (_super) {
__extends(Document, _super);
function Document() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.type = domelementtype_1$1.ElementType.Root;
return _this;
}
Object.defineProperty(Document.prototype, "nodeType", {
get: function () {
return 9;
},
enumerable: false,
configurable: true
});
return Document;
}(NodeWithChildren));
node$2.Document = Document;
/**
* An element within the DOM.
*/
var Element = /** @class */ (function (_super) {
__extends(Element, _super);
/**
* @param name Name of the tag, eg. `div`, `span`.
* @param attribs Object mapping attribute names to attribute values.
* @param children Children of the node.
*/
function Element(name, attribs, children, type) {
if (children === void 0) { children = []; }
if (type === void 0) { type = name === "script"
? domelementtype_1$1.ElementType.Script
: name === "style"
? domelementtype_1$1.ElementType.Style
: domelementtype_1$1.ElementType.Tag; }
var _this = _super.call(this, children) || this;
_this.name = name;
_this.attribs = attribs;
_this.type = type;
return _this;
}
Object.defineProperty(Element.prototype, "nodeType", {
get: function () {
return 1;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Element.prototype, "tagName", {
// DOM Level 1 aliases
/**
* Same as {@link name}.
* [DOM spec](https://dom.spec.whatwg.org)-compatible alias.
*/
get: function () {
return this.name;
},
set: function (name) {
this.name = name;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Element.prototype, "attributes", {
get: function () {
var _this = this;
return Object.keys(this.attribs).map(function (name) {
var _a, _b;
return ({
name: name,
value: _this.attribs[name],
namespace: (_a = _this["x-attribsNamespace"]) === null || _a === void 0 ? void 0 : _a[name],
prefix: (_b = _this["x-attribsPrefix"]) === null || _b === void 0 ? void 0 : _b[name],
});
});
},
enumerable: false,
configurable: true
});
return Element;
}(NodeWithChildren));
node$2.Element = Element;
/**
* @param node Node to check.
* @returns `true` if the node is a `Element`, `false` otherwise.
*/
function isTag$1(node) {
return (0, domelementtype_1$1.isTag)(node);
}
node$2.isTag = isTag$1;
/**
* @param node Node to check.
* @returns `true` if the node has the type `CDATA`, `false` otherwise.
*/
function isCDATA(node) {
return node.type === domelementtype_1$1.ElementType.CDATA;
}
node$2.isCDATA = isCDATA;
/**
* @param node Node to check.
* @returns `true` if the node has the type `Text`, `false` otherwise.
*/
function isText(node) {
return node.type === domelementtype_1$1.ElementType.Text;
}
node$2.isText = isText;
/**
* @param node Node to check.
* @returns `true` if the node has the type `Comment`, `false` otherwise.
*/
function isComment(node) {
return node.type === domelementtype_1$1.ElementType.Comment;
}
node$2.isComment = isComment;
/**
* @param node Node to check.
* @returns `true` if the node has the type `ProcessingInstruction`, `false` otherwise.
*/
function isDirective(node) {
return node.type === domelementtype_1$1.ElementType.Directive;
}
node$2.isDirective = isDirective;
/**
* @param node Node to check.
* @returns `true` if the node has the type `ProcessingInstruction`, `false` otherwise.
*/
function isDocument(node) {
return node.type === domelementtype_1$1.ElementType.Root;
}
node$2.isDocument = isDocument;
/**
* @param node Node to check.
* @returns `true` if the node has children, `false` otherwise.
*/
function hasChildren(node) {
return Object.prototype.hasOwnProperty.call(node, "children");
}
node$2.hasChildren = hasChildren;
/**
* Clone a node, and optionally its children.
*
* @param recursive Clone child nodes as well.
* @returns A clone of the node.
*/
function cloneNode(node, recursive) {
if (recursive === void 0) { recursive = false; }
var result;
if (isText(node)) {
result = new Text(node.data);
}
else if (isComment(node)) {
result = new Comment$a(node.data);
}
else if (isTag$1(node)) {
var children = recursive ? cloneChildren(node.children) : [];
var clone_1 = new Element(node.name, __assign$1({}, node.attribs), children);
children.forEach(function (child) { return (child.parent = clone_1); });
if (node.namespace != null) {
clone_1.namespace = node.namespace;
}
if (node["x-attribsNamespace"]) {
clone_1["x-attribsNamespace"] = __assign$1({}, node["x-attribsNamespace"]);
}
if (node["x-attribsPrefix"]) {
clone_1["x-attribsPrefix"] = __assign$1({}, node["x-attribsPrefix"]);
}
result = clone_1;
}
else if (isCDATA(node)) {
var children = recursive ? cloneChildren(node.children) : [];
var clone_2 = new CDATA(children);
children.forEach(function (child) { return (child.parent = clone_2); });
result = clone_2;
}
else if (isDocument(node)) {
var children = recursive ? cloneChildren(node.children) : [];
var clone_3 = new Document(children);
children.forEach(function (child) { return (child.parent = clone_3); });
if (node["x-mode"]) {
clone_3["x-mode"] = node["x-mode"];
}
result = clone_3;
}
else if (isDirective(node)) {
var instruction = new ProcessingInstruction(node.name, node.data);
if (node["x-name"] != null) {
instruction["x-name"] = node["x-name"];
instruction["x-publicId"] = node["x-publicId"];
instruction["x-systemId"] = node["x-systemId"];
}
result = instruction;
}
else {
throw new Error("Not implemented yet: ".concat(node.type));
}
result.startIndex = node.startIndex;
result.endIndex = node.endIndex;
if (node.sourceCodeLocation != null) {
result.sourceCodeLocation = node.sourceCodeLocation;
}
return result;
}
node$2.cloneNode = cloneNode;
function cloneChildren(childs) {
var children = childs.map(function (child) { return cloneNode(child, true); });
for (var i = 1; i < children.length; i++) {
children[i].prev = children[i - 1];
children[i - 1].next = children[i];
}
return children;
}
(function (exports) {
var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DomHandler = void 0;
var domelementtype_1 = require$$0$6;
var node_js_1 = node$2;
__exportStar(node$2, exports);
// Default options
var defaultOpts = {
withStartIndices: false,
withEndIndices: false,
xmlMode: false,
};
var DomHandler = /** @class */ (function () {
/**
* @param callback Called once parsing has completed.
* @param options Settings for the handler.
* @param elementCB Callback whenever a tag is closed.
*/
function DomHandler(callback, options, elementCB) {
/** The elements of the DOM */
this.dom = [];
/** The root element for the DOM */
this.root = new node_js_1.Document(this.dom);
/** Indicated whether parsing has been completed. */
this.done = false;
/** Stack of open tags. */
this.tagStack = [this.root];
/** A data node that is still being written to. */
this.lastNode = null;
/** Reference to the parser instance. Used for location information. */
this.parser = null;
// Make it possible to skip arguments, for backwards-compatibility
if (typeof options === "function") {
elementCB = options;
options = defaultOpts;
}
if (typeof callback === "object") {
options = callback;
callback = undefined;
}
this.callback = callback !== null && callback !== void 0 ? callback : null;
this.options = options !== null && options !== void 0 ? options : defaultOpts;
this.elementCB = elementCB !== null && elementCB !== void 0 ? elementCB : null;
}
DomHandler.prototype.onparserinit = function (parser) {
this.parser = parser;
};
// Resets the handler back to starting state
DomHandler.prototype.onreset = function () {
this.dom = [];
this.root = new node_js_1.Document(this.dom);
this.done = false;
this.tagStack = [this.root];
this.lastNode = null;
this.parser = null;
};
// Signals the handler that parsing is done
DomHandler.prototype.onend = function () {
if (this.done)
return;
this.done = true;
this.parser = null;
this.handleCallback(null);
};
DomHandler.prototype.onerror = function (error) {
this.handleCallback(error);
};
DomHandler.prototype.onclosetag = function () {
this.lastNode = null;
var elem = this.tagStack.pop();
if (this.options.withEndIndices) {
elem.endIndex = this.parser.endIndex;
}
if (this.elementCB)
this.elementCB(elem);
};
DomHandler.prototype.onopentag = function (name, attribs) {
var type = this.options.xmlMode ? domelementtype_1.ElementType.Tag : undefined;
var element = new node_js_1.Element(name, attribs, undefined, type);
this.addNode(element);
this.tagStack.push(element);
};
DomHandler.prototype.ontext = function (data) {
var lastNode = this.lastNode;
if (lastNode && lastNode.type === domelementtype_1.ElementType.Text) {
lastNode.data += data;
if (this.options.withEndIndices) {
lastNode.endIndex = this.parser.endIndex;
}
}
else {
var node = new node_js_1.Text(data);
this.addNode(node);
this.lastNode = node;
}
};
DomHandler.prototype.oncomment = function (data) {
if (this.lastNode && this.lastNode.type === domelementtype_1.ElementType.Comment) {
this.lastNode.data += data;
return;
}
var node = new node_js_1.Comment(data);
this.addNode(node);
this.lastNode = node;
};
DomHandler.prototype.oncommentend = function () {
this.lastNode = null;
};
DomHandler.prototype.oncdatastart = function () {
var text = new node_js_1.Text("");
var node = new node_js_1.CDATA([text]);
this.addNode(node);
text.parent = node;
this.lastNode = text;
};
DomHandler.prototype.oncdataend = function () {
this.lastNode = null;
};
DomHandler.prototype.onprocessinginstruction = function (name, data) {
var node = new node_js_1.ProcessingInstruction(name, data);
this.addNode(node);
};
DomHandler.prototype.handleCallback = function (error) {
if (typeof this.callback === "function") {
this.callback(error, this.dom);
}
else if (error) {
throw error;
}
};
DomHandler.prototype.addNode = function (node) {
var parent = this.tagStack[this.tagStack.length - 1];
var previousSibling = parent.children[parent.children.length - 1];
if (this.options.withStartIndices) {
node.startIndex = this.parser.startIndex;
}
if (this.options.withEndIndices) {
node.endIndex = this.parser.endIndex;
}
parent.children.push(node);
if (previousSibling) {
node.prev = previousSibling;
previousSibling.next = node;
}
node.parent = parent;
this.lastNode = null;
};
return DomHandler;
}());
exports.DomHandler = DomHandler;
exports.default = DomHandler;
} (lib$2));
var lib$1 = {};
var lib = {};
var decode$6 = {};
var decodeDataHtml = {};
// Generated using scripts/write-decode-map.ts
Object.defineProperty(decodeDataHtml, "__esModule", { value: true });
decodeDataHtml.default = new Uint16Array(
// prettier-ignore
"\u1d41<\xd5\u0131\u028a\u049d\u057b\u05d0\u0675\u06de\u07a2\u07d6\u080f\u0a4a\u0a91\u0da1\u0e6d\u0f09\u0f26\u10ca\u1228\u12e1\u1415\u149d\u14c3\u14df\u1525\0\0\0\0\0\0\u156b\u16cd\u198d\u1c12\u1ddd\u1f7e\u2060\u21b0\u228d\u23c0\u23fb\u2442\u2824\u2912\u2d08\u2e48\u2fce\u3016\u32ba\u3639\u37ac\u38fe\u3a28\u3a71\u3ae0\u3b2e\u0800EMabcfglmnoprstu\\bfms\x7f\x84\x8b\x90\x95\x98\xa6\xb3\xb9\xc8\xcflig\u803b\xc6\u40c6P\u803b&\u4026cute\u803b\xc1\u40c1reve;\u4102\u0100iyx}rc\u803b\xc2\u40c2;\u4410r;\uc000\ud835\udd04rave\u803b\xc0\u40c0pha;\u4391acr;\u4100d;\u6a53\u0100gp\x9d\xa1on;\u4104f;\uc000\ud835\udd38plyFunction;\u6061ing\u803b\xc5\u40c5\u0100cs\xbe\xc3r;\uc000\ud835\udc9cign;\u6254ilde\u803b\xc3\u40c3ml\u803b\xc4\u40c4\u0400aceforsu\xe5\xfb\xfe\u0117\u011c\u0122\u0127\u012a\u0100cr\xea\xf2kslash;\u6216\u0176\xf6\xf8;\u6ae7ed;\u6306y;\u4411\u0180crt\u0105\u010b\u0114ause;\u6235noullis;\u612ca;\u4392r;\uc000\ud835\udd05pf;\uc000\ud835\udd39eve;\u42d8c\xf2\u0113mpeq;\u624e\u0700HOacdefhilorsu\u014d\u0151\u0156\u0180\u019e\u01a2\u01b5\u01b7\u01ba\u01dc\u0215\u0273\u0278\u027ecy;\u4427PY\u803b\xa9\u40a9\u0180cpy\u015d\u0162\u017aute;\u4106\u0100;i\u0167\u0168\u62d2talDifferentialD;\u6145leys;\u612d\u0200aeio\u0189\u018e\u0194\u0198ron;\u410cdil\u803b\xc7\u40c7rc;\u4108nint;\u6230ot;\u410a\u0100dn\u01a7\u01adilla;\u40b8terDot;\u40b7\xf2\u017fi;\u43a7rcle\u0200DMPT\u01c7\u01cb\u01d1\u01d6ot;\u6299inus;\u6296lus;\u6295imes;\u6297o\u0100cs\u01e2\u01f8kwiseContourIntegral;\u6232eCurly\u0100DQ\u0203\u020foubleQuote;\u601duote;\u6019\u0200lnpu\u021e\u0228\u0247\u0255on\u0100;e\u0225\u0226\u6237;\u6a74\u0180git\u022f\u0236\u023aruent;\u6261nt;\u622fourIntegral;\u622e\u0100fr\u024c\u024e;\u6102oduct;\u6210nterClockwiseContourIntegral;\u6233oss;\u6a2fcr;\uc000\ud835\udc9ep\u0100;C\u0284\u0285\u62d3ap;\u624d\u0580DJSZacefios\u02a0\u02ac\u02b0\u02b4\u02b8\u02cb\u02d7\u02e1\u02e6\u0333\u048d\u0100;o\u0179\u02a5trahd;\u6911cy;\u4402cy;\u4405cy;\u440f\u0180grs\u02bf\u02c4\u02c7ger;\u6021r;\u61a1hv;\u6ae4\u0100ay\u02d0\u02d5ron;\u410e;\u4414l\u0100;t\u02dd\u02de\u6207a;\u4394r;\uc000\ud835\udd07\u0100af\u02eb\u0327\u0100cm\u02f0\u0322ritical\u0200ADGT\u0300\u0306\u0316\u031ccute;\u40b4o\u0174\u030b\u030d;\u42d9bleAcute;\u42ddrave;\u4060ilde;\u42dcond;\u62c4ferentialD;\u6146\u0470\u033d\0\0\0\u0342\u0354\0\u0405f;\uc000\ud835\udd3b\u0180;DE\u0348\u0349\u034d\u40a8ot;\u60dcqual;\u6250ble\u0300CDLRUV\u0363\u0372\u0382\u03cf\u03e2\u03f8ontourIntegra\xec\u0239o\u0274\u0379\0\0\u037b\xbb\u0349nArrow;\u61d3\u0100eo\u0387\u03a4ft\u0180ART\u0390\u0396\u03a1rrow;\u61d0ightArrow;\u61d4e\xe5\u02cang\u0100LR\u03ab\u03c4eft\u0100AR\u03b3\u03b9rrow;\u67f8ightArrow;\u67faightArrow;\u67f9ight\u0100AT\u03d8\u03derrow;\u61d2ee;\u62a8p\u0241\u03e9\0\0\u03efrrow;\u61d1ownArrow;\u61d5erticalBar;\u6225n\u0300ABLRTa\u0412\u042a\u0430\u045e\u047f\u037crrow\u0180;BU\u041d\u041e\u0422\u6193ar;\u6913pArrow;\u61f5reve;\u4311eft\u02d2\u043a\0\u0446\0\u0450ightVector;\u6950eeVector;\u695eector\u0100;B\u0459\u045a\u61bdar;\u6956ight\u01d4\u0467\0\u0471eeVector;\u695fector\u0100;B\u047a\u047b\u61c1ar;\u6957ee\u0100;A\u0486\u0487\u62a4rrow;\u61a7\u0100ct\u0492\u0497r;\uc000\ud835\udc9frok;\u4110\u0800NTacdfglmopqstux\u04bd\u04c0\u04c4\u04cb\u04de\u04e2\u04e7\u04ee\u04f5\u0521\u052f\u0536\u0552\u055d\u0560\u0565G;\u414aH\u803b\xd0\u40d0cute\u803b\xc9\u40c9\u0180aiy\u04d2\u04d7\u04dcron;\u411arc\u803b\xca\u40ca;\u442dot;\u4116r;\uc000\ud835\udd08rave\u803b\xc8\u40c8ement;\u6208\u0100ap\u04fa\u04fecr;\u4112ty\u0253\u0506\0\0\u0512mallSquare;\u65fberySmallSquare;\u65ab\u0100gp\u0526\u052aon;\u4118f;\uc000\ud835\udd3csilon;\u4395u\u0100ai\u053c\u0549l\u0100;T\u0542\u0543\u6a75ilde;\u6242librium;\u61cc\u0100ci\u0557\u055ar;\u6130m;\u6a73a;\u4397ml\u803b\xcb\u40cb\u0100ip\u056a\u056fsts;\u6203onentialE;\u6147\u0280cfios\u0585\u0588\u058d\u05b2\u05ccy;\u4424r;\uc000\ud835\udd09lled\u0253\u0597\0\0\u05a3mallSquare;\u65fcerySmallSquare;\u65aa\u0370\u05ba\0\u05bf\0\0\u05c4f;\uc000\ud835\udd3dAll;\u6200riertrf;\u6131c\xf2\u05cb\u0600JTabcdfgorst\u05e8\u05ec\u05ef\u05fa\u0600\u0612\u0616\u061b\u061d\u0623\u066c\u0672cy;\u4403\u803b>\u403emma\u0100;d\u05f7\u05f8\u4393;\u43dcreve;\u411e\u0180eiy\u0607\u060c\u0610dil;\u4122rc;\u411c;\u4413ot;\u4120r;\uc000\ud835\udd0a;\u62d9pf;\uc000\ud835\udd3eeater\u0300EFGLST\u0635\u0644\u064e\u0656\u065b\u0666qual\u0100;L\u063e\u063f\u6265ess;\u62dbullEqual;\u6267reater;\u6aa2ess;\u6277lantEqual;\u6a7eilde;\u6273cr;\uc000\ud835\udca2;\u626b\u0400Aacfiosu\u0685\u068b\u0696\u069b\u069e\u06aa\u06be\u06caRDcy;\u442a\u0100ct\u0690\u0694ek;\u42c7;\u405eirc;\u4124r;\u610clbertSpace;\u610b\u01f0\u06af\0\u06b2f;\u610dizontalLine;\u6500\u0100ct\u06c3\u06c5\xf2\u06a9rok;\u4126mp\u0144\u06d0\u06d8ownHum\xf0\u012fqual;\u624f\u0700EJOacdfgmnostu\u06fa\u06fe\u0703\u0707\u070e\u071a\u071e\u0721\u0728\u0744\u0778\u078b\u078f\u0795cy;\u4415lig;\u4132cy;\u4401cute\u803b\xcd\u40cd\u0100iy\u0713\u0718rc\u803b\xce\u40ce;\u4418ot;\u4130r;\u6111rave\u803b\xcc\u40cc\u0180;ap\u0720\u072f\u073f\u0100cg\u0734\u0737r;\u412ainaryI;\u6148lie\xf3\u03dd\u01f4\u0749\0\u0762\u0100;e\u074d\u074e\u622c\u0100gr\u0753\u0758ral;\u622bsection;\u62c2isible\u0100CT\u076c\u0772omma;\u6063imes;\u6062\u0180gpt\u077f\u0783\u0788on;\u412ef;\uc000\ud835\udd40a;\u4399cr;\u6110ilde;\u4128\u01eb\u079a\0\u079ecy;\u4406l\u803b\xcf\u40cf\u0280cfosu\u07ac\u07b7\u07bc\u07c2\u07d0\u0100iy\u07b1\u07b5rc;\u4134;\u4419r;\uc000\ud835\udd0dpf;\uc000\ud835\udd41\u01e3\u07c7\0\u07ccr;\uc000\ud835\udca5rcy;\u4408kcy;\u4404\u0380HJacfos\u07e4\u07e8\u07ec\u07f1\u07fd\u0802\u0808cy;\u4425cy;\u440cppa;\u439a\u0100ey\u07f6\u07fbdil;\u4136;\u441ar;\uc000\ud835\udd0epf;\uc000\ud835\udd42cr;\uc000\ud835\udca6\u0580JTaceflmost\u0825\u0829\u082c\u0850\u0863\u09b3\u09b8\u09c7\u09cd\u0a37\u0a47cy;\u4409\u803b<\u403c\u0280cmnpr\u0837\u083c\u0841\u0844\u084dute;\u4139bda;\u439bg;\u67ealacetrf;\u6112r;\u619e\u0180aey\u0857\u085c\u0861ron;\u413ddil;\u413b;\u441b\u0100fs\u0868\u0970t\u0500ACDFRTUVar\u087e\u08a9\u08b1\u08e0\u08e6\u08fc\u092f\u095b\u0390\u096a\u0100nr\u0883\u088fgleBracket;\u67e8row\u0180;BR\u0899\u089a\u089e\u6190ar;\u61e4ightArrow;\u61c6eiling;\u6308o\u01f5\u08b7\0\u08c3bleBracket;\u67e6n\u01d4\u08c8\0\u08d2eeVector;\u6961ector\u0100;B\u08db\u08dc\u61c3ar;\u6959loor;\u630aight\u0100AV\u08ef\u08f5rrow;\u6194ector;\u694e\u0100er\u0901\u0917e\u0180;AV\u0909\u090a\u0910\u62a3rrow;\u61a4ector;\u695aiangle\u0180;BE\u0924\u0925\u0929\u62b2ar;\u69cfqual;\u62b4p\u0180DTV\u0937\u0942\u094cownVector;\u6951eeVector;\u6960ector\u0100;B\u0956\u0957\u61bfar;\u6958ector\u0100;B\u0965\u0966\u61bcar;\u6952ight\xe1\u039cs\u0300EFGLST\u097e\u098b\u0995\u099d\u09a2\u09adqualGreater;\u62daullEqual;\u6266reater;\u6276ess;\u6aa1lantEqual;\u6a7dilde;\u6272r;\uc000\ud835\udd0f\u0100;e\u09bd\u09be\u62d8ftarrow;\u61daidot;\u413f\u0180npw\u09d4\u0a16\u0a1bg\u0200LRlr\u09de\u09f7\u0a02\u0a10eft\u0100AR\u09e6\u09ecrrow;\u67f5ightArrow;\u67f7ightArrow;\u67f6eft\u0100ar\u03b3\u0a0aight\xe1\u03bfight\xe1\u03caf;\uc000\ud835\udd43er\u0100LR\u0a22\u0a2ceftArrow;\u6199ightArrow;\u6198\u0180cht\u0a3e\u0a40\u0a42\xf2\u084c;\u61b0rok;\u4141;\u626a\u0400acefiosu\u0a5a\u0a5d\u0a60\u0a77\u0a7c\u0a85\u0a8b\u0a8ep;\u6905y;\u441c\u0100dl\u0a65\u0a6fiumSpace;\u605flintrf;\u6133r;\uc000\ud835\udd10nusPlus;\u6213pf;\uc000\ud835\udd44c\xf2\u0a76;\u439c\u0480Jacefostu\u0aa3\u0aa7\u0aad\u0ac0\u0b14\u0b19\u0d91\u0d97\u0d9ecy;\u440acute;\u4143\u0180aey\u0ab4\u0ab9\u0aberon;\u4147dil;\u4145;\u441d\u0180gsw\u0ac7\u0af0\u0b0eative\u0180MTV\u0ad3\u0adf\u0ae8ediumSpace;\u600bhi\u0100cn\u0ae6\u0ad8\xeb\u0ad9eryThi\xee\u0ad9ted\u0100GL\u0af8\u0b06reaterGreate\xf2\u0673essLes\xf3\u0a48Line;\u400ar;\uc000\ud835\udd11\u0200Bnpt\u0b22\u0b28\u0b37\u0b3areak;\u6060BreakingSpace;\u40a0f;\u6115\u0680;CDEGHLNPRSTV\u0b55\u0b56\u0b6a\u0b7c\u0ba1\u0beb\u0c04\u0c5e\u0c84\u0ca6\u0cd8\u0d61\u0d85\u6aec\u0100ou\u0b5b\u0b64ngruent;\u6262pCap;\u626doubleVerticalBar;\u6226\u0180lqx\u0b83\u0b8a\u0b9bement;\u6209ual\u0100;T\u0b92\u0b93\u6260ilde;\uc000\u2242\u0338ists;\u6204reater\u0380;EFGLST\u0bb6\u0bb7\u0bbd\u0bc9\u0bd3\u0bd8\u0be5\u626fqual;\u6271ullEqual;\uc000\u2267\u0338reater;\uc000\u226b\u0338ess;\u6279lantEqual;\uc000\u2a7e\u0338ilde;\u6275ump\u0144\u0bf2\u0bfdownHump;\uc000\u224e\u0338qual;\uc000\u224f\u0338e\u0100fs\u0c0a\u0c27tTriangle\u0180;BE\u0c1a\u0c1b\u0c21\u62eaar;\uc000\u29cf\u0338qual;\u62ecs\u0300;EGLST\u0c35\u0c36\u0c3c\u0c44\u0c4b\u0c58\u626equal;\u6270reater;\u6278ess;\uc000\u226a\u0338lantEqual;\uc000\u2a7d\u0338ilde;\u6274ested\u0100GL\u0c68\u0c79reaterGreater;\uc000\u2aa2\u0338essLess;\uc000\u2aa1\u0338recedes\u0180;ES\u0c92\u0c93\u0c9b\u6280qual;\uc000\u2aaf\u0338lantEqual;\u62e0\u0100ei\u0cab\u0cb9verseElement;\u620cghtTriangle\u0180;BE\u0ccb\u0ccc\u0cd2\u62ebar;\uc000\u29d0\u0338qual;\u62ed\u0100qu\u0cdd\u0d0cuareSu\u0100bp\u0ce8\u0cf9set\u0100;E\u0cf0\u0cf3\uc000\u228f\u0338qual;\u62e2erset\u0100;E\u0d03\u0d06\uc000\u2290\u0338qual;\u62e3\u0180bcp\u0d13\u0d24\u0d4eset\u0100;E\u0d1b\u0d1e\uc000\u2282\u20d2qual;\u6288ceeds\u0200;EST\u0d32\u0d33\u0d3b\u0d46\u6281qual;\uc000\u2ab0\u0338lantEqual;\u62e1ilde;\uc000\u227f\u0338erset\u0100;E\u0d58\u0d5b\uc000\u2283\u20d2qual;\u6289ilde\u0200;EFT\u0d6e\u0d6f\u0d75\u0d7f\u6241qual;\u6244ullEqual;\u6247ilde;\u6249erticalBar;\u6224cr;\uc000\ud835\udca9ilde\u803b\xd1\u40d1;\u439d\u0700Eacdfgmoprstuv\u0dbd\u0dc2\u0dc9\u0dd5\u0ddb\u0de0\u0de7\u0dfc\u0e02\u0e20\u0e22\u0e32\u0e3f\u0e44lig;\u4152cute\u803b\xd3\u40d3\u0100iy\u0dce\u0dd3rc\u803b\xd4\u40d4;\u441eblac;\u4150r;\uc000\ud835\udd12rave\u803b\xd2\u40d2\u0180aei\u0dee\u0df2\u0df6cr;\u414cga;\u43a9cron;\u439fpf;\uc000\ud835\udd46enCurly\u0100DQ\u0e0e\u0e1aoubleQuote;\u601cuote;\u6018;\u6a54\u0100cl\u0e27\u0e2cr;\uc000\ud835\udcaaash\u803b\xd8\u40d8i\u016c\u0e37\u0e3cde\u803b\xd5\u40d5es;\u6a37ml\u803b\xd6\u40d6er\u0100BP\u0e4b\u0e60\u0100ar\u0e50\u0e53r;\u603eac\u0100ek\u0e5a\u0e5c;\u63deet;\u63b4arenthesis;\u63dc\u0480acfhilors\u0e7f\u0e87\u0e8a\u0e8f\u0e92\u0e94\u0e9d\u0eb0\u0efcrtialD;\u6202y;\u441fr;\uc000\ud835\udd13i;\u43a6;\u43a0usMinus;\u40b1\u0100ip\u0ea2\u0eadncareplan\xe5\u069df;\u6119\u0200;eio\u0eb9\u0eba\u0ee0\u0ee4\u6abbcedes\u0200;EST\u0ec8\u0ec9\u0ecf\u0eda\u627aqual;\u6aaflantEqual;\u627cilde;\u627eme;\u6033\u0100dp\u0ee9\u0eeeuct;\u620fortion\u0100;a\u0225\u0ef9l;\u621d\u0100ci\u0f01\u0f06r;\uc000\ud835\udcab;\u43a8\u0200Ufos\u0f11\u0f16\u0f1b\u0f1fOT\u803b\"\u4022r;\uc000\ud835\udd14pf;\u611acr;\uc000\ud835\udcac\u0600BEacefhiorsu\u0f3e\u0f43\u0f47\u0f60\u0f73\u0fa7\u0faa\u0fad\u1096\u10a9\u10b4\u10bearr;\u6910G\u803b\xae\u40ae\u0180cnr\u0f4e\u0f53\u0f56ute;\u4154g;\u67ebr\u0100;t\u0f5c\u0f5d\u61a0l;\u6916\u0180aey\u0f67\u0f6c\u0f71ron;\u4158dil;\u4156;\u4420\u0100;v\u0f78\u0f79\u611cerse\u0100EU\u0f82\u0f99\u0100lq\u0f87\u0f8eement;\u620builibrium;\u61cbpEquilibrium;\u696fr\xbb\u0f79o;\u43a1ght\u0400ACDFTUVa\u0fc1\u0feb\u0ff3\u1022\u1028\u105b\u1087\u03d8\u0100nr\u0fc6\u0fd2gleBracket;\u67e9row\u0180;BL\u0fdc\u0fdd\u0fe1\u6192ar;\u61e5eftArrow;\u61c4eiling;\u6309o\u01f5\u0ff9\0\u1005bleBracket;\u67e7n\u01d4\u100a\0\u1014eeVector;\u695dector\u0100;B\u101d\u101e\u61c2ar;\u6955loor;\u630b\u0100er\u102d\u1043e\u0180;AV\u1035\u1036\u103c\u62a2rrow;\u61a6ector;\u695biangle\u0180;BE\u1050\u1051\u1055\u62b3ar;\u69d0qual;\u62b5p\u0180DTV\u1063\u106e\u1078ownVector;\u694feeVector;\u695cector\u0100;B\u1082\u1083\u61bear;\u6954ector\u0100;B\u1091\u1092\u61c0ar;\u6953\u0100pu\u109b\u109ef;\u611dndImplies;\u6970ightarrow;\u61db\u0100ch\u10b9\u10bcr;\u611b;\u61b1leDelayed;\u69f4\u0680HOacfhimoqstu\u10e4\u10f1\u10f7\u10fd\u1119\u111e\u1151\u1156\u1161\u1167\u11b5\u11bb\u11bf\u0100Cc\u10e9\u10eeHcy;\u4429y;\u4428FTcy;\u442ccute;\u415a\u0280;aeiy\u1108\u1109\u110e\u1113\u1117\u6abcron;\u4160dil;\u415erc;\u415c;\u4421r;\uc000\ud835\udd16ort\u0200DLRU\u112a\u1134\u113e\u1149ownArrow\xbb\u041eeftArrow\xbb\u089aightArrow\xbb\u0fddpArrow;\u6191gma;\u43a3allCircle;\u6218pf;\uc000\ud835\udd4a\u0272\u116d\0\0\u1170t;\u621aare\u0200;ISU\u117b\u117c\u1189\u11af\u65a1ntersection;\u6293u\u0100bp\u118f\u119eset\u0100;E\u1197\u1198\u628fqual;\u6291erset\u0100;E\u11a8\u11a9\u6290qual;\u6292nion;\u6294cr;\uc000\ud835\udcaear;\u62c6\u0200bcmp\u11c8\u11db\u1209\u120b\u0100;s\u11cd\u11ce\u62d0et\u0100;E\u11cd\u11d5qual;\u6286\u0100ch\u11e0\u1205eeds\u0200;EST\u11ed\u11ee\u11f4\u11ff\u627bqual;\u6ab0lantEqual;\u627dilde;\u627fTh\xe1\u0f8c;\u6211\u0180;es\u1212\u1213\u1223\u62d1rset\u0100;E\u121c\u121d\u6283qual;\u6287et\xbb\u1213\u0580HRSacfhiors\u123e\u1244\u1249\u1255\u125e\u1271\u1276\u129f\u12c2\u12c8\u12d1ORN\u803b\xde\u40deADE;\u6122\u0100Hc\u124e\u1252cy;\u440by;\u4426\u0100bu\u125a\u125c;\u4009;\u43a4\u0180aey\u1265\u126a\u126fron;\u4164dil;\u4162;\u4422r;\uc000\ud835\udd17\u0100ei\u127b\u1289\u01f2\u1280\0\u1287efore;\u6234a;\u4398\u0100cn\u128e\u1298kSpace;\uc000\u205f\u200aSpace;\u6009lde\u0200;EFT\u12ab\u12ac\u12b2\u12bc\u623cqual;\u6243ullEqual;\u6245ilde;\u6248pf;\uc000\ud835\udd4bipleDot;\u60db\u0100ct\u12d6\u12dbr;\uc000\ud835\udcafrok;\u4166\u0ae1\u12f7\u130e\u131a\u1326\0\u132c\u1331\0\0\0\0\0\u1338\u133d\u1377\u1385\0\u13ff\u1404\u140a\u1410\u0100cr\u12fb\u1301ute\u803b\xda\u40dar\u0100;o\u1307\u1308\u619fcir;\u6949r\u01e3\u1313\0\u1316y;\u440eve;\u416c\u0100iy\u131e\u1323rc\u803b\xdb\u40db;\u4423blac;\u4170r;\uc000\ud835\udd18rave\u803b\xd9\u40d9acr;\u416a\u0100di\u1341\u1369er\u0100BP\u1348\u135d\u0100ar\u134d\u1350r;\u405fac\u0100ek\u1357\u1359;\u63dfet;\u63b5arenthesis;\u63ddon\u0100;P\u1370\u1371\u62c3lus;\u628e\u0100gp\u137b\u137fon;\u4172f;\uc000\ud835\udd4c\u0400ADETadps\u1395\u13ae\u13b8\u13c4\u03e8\u13d2\u13d7\u13f3rrow\u0180;BD\u1150\u13a0\u13a4ar;\u6912ownArrow;\u61c5ownArrow;\u6195quilibrium;\u696eee\u0100;A\u13cb\u13cc\u62a5rrow;\u61a5own\xe1\u03f3er\u0100LR\u13de\u13e8eftArrow;\u6196ightArrow;\u6197i\u0100;l\u13f9\u13fa\u43d2on;\u43a5ing;\u416ecr;\uc000\ud835\udcb0ilde;\u4168ml\u803b\xdc\u40dc\u0480Dbcdefosv\u1427\u142c\u1430\u1433\u143e\u1485\u148a\u1490\u1496ash;\u62abar;\u6aeby;\u4412ash\u0100;l\u143b\u143c\u62a9;\u6ae6\u0100er\u1443\u1445;\u62c1\u0180bty\u144c\u1450\u147aar;\u6016\u0100;i\u144f\u1455cal\u0200BLST\u1461\u1465\u146a\u1474ar;\u6223ine;\u407ceparator;\u6758ilde;\u6240ThinSpace;\u600ar;\uc000\ud835\udd19pf;\uc000\ud835\udd4dcr;\uc000\ud835\udcb1dash;\u62aa\u0280cefos\u14a7\u14ac\u14b1\u14b6\u14bcirc;\u4174dge;\u62c0r;\uc000\ud835\udd1apf;\uc000\ud835\udd4ecr;\uc000\ud835\udcb2\u0200fios\u14cb\u14d0\u14d2\u14d8r;\uc000\ud835\udd1b;\u439epf;\uc000\ud835\udd4fcr;\uc000\ud835\udcb3\u0480AIUacfosu\u14f1\u14f5\u14f9\u14fd\u1504\u150f\u1514\u151a\u1520cy;\u442fcy;\u4407cy;\u442ecute\u803b\xdd\u40dd\u0100iy\u1509\u150drc;\u4176;\u442br;\uc000\ud835\udd1cpf;\uc000\ud835\udd50cr;\uc000\ud835\udcb4ml;\u4178\u0400Hacdefos\u1535\u1539\u153f\u154b\u154f\u155d\u1560\u1564cy;\u4416cute;\u4179\u0100ay\u1544\u1549ron;\u417d;\u4417ot;\u417b\u01f2\u1554\0\u155boWidt\xe8\u0ad9a;\u4396r;\u6128pf;\u6124cr;\uc000\ud835\udcb5\u0be1\u1583\u158a\u1590\0\u15b0\u15b6\u15bf\0\0\0\0\u15c6\u15db\u15eb\u165f\u166d\0\u1695\u169b\u16b2\u16b9\0\u16becute\u803b\xe1\u40e1reve;\u4103\u0300;Ediuy\u159c\u159d\u15a1\u15a3\u15a8\u15ad\u623e;\uc000\u223e\u0333;\u623frc\u803b\xe2\u40e2te\u80bb\xb4\u0306;\u4430lig\u803b\xe6\u40e6\u0100;r\xb2\u15ba;\uc000\ud835\udd1erave\u803b\xe0\u40e0\u0100ep\u15ca\u15d6\u0100fp\u15cf\u15d4sym;\u6135\xe8\u15d3ha;\u43b1\u0100ap\u15dfc\u0100cl\u15e4\u15e7r;\u4101g;\u6a3f\u0264\u15f0\0\0\u160a\u0280;adsv\u15fa\u15fb\u15ff\u1601\u1607\u6227nd;\u6a55;\u6a5clope;\u6a58;\u6a5a\u0380;elmrsz\u1618\u1619\u161b\u161e\u163f\u164f\u1659\u6220;\u69a4e\xbb\u1619sd\u0100;a\u1625\u1626\u6221\u0461\u1630\u1632\u1634\u1636\u1638\u163a\u163c\u163e;\u69a8;\u69a9;\u69aa;\u69ab;\u69ac;\u69ad;\u69ae;\u69aft\u0100;v\u1645\u1646\u621fb\u0100;d\u164c\u164d\u62be;\u699d\u0100pt\u1654\u1657h;\u6222\xbb\xb9arr;\u637c\u0100gp\u1663\u1667on;\u4105f;\uc000\ud835\udd52\u0380;Eaeiop\u12c1\u167b\u167d\u1682\u1684\u1687\u168a;\u6a70cir;\u6a6f;\u624ad;\u624bs;\u4027rox\u0100;e\u12c1\u1692\xf1\u1683ing\u803b\xe5\u40e5\u0180cty\u16a1\u16a6\u16a8r;\uc000\ud835\udcb6;\u402amp\u0100;e\u12c1\u16af\xf1\u0288ilde\u803b\xe3\u40e3ml\u803b\xe4\u40e4\u0100ci\u16c2\u16c8onin\xf4\u0272nt;\u6a11\u0800Nabcdefiklnoprsu\u16ed\u16f1\u1730\u173c\u1743\u1748\u1778\u177d\u17e0\u17e6\u1839\u1850\u170d\u193d\u1948\u1970ot;\u6aed\u0100cr\u16f6\u171ek\u0200ceps\u1700\u1705\u170d\u1713ong;\u624cpsilon;\u43f6rime;\u6035im\u0100;e\u171a\u171b\u623dq;\u62cd\u0176\u1722\u1726ee;\u62bded\u0100;g\u172c\u172d\u6305e\xbb\u172drk\u0100;t\u135c\u1737brk;\u63b6\u0100oy\u1701\u1741;\u4431quo;\u601e\u0280cmprt\u1753\u175b\u1761\u1764\u1768aus\u0100;e\u010a\u0109ptyv;\u69b0s\xe9\u170cno\xf5\u0113\u0180ahw\u176f\u1771\u1773;\u43b2;\u6136een;\u626cr;\uc000\ud835\udd1fg\u0380costuvw\u178d\u179d\u17b3\u17c1\u17d5\u17db\u17de\u0180aiu\u1794\u1796\u179a\xf0\u0760rc;\u65efp\xbb\u1371\u0180dpt\u17a4\u17a8\u17adot;\u6a00lus;\u6a01imes;\u6a02\u0271\u17b9\0\0\u17becup;\u6a06ar;\u6605riangle\u0100du\u17cd\u17d2own;\u65bdp;\u65b3plus;\u6a04e\xe5\u1444\xe5\u14adarow;\u690d\u0180ako\u17ed\u1826\u1835\u0100cn\u17f2\u1823k\u0180lst\u17fa\u05ab\u1802ozenge;\u69ebriangle\u0200;dlr\u1812\u1813\u1818\u181d\u65b4own;\u65beeft;\u65c2ight;\u65b8k;\u6423\u01b1\u182b\0\u1833\u01b2\u182f\0\u1831;\u6592;\u65914;\u6593ck;\u6588\u0100eo\u183e\u184d\u0100;q\u1843\u1846\uc000=\u20e5uiv;\uc000\u2261\u20e5t;\u6310\u0200ptwx\u1859\u185e\u1867\u186cf;\uc000\ud835\udd53\u0100;t\u13cb\u1863om\xbb\u13cctie;\u62c8\u0600DHUVbdhmptuv\u1885\u1896\u18aa\u18bb\u18d7\u18db\u18ec\u18ff\u1905\u190a\u1910\u1921\u0200LRlr\u188e\u1890\u1892\u1894;\u6557;\u6554;\u6556;\u6553\u0280;DUdu\u18a1\u18a2\u18a4\u18a6\u18a8\u6550;\u6566;\u6569;\u6564;\u6567\u0200LRlr\u18b3\u18b5\u18b7\u18b9;\u655d;\u655a;\u655c;\u6559\u0380;HLRhlr\u18ca\u18cb\u18cd\u18cf\u18d1\u18d3\u18d5\u6551;\u656c;\u6563;\u6560;\u656b;\u6562;\u655fox;\u69c9\u0200LRlr\u18e4\u18e6\u18e8\u18ea;\u6555;\u6552;\u6510;\u650c\u0280;DUdu\u06bd\u18f7\u18f9\u18fb\u18fd;\u6565;\u6568;\u652c;\u6534inus;\u629flus;\u629eimes;\u62a0\u0200LRlr\u1919\u191b\u191d\u191f;\u655b;\u6558;\u6518;\u6514\u0380;HLRhlr\u1930\u1931\u1933\u1935\u1937\u1939\u193b\u6502;\u656a;\u6561;\u655e;\u653c;\u6524;\u651c\u0100ev\u0123\u1942bar\u803b\xa6\u40a6\u0200ceio\u1951\u1956\u195a\u1960r;\uc000\ud835\udcb7mi;\u604fm\u0100;e\u171a\u171cl\u0180;bh\u1968\u1969\u196b\u405c;\u69c5sub;\u67c8\u016c\u1974\u197el\u0100;e\u1979\u197a\u6022t\xbb\u197ap\u0180;Ee\u012f\u1985\u1987;\u6aae\u0100;q\u06dc\u06db\u0ce1\u19a7\0\u19e8\u1a11\u1a15\u1a32\0\u1a37\u1a50\0\0\u1ab4\0\0\u1ac1\0\0\u1b21\u1b2e\u1b4d\u1b52\0\u1bfd\0\u1c0c\u0180cpr\u19ad\u19b2\u19ddute;\u4107\u0300;abcds\u19bf\u19c0\u19c4\u19ca\u19d5\u19d9\u6229nd;\u6a44rcup;\u6a49\u0100au\u19cf\u19d2p;\u6a4bp;\u6a47ot;\u6a40;\uc000\u2229\ufe00\u0100eo\u19e2\u19e5t;\u6041\xee\u0693\u0200aeiu\u19f0\u19fb\u1a01\u1a05\u01f0\u19f5\0\u19f8s;\u6a4don;\u410ddil\u803b\xe7\u40e7rc;\u4109ps\u0100;s\u1a0c\u1a0d\u6a4cm;\u6a50ot;\u410b\u0180dmn\u1a1b\u1a20\u1a26il\u80bb\xb8\u01adptyv;\u69b2t\u8100\xa2;e\u1a2d\u1a2e\u40a2r\xe4\u01b2r;\uc000\ud835\udd20\u0180cei\u1a3d\u1a40\u1a4dy;\u4447ck\u0100;m\u1a47\u1a48\u6713ark\xbb\u1a48;\u43c7r\u0380;Ecefms\u1a5f\u1a60\u1a62\u1a6b\u1aa4\u1aaa\u1aae\u65cb;\u69c3\u0180;el\u1a69\u1a6a\u1a6d\u42c6q;\u6257e\u0261\u1a74\0\0\u1a88rrow\u0100lr\u1a7c\u1a81eft;\u61baight;\u61bb\u0280RSacd\u1a92\u1a94\u1a96\u1a9a\u1a9f\xbb\u0f47;\u64c8st;\u629birc;\u629aash;\u629dnint;\u6a10id;\u6aefcir;\u69c2ubs\u0100;u\u1abb\u1abc\u6663it\xbb\u1abc\u02ec\u1ac7\u1ad4\u1afa\0\u1b0aon\u0100;e\u1acd\u1ace\u403a\u0100;q\xc7\xc6\u026d\u1ad9\0\0\u1ae2a\u0100;t\u1ade\u1adf\u402c;\u4040\u0180;fl\u1ae8\u1ae9\u1aeb\u6201\xee\u1160e\u0100mx\u1af1\u1af6ent\xbb\u1ae9e\xf3\u024d\u01e7\u1afe\0\u1b07\u0100;d\u12bb\u1b02ot;\u6a6dn\xf4\u0246\u0180fry\u1b10\u1b14\u1b17;\uc000\ud835\udd54o\xe4\u0254\u8100\xa9;s\u0155\u1b1dr;\u6117\u0100ao\u1b25\u1b29rr;\u61b5ss;\u6717\u0100cu\u1b32\u1b37r;\uc000\ud835\udcb8\u0100bp\u1b3c\u1b44\u0100;e\u1b41\u1b42\u6acf;\u6ad1\u0100;e\u1b49\u1b4a\u6ad0;\u6ad2dot;\u62ef\u0380delprvw\u1b60\u1b6c\u1b77\u1b82\u1bac\u1bd4\u1bf9arr\u0100lr\u1b68\u1b6a;\u6938;\u6935\u0270\u1b72\0\0\u1b75r;\u62dec;\u62dfarr\u0100;p\u1b7f\u1b80\u61b6;\u693d\u0300;bcdos\u1b8f\u1b90\u1b96\u1ba1\u1ba5\u1ba8\u622arcap;\u6a48\u0100au\u1b9b\u1b9ep;\u6a46p;\u6a4aot;\u628dr;\u6a45;\uc000\u222a\ufe00\u0200alrv\u1bb5\u1bbf\u1bde\u1be3rr\u0100;m\u1bbc\u1bbd\u61b7;\u693cy\u0180evw\u1bc7\u1bd4\u1bd8q\u0270\u1bce\0\0\u1bd2re\xe3\u1b73u\xe3\u1b75ee;\u62ceedge;\u62cfen\u803b\xa4\u40a4earrow\u0100lr\u1bee\u1bf3eft\xbb\u1b80ight\xbb\u1bbde\xe4\u1bdd\u0100ci\u1c01\u1c07onin\xf4\u01f7nt;\u6231lcty;\u632d\u0980AHabcdefhijlorstuwz\u1c38\u1c3b\u1c3f\u1c5d\u1c69\u1c75\u1c8a\u1c9e\u1cac\u1cb7\u1cfb\u1cff\u1d0d\u1d7b\u1d91\u1dab\u1dbb\u1dc6\u1dcdr\xf2\u0381ar;\u6965\u0200glrs\u1c48\u1c4d\u1c52\u1c54ger;\u6020eth;\u6138\xf2\u1133h\u0100;v\u1c5a\u1c5b\u6010\xbb\u090a\u016b\u1c61\u1c67arow;\u690fa\xe3\u0315\u0100ay\u1c6e\u1c73ron;\u410f;\u4434\u0180;ao\u0332\u1c7c\u1c84\u0100gr\u02bf\u1c81r;\u61catseq;\u6a77\u0180glm\u1c91\u1c94\u1c98\u803b\xb0\u40b0ta;\u43b4ptyv;\u69b1\u0100ir\u1ca3\u1ca8sht;\u697f;\uc000\ud835\udd21ar\u0100lr\u1cb3\u1cb5\xbb\u08dc\xbb\u101e\u0280aegsv\u1cc2\u0378\u1cd6\u1cdc\u1ce0m\u0180;os\u0326\u1cca\u1cd4nd\u0100;s\u0326\u1cd1uit;\u6666amma;\u43ddin;\u62f2\u0180;io\u1ce7\u1ce8\u1cf8\u40f7de\u8100\xf7;o\u1ce7\u1cf0ntimes;\u62c7n\xf8\u1cf7cy;\u4452c\u026f\u1d06\0\0\u1d0arn;\u631eop;\u630d\u0280lptuw\u1d18\u1d1d\u1d22\u1d49\u1d55lar;\u4024f;\uc000\ud835\udd55\u0280;emps\u030b\u1d2d\u1d37\u1d3d\u1d42q\u0100;d\u0352\u1d33ot;\u6251inus;\u6238lus;\u6214quare;\u62a1blebarwedg\xe5\xfan\u0180adh\u112e\u1d5d\u1d67ownarrow\xf3\u1c83arpoon\u0100lr\u1d72\u1d76ef\xf4\u1cb4igh\xf4\u1cb6\u0162\u1d7f\u1d85karo\xf7\u0f42\u026f\u1d8a\0\0\u1d8ern;\u631fop;\u630c\u0180cot\u1d98\u1da3\u1da6\u0100ry\u1d9d\u1da1;\uc000\ud835\udcb9;\u4455l;\u69f6rok;\u4111\u0100dr\u1db0\u1db4ot;\u62f1i\u0100;f\u1dba\u1816\u65bf\u0100ah\u1dc0\u1dc3r\xf2\u0429a\xf2\u0fa6angle;\u69a6\u0100ci\u1dd2\u1dd5y;\u445fgrarr;\u67ff\u0900Dacdefglmnopqrstux\u1e01\u1e09\u1e19\u1e38\u0578\u1e3c\u1e49\u1e61\u1e7e\u1ea5\u1eaf\u1ebd\u1ee1\u1f2a\u1f37\u1f44\u1f4e\u1f5a\u0100Do\u1e06\u1d34o\xf4\u1c89\u0100cs\u1e0e\u1e14ute\u803b\xe9\u40e9ter;\u6a6e\u0200aioy\u1e22\u1e27\u1e31\u1e36ron;\u411br\u0100;c\u1e2d\u1e2e\u6256\u803b\xea\u40ealon;\u6255;\u444dot;\u4117\u0100Dr\u1e41\u1e45ot;\u6252;\uc000\ud835\udd22\u0180;rs\u1e50\u1e51\u1e57\u6a9aave\u803b\xe8\u40e8\u0100;d\u1e5c\u1e5d\u6a96ot;\u6a98\u0200;ils\u1e6a\u1e6b\u1e72\u1e74\u6a99nters;\u63e7;\u6113\u0100;d\u1e79\u1e7a\u6a95ot;\u6a97\u0180aps\u1e85\u1e89\u1e97cr;\u4113ty\u0180;sv\u1e92\u1e93\u1e95\u6205et\xbb\u1e93p\u01001;\u1e9d\u1ea4\u0133\u1ea1\u1ea3;\u6004;\u6005\u6003\u0100gs\u1eaa\u1eac;\u414bp;\u6002\u0100gp\u1eb4\u1eb8on;\u4119f;\uc000\ud835\udd56\u0180als\u1ec4\u1ece\u1ed2r\u0100;s\u1eca\u1ecb\u62d5l;\u69e3us;\u6a71i\u0180;lv\u1eda\u1edb\u1edf\u43b5on\xbb\u1edb;\u43f5\u0200csuv\u1eea\u1ef3\u1f0b\u1f23\u0100io\u1eef\u1e31rc\xbb\u1e2e\u0269\u1ef9\0\0\u1efb\xed\u0548ant\u0100gl\u1f02\u1f06tr\xbb\u1e5dess\xbb\u1e7a\u0180aei\u1f12\u1f16\u1f1als;\u403dst;\u625fv\u0100;D\u0235\u1f20D;\u6a78parsl;\u69e5\u0100Da\u1f2f\u1f33ot;\u6253rr;\u6971\u0180cdi\u1f3e\u1f41\u1ef8r;\u612fo\xf4\u0352\u0100ah\u1f49\u1f4b;\u43b7\u803b\xf0\u40f0\u0100mr\u1f53\u1f57l\u803b\xeb\u40ebo;\u60ac\u0180cip\u1f61\u1f64\u1f67l;\u4021s\xf4\u056e\u0100eo\u1f6c\u1f74ctatio\xee\u0559nential\xe5\u0579\u09e1\u1f92\0\u1f9e\0\u1fa1\u1fa7\0\0\u1fc6\u1fcc\0\u1fd3\0\u1fe6\u1fea\u2000\0\u2008\u205allingdotse\xf1\u1e44y;\u4444male;\u6640\u0180ilr\u1fad\u1fb3\u1fc1lig;\u8000\ufb03\u0269\u1fb9\0\0\u1fbdg;\u8000\ufb00ig;\u8000\ufb04;\uc000\ud835\udd23lig;\u8000\ufb01lig;\uc000fj\u0180alt\u1fd9\u1fdc\u1fe1t;\u666dig;\u8000\ufb02ns;\u65b1of;\u4192\u01f0\u1fee\0\u1ff3f;\uc000\ud835\udd57\u0100ak\u05bf\u1ff7\u0100;v\u1ffc\u1ffd\u62d4;\u6ad9artint;\u6a0d\u0100ao\u200c\u2055\u0100cs\u2011\u2052\u03b1\u201a\u2030\u2038\u2045\u2048\0\u2050\u03b2\u2022\u2025\u2027\u202a\u202c\0\u202e\u803b\xbd\u40bd;\u6153\u803b\xbc\u40bc;\u6155;\u6159;\u615b\u01b3\u2034\0\u2036;\u6154;\u6156\u02b4\u203e\u2041\0\0\u2043\u803b\xbe\u40be;\u6157;\u615c5;\u6158\u01b6\u204c\0\u204e;\u615a;\u615d8;\u615el;\u6044wn;\u6322cr;\uc000\ud835\udcbb\u0880Eabcdefgijlnorstv\u2082\u2089\u209f\u20a5\u20b0\u20b4\u20f0\u20f5\u20fa\u20ff\u2103\u2112\u2138\u0317\u213e\u2152\u219e\u0100;l\u064d\u2087;\u6a8c\u0180cmp\u2090\u2095\u209dute;\u41f5ma\u0100;d\u209c\u1cda\u43b3;\u6a86reve;\u411f\u0100iy\u20aa\u20aerc;\u411d;\u4433ot;\u4121\u0200;lqs\u063e\u0642\u20bd\u20c9\u0180;qs\u063e\u064c\u20c4lan\xf4\u0665\u0200;cdl\u0665\u20d2\u20d5\u20e5c;\u6aa9ot\u0100;o\u20dc\u20dd\u6a80\u0100;l\u20e2\u20e3\u6a82;\u6a84\u0100;e\u20ea\u20ed\uc000\u22db\ufe00s;\u6a94r;\uc000\ud835\udd24\u0100;g\u0673\u061bmel;\u6137cy;\u4453\u0200;Eaj\u065a\u210c\u210e\u2110;\u6a92;\u6aa5;\u6aa4\u0200Eaes\u211b\u211d\u2129\u2134;\u6269p\u0100;p\u2123\u2124\u6a8arox\xbb\u2124\u0100;q\u212e\u212f\u6a88\u0100;q\u212e\u211bim;\u62e7pf;\uc000\ud835\udd58\u0100ci\u2143\u2146r;\u610am\u0180;el\u066b\u214e\u2150;\u6a8e;\u6a90\u8300>;cdlqr\u05ee\u2160\u216a\u216e\u2173\u2179\u0100ci\u2165\u2167;\u6aa7r;\u6a7aot;\u62d7Par;\u6995uest;\u6a7c\u0280adels\u2184\u216a\u2190\u0656\u219b\u01f0\u2189\0\u218epro\xf8\u209er;\u6978q\u0100lq\u063f\u2196les\xf3\u2088i\xed\u066b\u0100en\u21a3\u21adrtneqq;\uc000\u2269\ufe00\xc5\u21aa\u0500Aabcefkosy\u21c4\u21c7\u21f1\u21f5\u21fa\u2218\u221d\u222f\u2268\u227dr\xf2\u03a0\u0200ilmr\u21d0\u21d4\u21d7\u21dbrs\xf0\u1484f\xbb\u2024il\xf4\u06a9\u0100dr\u21e0\u21e4cy;\u444a\u0180;cw\u08f4\u21eb\u21efir;\u6948;\u61adar;\u610firc;\u4125\u0180alr\u2201\u220e\u2213rts\u0100;u\u2209\u220a\u6665it\xbb\u220alip;\u6026con;\u62b9r;\uc000\ud835\udd25s\u0100ew\u2223\u2229arow;\u6925arow;\u6926\u0280amopr\u223a\u223e\u2243\u225e\u2263rr;\u61fftht;\u623bk\u0100lr\u2249\u2253eftarrow;\u61a9ightarrow;\u61aaf;\uc000\ud835\udd59bar;\u6015\u0180clt\u226f\u2274\u2278r;\uc000\ud835\udcbdas\xe8\u21f4rok;\u4127\u0100bp\u2282\u2287ull;\u6043hen\xbb\u1c5b\u0ae1\u22a3\0\u22aa\0\u22b8\u22c5\u22ce\0\u22d5\u22f3\0\0\u22f8\u2322\u2367\u2362\u237f\0\u2386\u23aa\u23b4cute\u803b\xed\u40ed\u0180;iy\u0771\u22b0\u22b5rc\u803b\xee\u40ee;\u4438\u0100cx\u22bc\u22bfy;\u4435cl\u803b\xa1\u40a1\u0100fr\u039f\u22c9;\uc000\ud835\udd26rave\u803b\xec\u40ec\u0200;ino\u073e\u22dd\u22e9\u22ee\u0100in\u22e2\u22e6nt;\u6a0ct;\u622dfin;\u69dcta;\u6129lig;\u4133\u0180aop\u22fe\u231a\u231d\u0180cgt\u2305\u2308\u2317r;\u412b\u0180elp\u071f\u230f\u2313in\xe5\u078ear\xf4\u0720h;\u4131f;\u62b7ed;\u41b5\u0280;cfot\u04f4\u232c\u2331\u233d\u2341are;\u6105in\u0100;t\u2338\u2339\u621eie;\u69dddo\xf4\u2319\u0280;celp\u0757\u234c\u2350\u235b\u2361al;\u62ba\u0100gr\u2355\u2359er\xf3\u1563\xe3\u234darhk;\u6a17rod;\u6a3c\u0200cgpt\u236f\u2372\u2376\u237by;\u4451on;\u412ff;\uc000\ud835\udd5aa;\u43b9uest\u803b\xbf\u40bf\u0100ci\u238a\u238fr;\uc000\ud835\udcben\u0280;Edsv\u04f4\u239b\u239d\u23a1\u04f3;\u62f9ot;\u62f5\u0100;v\u23a6\u23a7\u62f4;\u62f3\u0100;i\u0777\u23aelde;\u4129\u01eb\u23b8\0\u23bccy;\u4456l\u803b\xef\u40ef\u0300cfmosu\u23cc\u23d7\u23dc\u23e1\u23e7\u23f5\u0100iy\u23d1\u23d5rc;\u4135;\u4439r;\uc000\ud835\udd27ath;\u4237pf;\uc000\ud835\udd5b\u01e3\u23ec\0\u23f1r;\uc000\ud835\udcbfrcy;\u4458kcy;\u4454\u0400acfghjos\u240b\u2416\u2422\u2427\u242d\u2431\u2435\u243bppa\u0100;v\u2413\u2414\u43ba;\u43f0\u0100ey\u241b\u2420dil;\u4137;\u443ar;\uc000\ud835\udd28reen;\u4138cy;\u4445cy;\u445cpf;\uc000\ud835\udd5ccr;\uc000\ud835\udcc0\u0b80ABEHabcdefghjlmnoprstuv\u2470\u2481\u2486\u248d\u2491\u250e\u253d\u255a\u2580\u264e\u265e\u2665\u2679\u267d\u269a\u26b2\u26d8\u275d\u2768\u278b\u27c0\u2801\u2812\u0180art\u2477\u247a\u247cr\xf2\u09c6\xf2\u0395ail;\u691barr;\u690e\u0100;g\u0994\u248b;\u6a8bar;\u6962\u0963\u24a5\0\u24aa\0\u24b1\0\0\0\0\0\u24b5\u24ba\0\u24c6\u24c8\u24cd\0\u24f9ute;\u413amptyv;\u69b4ra\xee\u084cbda;\u43bbg\u0180;dl\u088e\u24c1\u24c3;\u6991\xe5\u088e;\u6a85uo\u803b\xab\u40abr\u0400;bfhlpst\u0899\u24de\u24e6\u24e9\u24eb\u24ee\u24f1\u24f5\u0100;f\u089d\u24e3s;\u691fs;\u691d\xeb\u2252p;\u61abl;\u6939im;\u6973l;\u61a2\u0180;ae\u24ff\u2500\u2504\u6aabil;\u6919\u0100;s\u2509\u250a\u6aad;\uc000\u2aad\ufe00\u0180abr\u2515\u2519\u251drr;\u690crk;\u6772\u0100ak\u2522\u252cc\u0100ek\u2528\u252a;\u407b;\u405b\u0100es\u2531\u2533;\u698bl\u0100du\u2539\u253b;\u698f;\u698d\u0200aeuy\u2546\u254b\u2556\u2558ron;\u413e\u0100di\u2550\u2554il;\u413c\xec\u08b0\xe2\u2529;\u443b\u0200cqrs\u2563\u2566\u256d\u257da;\u6936uo\u0100;r\u0e19\u1746\u0100du\u2572\u2577har;\u6967shar;\u694bh;\u61b2\u0280;fgqs\u258b\u258c\u0989\u25f3\u25ff\u6264t\u0280ahlrt\u2598\u25a4\u25b7\u25c2\u25e8rrow\u0100;t\u0899\u25a1a\xe9\u24f6arpoon\u0100du\u25af\u25b4own\xbb\u045ap\xbb\u0966eftarrows;\u61c7ight\u0180ahs\u25cd\u25d6\u25derrow\u0100;s\u08f4\u08a7arpoon\xf3\u0f98quigarro\xf7\u21f0hreetimes;\u62cb\u0180;qs\u258b\u0993\u25falan\xf4\u09ac\u0280;cdgs\u09ac\u260a\u260d\u261d\u2628c;\u6aa8ot\u0100;o\u2614\u2615\u6a7f\u0100;r\u261a\u261b\u6a81;\u6a83\u0100;e\u2622\u2625\uc000\u22da\ufe00s;\u6a93\u0280adegs\u2633\u2639\u263d\u2649\u264bppro\xf8\u24c6ot;\u62d6q\u0100gq\u2643\u2645\xf4\u0989gt\xf2\u248c\xf4\u099bi\xed\u09b2\u0180ilr\u2655\u08e1\u265asht;\u697c;\uc000\ud835\udd29\u0100;E\u099c\u2663;\u6a91\u0161\u2669\u2676r\u0100du\u25b2\u266e\u0100;l\u0965\u2673;\u696alk;\u6584cy;\u4459\u0280;acht\u0a48\u2688\u268b\u2691\u2696r\xf2\u25c1orne\xf2\u1d08ard;\u696bri;\u65fa\u0100io\u269f\u26a4dot;\u4140ust\u0100;a\u26ac\u26ad\u63b0che\xbb\u26ad\u0200Eaes\u26bb\u26bd\u26c9\u26d4;\u6268p\u0100;p\u26c3\u26c4\u6a89rox\xbb\u26c4\u0100;q\u26ce\u26cf\u6a87\u0100;q\u26ce\u26bbim;\u62e6\u0400abnoptwz\u26e9\u26f4\u26f7\u271a\u272f\u2741\u2747\u2750\u0100nr\u26ee\u26f1g;\u67ecr;\u61fdr\xeb\u08c1g\u0180lmr\u26ff\u270d\u2714eft\u0100ar\u09e6\u2707ight\xe1\u09f2apsto;\u67fcight\xe1\u09fdparrow\u0100lr\u2725\u2729ef\xf4\u24edight;\u61ac\u0180afl\u2736\u2739\u273dr;\u6985;\uc000\ud835\udd5dus;\u6a2dimes;\u6a34\u0161\u274b\u274fst;\u6217\xe1\u134e\u0180;ef\u2757\u2758\u1800\u65cange\xbb\u2758ar\u0100;l\u2764\u2765\u4028t;\u6993\u0280achmt\u2773\u2776\u277c\u2785\u2787r\xf2\u08a8orne\xf2\u1d8car\u0100;d\u0f98\u2783;\u696d;\u600eri;\u62bf\u0300achiqt\u2798\u279d\u0a40\u27a2\u27ae\u27bbquo;\u6039r;\uc000\ud835\udcc1m\u0180;eg\u09b2\u27aa\u27ac;\u6a8d;\u6a8f\u0100bu\u252a\u27b3o\u0100;r\u0e1f\u27b9;\u601arok;\u4142\u8400<;cdhilqr\u082b\u27d2\u2639\u27dc\u27e0\u27e5\u27ea\u27f0\u0100ci\u27d7\u27d9;\u6aa6r;\u6a79re\xe5\u25f2mes;\u62c9arr;\u6976uest;\u6a7b\u0100Pi\u27f5\u27f9ar;\u6996\u0180;ef\u2800\u092d\u181b\u65c3r\u0100du\u2807\u280dshar;\u694ahar;\u6966\u0100en\u2817\u2821rtneqq;\uc000\u2268\ufe00\xc5\u281e\u0700Dacdefhilnopsu\u2840\u2845\u2882\u288e\u2893\u28a0\u28a5\u28a8\u28da\u28e2\u28e4\u0a83\u28f3\u2902Dot;\u623a\u0200clpr\u284e\u2852\u2863\u287dr\u803b\xaf\u40af\u0100et\u2857\u2859;\u6642\u0100;e\u285e\u285f\u6720se\xbb\u285f\u0100;s\u103b\u2868to\u0200;dlu\u103b\u2873\u2877\u287bow\xee\u048cef\xf4\u090f\xf0\u13d1ker;\u65ae\u0100oy\u2887\u288cmma;\u6a29;\u443cash;\u6014asuredangle\xbb\u1626r;\uc000\ud835\udd2ao;\u6127\u0180cdn\u28af\u28b4\u28c9ro\u803b\xb5\u40b5\u0200;acd\u1464\u28bd\u28c0\u28c4s\xf4\u16a7ir;\u6af0ot\u80bb\xb7\u01b5us\u0180;bd\u28d2\u1903\u28d3\u6212\u0100;u\u1d3c\u28d8;\u6a2a\u0163\u28de\u28e1p;\u6adb\xf2\u2212\xf0\u0a81\u0100dp\u28e9\u28eeels;\u62a7f;\uc000\ud835\udd5e\u0100ct\u28f8\u28fdr;\uc000\ud835\udcc2pos\xbb\u159d\u0180;lm\u2909\u290a\u290d\u43bctimap;\u62b8\u0c00GLRVabcdefghijlmoprstuvw\u2942\u2953\u297e\u2989\u2998\u29da\u29e9\u2a15\u2a1a\u2a58\u2a5d\u2a83\u2a95\u2aa4\u2aa8\u2b04\u2b07\u2b44\u2b7f\u2bae\u2c34\u2c67\u2c7c\u2ce9\u0100gt\u2947\u294b;\uc000\u22d9\u0338\u0100;v\u2950\u0bcf\uc000\u226b\u20d2\u0180elt\u295a\u2972\u2976ft\u0100ar\u2961\u2967rrow;\u61cdightarrow;\u61ce;\uc000\u22d8\u0338\u0100;v\u297b\u0c47\uc000\u226a\u20d2ightarrow;\u61cf\u0100Dd\u298e\u2993ash;\u62afash;\u62ae\u0280bcnpt\u29a3\u29a7\u29ac\u29b1\u29ccla\xbb\u02deute;\u4144g;\uc000\u2220\u20d2\u0280;Eiop\u0d84\u29bc\u29c0\u29c5\u29c8;\uc000\u2a70\u0338d;\uc000\u224b\u0338s;\u4149ro\xf8\u0d84ur\u0100;a\u29d3\u29d4\u666el\u0100;s\u29d3\u0b38\u01f3\u29df\0\u29e3p\u80bb\xa0\u0b37mp\u0100;e\u0bf9\u0c00\u0280aeouy\u29f4\u29fe\u2a03\u2a10\u2a13\u01f0\u29f9\0\u29fb;\u6a43on;\u4148dil;\u4146ng\u0100;d\u0d7e\u2a0aot;\uc000\u2a6d\u0338p;\u6a42;\u443dash;\u6013\u0380;Aadqsx\u0b92\u2a29\u2a2d\u2a3b\u2a41\u2a45\u2a50rr;\u61d7r\u0100hr\u2a33\u2a36k;\u6924\u0100;o\u13f2\u13f0ot;\uc000\u2250\u0338ui\xf6\u0b63\u0100ei\u2a4a\u2a4ear;\u6928\xed\u0b98ist\u0100;s\u0ba0\u0b9fr;\uc000\ud835\udd2b\u0200Eest\u0bc5\u2a66\u2a79\u2a7c\u0180;qs\u0bbc\u2a6d\u0be1\u0180;qs\u0bbc\u0bc5\u2a74lan\xf4\u0be2i\xed\u0bea\u0100;r\u0bb6\u2a81\xbb\u0bb7\u0180Aap\u2a8a\u2a8d\u2a91r\xf2\u2971rr;\u61aear;\u6af2\u0180;sv\u0f8d\u2a9c\u0f8c\u0100;d\u2aa1\u2aa2\u62fc;\u62facy;\u445a\u0380AEadest\u2ab7\u2aba\u2abe\u2ac2\u2ac5\u2af6\u2af9r\xf2\u2966;\uc000\u2266\u0338rr;\u619ar;\u6025\u0200;fqs\u0c3b\u2ace\u2ae3\u2aeft\u0100ar\u2ad4\u2ad9rro\xf7\u2ac1ightarro\xf7\u2a90\u0180;qs\u0c3b\u2aba\u2aealan\xf4\u0c55\u0100;s\u0c55\u2af4\xbb\u0c36i\xed\u0c5d\u0100;r\u0c35\u2afei\u0100;e\u0c1a\u0c25i\xe4\u0d90\u0100pt\u2b0c\u2b11f;\uc000\ud835\udd5f\u8180\xac;in\u2b19\u2b1a\u2b36\u40acn\u0200;Edv\u0b89\u2b24\u2b28\u2b2e;\uc000\u22f9\u0338ot;\uc000\u22f5\u0338\u01e1\u0b89\u2b33\u2b35;\u62f7;\u62f6i\u0100;v\u0cb8\u2b3c\u01e1\u0cb8\u2b41\u2b43;\u62fe;\u62fd\u0180aor\u2b4b\u2b63\u2b69r\u0200;ast\u0b7b\u2b55\u2b5a\u2b5flle\xec\u0b7bl;\uc000\u2afd\u20e5;\uc000\u2202\u0338lint;\u6a14\u0180;ce\u0c92\u2b70\u2b73u\xe5\u0ca5\u0100;c\u0c98\u2b78\u0100;e\u0c92\u2b7d\xf1\u0c98\u0200Aait\u2b88\u2b8b\u2b9d\u2ba7r\xf2\u2988rr\u0180;cw\u2b94\u2b95\u2b99\u619b;\uc000\u2933\u0338;\uc000\u219d\u0338ghtarrow\xbb\u2b95ri\u0100;e\u0ccb\u0cd6\u0380chimpqu\u2bbd\u2bcd\u2bd9\u2b04\u0b78\u2be4\u2bef\u0200;cer\u0d32\u2bc6\u0d37\u2bc9u\xe5\u0d45;\uc000\ud835\udcc3ort\u026d\u2b05\0\0\u2bd6ar\xe1\u2b56m\u0100;e\u0d6e\u2bdf\u0100;q\u0d74\u0d73su\u0100bp\u2beb\u2bed\xe5\u0cf8\xe5\u0d0b\u0180bcp\u2bf6\u2c11\u2c19\u0200;Ees\u2bff\u2c00\u0d22\u2c04\u6284;\uc000\u2ac5\u0338et\u0100;e\u0d1b\u2c0bq\u0100;q\u0d23\u2c00c\u0100;e\u0d32\u2c17\xf1\u0d38\u0200;Ees\u2c22\u2c23\u0d5f\u2c27\u6285;\uc000\u2ac6\u0338et\u0100;e\u0d58\u2c2eq\u0100;q\u0d60\u2c23\u0200gilr\u2c3d\u2c3f\u2c45\u2c47\xec\u0bd7lde\u803b\xf1\u40f1\xe7\u0c43iangle\u0100lr\u2c52\u2c5ceft\u0100;e\u0c1a\u2c5a\xf1\u0c26ight\u0100;e\u0ccb\u2c65\xf1\u0cd7\u0100;m\u2c6c\u2c6d\u43bd\u0180;es\u2c74\u2c75\u2c79\u4023ro;\u6116p;\u6007\u0480DHadgilrs\u2c8f\u2c94\u2c99\u2c9e\u2ca3\u2cb0\u2cb6\u2cd3\u2ce3ash;\u62adarr;\u6904p;\uc000\u224d\u20d2ash;\u62ac\u0100et\u2ca8\u2cac;\uc000\u2265\u20d2;\uc000>\u20d2nfin;\u69de\u0180Aet\u2cbd\u2cc1\u2cc5rr;\u6902;\uc000\u2264\u20d2\u0100;r\u2cca\u2ccd\uc000<\u20d2ie;\uc000\u22b4\u20d2\u0100At\u2cd8\u2cdcrr;\u6903rie;\uc000\u22b5\u20d2im;\uc000\u223c\u20d2\u0180Aan\u2cf0\u2cf4\u2d02rr;\u61d6r\u0100hr\u2cfa\u2cfdk;\u6923\u0100;o\u13e7\u13e5ear;\u6927\u1253\u1a95\0\0\0\0\0\0\0\0\0\0\0\0\0\u2d2d\0\u2d38\u2d48\u2d60\u2d65\u2d72\u2d84\u1b07\0\0\u2d8d\u2dab\0\u2dc8\u2dce\0\u2ddc\u2e19\u2e2b\u2e3e\u2e43\u0100cs\u2d31\u1a97ute\u803b\xf3\u40f3\u0100iy\u2d3c\u2d45r\u0100;c\u1a9e\u2d42\u803b\xf4\u40f4;\u443e\u0280abios\u1aa0\u2d52\u2d57\u01c8\u2d5alac;\u4151v;\u6a38old;\u69bclig;\u4153\u0100cr\u2d69\u2d6dir;\u69bf;\uc000\ud835\udd2c\u036f\u2d79\0\0\u2d7c\0\u2d82n;\u42dbave\u803b\xf2\u40f2;\u69c1\u0100bm\u2d88\u0df4ar;\u69b5\u0200acit\u2d95\u2d98\u2da5\u2da8r\xf2\u1a80\u0100ir\u2d9d\u2da0r;\u69beoss;\u69bbn\xe5\u0e52;\u69c0\u0180aei\u2db1\u2db5\u2db9cr;\u414dga;\u43c9\u0180cdn\u2dc0\u2dc5\u01cdron;\u43bf;\u69b6pf;\uc000\ud835\udd60\u0180ael\u2dd4\u2dd7\u01d2r;\u69b7rp;\u69b9\u0380;adiosv\u2dea\u2deb\u2dee\u2e08\u2e0d\u2e10\u2e16\u6228r\xf2\u1a86\u0200;efm\u2df7\u2df8\u2e02\u2e05\u6a5dr\u0100;o\u2dfe\u2dff\u6134f\xbb\u2dff\u803b\xaa\u40aa\u803b\xba\u40bagof;\u62b6r;\u6a56lope;\u6a57;\u6a5b\u0180clo\u2e1f\u2e21\u2e27\xf2\u2e01ash\u803b\xf8\u40f8l;\u6298i\u016c\u2e2f\u2e34de\u803b\xf5\u40f5es\u0100;a\u01db\u2e3as;\u6a36ml\u803b\xf6\u40f6bar;\u633d\u0ae1\u2e5e\0\u2e7d\0\u2e80\u2e9d\0\u2ea2\u2eb9\0\0\u2ecb\u0e9c\0\u2f13\0\0\u2f2b\u2fbc\0\u2fc8r\u0200;ast\u0403\u2e67\u2e72\u0e85\u8100\xb6;l\u2e6d\u2e6e\u40b6le\xec\u0403\u0269\u2e78\0\0\u2e7bm;\u6af3;\u6afdy;\u443fr\u0280cimpt\u2e8b\u2e8f\u2e93\u1865\u2e97nt;\u4025od;\u402eil;\u6030enk;\u6031r;\uc000\ud835\udd2d\u0180imo\u2ea8\u2eb0\u2eb4\u0100;v\u2ead\u2eae\u43c6;\u43d5ma\xf4\u0a76ne;\u660e\u0180;tv\u2ebf\u2ec0\u2ec8\u43c0chfork\xbb\u1ffd;\u43d6\u0100au\u2ecf\u2edfn\u0100ck\u2ed5\u2eddk\u0100;h\u21f4\u2edb;\u610e\xf6\u21f4s\u0480;abcdemst\u2ef3\u2ef4\u1908\u2ef9\u2efd\u2f04\u2f06\u2f0a\u2f0e\u402bcir;\u6a23ir;\u6a22\u0100ou\u1d40\u2f02;\u6a25;\u6a72n\u80bb\xb1\u0e9dim;\u6a26wo;\u6a27\u0180ipu\u2f19\u2f20\u2f25ntint;\u6a15f;\uc000\ud835\udd61nd\u803b\xa3\u40a3\u0500;Eaceinosu\u0ec8\u2f3f\u2f41\u2f44\u2f47\u2f81\u2f89\u2f92\u2f7e\u2fb6;\u6ab3p;\u6ab7u\xe5\u0ed9\u0100;c\u0ece\u2f4c\u0300;acens\u0ec8\u2f59\u2f5f\u2f66\u2f68\u2f7eppro\xf8\u2f43urlye\xf1\u0ed9\xf1\u0ece\u0180aes\u2f6f\u2f76\u2f7approx;\u6ab9qq;\u6ab5im;\u62e8i\xed\u0edfme\u0100;s\u2f88\u0eae\u6032\u0180Eas\u2f78\u2f90\u2f7a\xf0\u2f75\u0180dfp\u0eec\u2f99\u2faf\u0180als\u2fa0\u2fa5\u2faalar;\u632eine;\u6312urf;\u6313\u0100;t\u0efb\u2fb4\xef\u0efbrel;\u62b0\u0100ci\u2fc0\u2fc5r;\uc000\ud835\udcc5;\u43c8ncsp;\u6008\u0300fiopsu\u2fda\u22e2\u2fdf\u2fe5\u2feb\u2ff1r;\uc000\ud835\udd2epf;\uc000\ud835\udd62rime;\u6057cr;\uc000\ud835\udcc6\u0180aeo\u2ff8\u3009\u3013t\u0100ei\u2ffe\u3005rnion\xf3\u06b0nt;\u6a16st\u0100;e\u3010\u3011\u403f\xf1\u1f19\xf4\u0f14\u0a80ABHabcdefhilmnoprstux\u3040\u3051\u3055\u3059\u30e0\u310e\u312b\u3147\u3162\u3172\u318e\u3206\u3215\u3224\u3229\u3258\u326e\u3272\u3290\u32b0\u32b7\u0180art\u3047\u304a\u304cr\xf2\u10b3\xf2\u03ddail;\u691car\xf2\u1c65ar;\u6964\u0380cdenqrt\u3068\u3075\u3078\u307f\u308f\u3094\u30cc\u0100eu\u306d\u3071;\uc000\u223d\u0331te;\u4155i\xe3\u116emptyv;\u69b3g\u0200;del\u0fd1\u3089\u308b\u308d;\u6992;\u69a5\xe5\u0fd1uo\u803b\xbb\u40bbr\u0580;abcfhlpstw\u0fdc\u30ac\u30af\u30b7\u30b9\u30bc\u30be\u30c0\u30c3\u30c7\u30cap;\u6975\u0100;f\u0fe0\u30b4s;\u6920;\u6933s;\u691e\xeb\u225d\xf0\u272el;\u6945im;\u6974l;\u61a3;\u619d\u0100ai\u30d1\u30d5il;\u691ao\u0100;n\u30db\u30dc\u6236al\xf3\u0f1e\u0180abr\u30e7\u30ea\u30eer\xf2\u17e5rk;\u6773\u0100ak\u30f3\u30fdc\u0100ek\u30f9\u30fb;\u407d;\u405d\u0100es\u3102\u3104;\u698cl\u0100du\u310a\u310c;\u698e;\u6990\u0200aeuy\u3117\u311c\u3127\u3129ron;\u4159\u0100di\u3121\u3125il;\u4157\xec\u0ff2\xe2\u30fa;\u4440\u0200clqs\u3134\u3137\u313d\u3144a;\u6937dhar;\u6969uo\u0100;r\u020e\u020dh;\u61b3\u0180acg\u314e\u315f\u0f44l\u0200;ips\u0f78\u3158\u315b\u109cn\xe5\u10bbar\xf4\u0fa9t;\u65ad\u0180ilr\u3169\u1023\u316esht;\u697d;\uc000\ud835\udd2f\u0100ao\u3177\u3186r\u0100du\u317d\u317f\xbb\u047b\u0100;l\u1091\u3184;\u696c\u0100;v\u318b\u318c\u43c1;\u43f1\u0180gns\u3195\u31f9\u31fcht\u0300ahlrst\u31a4\u31b0\u31c2\u31d8\u31e4\u31eerrow\u0100;t\u0fdc\u31ada\xe9\u30c8arpoon\u0100du\u31bb\u31bfow\xee\u317ep\xbb\u1092eft\u0100ah\u31ca\u31d0rrow\xf3\u0feaarpoon\xf3\u0551ightarrows;\u61c9quigarro\xf7\u30cbhreetimes;\u62ccg;\u42daingdotse\xf1\u1f32\u0180ahm\u320d\u3210\u3213r\xf2\u0feaa\xf2\u0551;\u600foust\u0100;a\u321e\u321f\u63b1che\xbb\u321fmid;\u6aee\u0200abpt\u3232\u323d\u3240\u3252\u0100nr\u3237\u323ag;\u67edr;\u61fer\xeb\u1003\u0180afl\u3247\u324a\u324er;\u6986;\uc000\ud835\udd63us;\u6a2eimes;\u6a35\u0100ap\u325d\u3267r\u0100;g\u3263\u3264\u4029t;\u6994olint;\u6a12ar\xf2\u31e3\u0200achq\u327b\u3280\u10bc\u3285quo;\u603ar;\uc000\ud835\udcc7\u0100bu\u30fb\u328ao\u0100;r\u0214\u0213\u0180hir\u3297\u329b\u32a0re\xe5\u31f8mes;\u62cai\u0200;efl\u32aa\u1059\u1821\u32ab\u65b9tri;\u69celuhar;\u6968;\u611e\u0d61\u32d5\u32db\u32df\u332c\u3338\u3371\0\u337a\u33a4\0\0\u33ec\u33f0\0\u3428\u3448\u345a\u34ad\u34b1\u34ca\u34f1\0\u3616\0\0\u3633cute;\u415bqu\xef\u27ba\u0500;Eaceinpsy\u11ed\u32f3\u32f5\u32ff\u3302\u330b\u330f\u331f\u3326\u3329;\u6ab4\u01f0\u32fa\0\u32fc;\u6ab8on;\u4161u\xe5\u11fe\u0100;d\u11f3\u3307il;\u415frc;\u415d\u0180Eas\u3316\u3318\u331b;\u6ab6p;\u6abaim;\u62e9olint;\u6a13i\xed\u1204;\u4441ot\u0180;be\u3334\u1d47\u3335\u62c5;\u6a66\u0380Aacmstx\u3346\u334a\u3357\u335b\u335e\u3363\u336drr;\u61d8r\u0100hr\u3350\u3352\xeb\u2228\u0100;o\u0a36\u0a34t\u803b\xa7\u40a7i;\u403bwar;\u6929m\u0100in\u3369\xf0nu\xf3\xf1t;\u6736r\u0100;o\u3376\u2055\uc000\ud835\udd30\u0200acoy\u3382\u3386\u3391\u33a0rp;\u666f\u0100hy\u338b\u338fcy;\u4449;\u4448rt\u026d\u3399\0\0\u339ci\xe4\u1464ara\xec\u2e6f\u803b\xad\u40ad\u0100gm\u33a8\u33b4ma\u0180;fv\u33b1\u33b2\u33b2\u43c3;\u43c2\u0400;deglnpr\u12ab\u33c5\u33c9\u33ce\u33d6\u33de\u33e1\u33e6ot;\u6a6a\u0100;q\u12b1\u12b0\u0100;E\u33d3\u33d4\u6a9e;\u6aa0\u0100;E\u33db\u33dc\u6a9d;\u6a9fe;\u6246lus;\u6a24arr;\u6972ar\xf2\u113d\u0200aeit\u33f8\u3408\u340f\u3417\u0100ls\u33fd\u3404lsetm\xe9\u336ahp;\u6a33parsl;\u69e4\u0100dl\u1463\u3414e;\u6323\u0100;e\u341c\u341d\u6aaa\u0100;s\u3422\u3423\u6aac;\uc000\u2aac\ufe00\u0180flp\u342e\u3433\u3442tcy;\u444c\u0100;b\u3438\u3439\u402f\u0100;a\u343e\u343f\u69c4r;\u633ff;\uc000\ud835\udd64a\u0100dr\u344d\u0402es\u0100;u\u3454\u3455\u6660it\xbb\u3455\u0180csu\u3460\u3479\u349f\u0100au\u3465\u346fp\u0100;s\u1188\u346b;\uc000\u2293\ufe00p\u0100;s\u11b4\u3475;\uc000\u2294\ufe00u\u0100bp\u347f\u348f\u0180;es\u1197\u119c\u3486et\u0100;e\u1197\u348d\xf1\u119d\u0180;es\u11a8\u11ad\u3496et\u0100;e\u11a8\u349d\xf1\u11ae\u0180;af\u117b\u34a6\u05b0r\u0165\u34ab\u05b1\xbb\u117car\xf2\u1148\u0200cemt\u34b9\u34be\u34c2\u34c5r;\uc000\ud835\udcc8tm\xee\xf1i\xec\u3415ar\xe6\u11be\u0100ar\u34ce\u34d5r\u0100;f\u34d4\u17bf\u6606\u0100an\u34da\u34edight\u0100ep\u34e3\u34eapsilo\xee\u1ee0h\xe9\u2eafs\xbb\u2852\u0280bcmnp\u34fb\u355e\u1209\u358b\u358e\u0480;Edemnprs\u350e\u350f\u3511\u3515\u351e\u3523\u352c\u3531\u3536\u6282;\u6ac5ot;\u6abd\u0100;d\u11da\u351aot;\u6ac3ult;\u6ac1\u0100Ee\u3528\u352a;\u6acb;\u628alus;\u6abfarr;\u6979\u0180eiu\u353d\u3552\u3555t\u0180;en\u350e\u3545\u354bq\u0100;q\u11da\u350feq\u0100;q\u352b\u3528m;\u6ac7\u0100bp\u355a\u355c;\u6ad5;\u6ad3c\u0300;acens\u11ed\u356c\u3572\u3579\u357b\u3326ppro\xf8\u32faurlye\xf1\u11fe\xf1\u11f3\u0180aes\u3582\u3588\u331bppro\xf8\u331aq\xf1\u3317g;\u666a\u0680123;Edehlmnps\u35a9\u35ac\u35af\u121c\u35b2\u35b4\u35c0\u35c9\u35d5\u35da\u35df\u35e8\u35ed\u803b\xb9\u40b9\u803b\xb2\u40b2\u803b\xb3\u40b3;\u6ac6\u0100os\u35b9\u35bct;\u6abeub;\u6ad8\u0100;d\u1222\u35c5ot;\u6ac4s\u0100ou\u35cf\u35d2l;\u67c9b;\u6ad7arr;\u697bult;\u6ac2\u0100Ee\u35e4\u35e6;\u6acc;\u628blus;\u6ac0\u0180eiu\u35f4\u3609\u360ct\u0180;en\u121c\u35fc\u3602q\u0100;q\u1222\u35b2eq\u0100;q\u35e7\u35e4m;\u6ac8\u0100bp\u3611\u3613;\u6ad4;\u6ad6\u0180Aan\u361c\u3620\u362drr;\u61d9r\u0100hr\u3626\u3628\xeb\u222e\u0100;o\u0a2b\u0a29war;\u692alig\u803b\xdf\u40df\u0be1\u3651\u365d\u3660\u12ce\u3673\u3679\0\u367e\u36c2\0\0\0\0\0\u36db\u3703\0\u3709\u376c\0\0\0\u3787\u0272\u3656\0\0\u365bget;\u6316;\u43c4r\xeb\u0e5f\u0180aey\u3666\u366b\u3670ron;\u4165dil;\u4163;\u4442lrec;\u6315r;\uc000\ud835\udd31\u0200eiko\u3686\u369d\u36b5\u36bc\u01f2\u368b\0\u3691e\u01004f\u1284\u1281a\u0180;sv\u3698\u3699\u369b\u43b8ym;\u43d1\u0100cn\u36a2\u36b2k\u0100as\u36a8\u36aeppro\xf8\u12c1im\xbb\u12acs\xf0\u129e\u0100as\u36ba\u36ae\xf0\u12c1rn\u803b\xfe\u40fe\u01ec\u031f\u36c6\u22e7es\u8180\xd7;bd\u36cf\u36d0\u36d8\u40d7\u0100;a\u190f\u36d5r;\u6a31;\u6a30\u0180eps\u36e1\u36e3\u3700\xe1\u2a4d\u0200;bcf\u0486\u36ec\u36f0\u36f4ot;\u6336ir;\u6af1\u0100;o\u36f9\u36fc\uc000\ud835\udd65rk;\u6ada\xe1\u3362rime;\u6034\u0180aip\u370f\u3712\u3764d\xe5\u1248\u0380adempst\u3721\u374d\u3740\u3751\u3757\u375c\u375fngle\u0280;dlqr\u3730\u3731\u3736\u3740\u3742\u65b5own\xbb\u1dbbeft\u0100;e\u2800\u373e\xf1\u092e;\u625cight\u0100;e\u32aa\u374b\xf1\u105aot;\u65ecinus;\u6a3alus;\u6a39b;\u69cdime;\u6a3bezium;\u63e2\u0180cht\u3772\u377d\u3781\u0100ry\u3777\u377b;\uc000\ud835\udcc9;\u4446cy;\u445brok;\u4167\u0100io\u378b\u378ex\xf4\u1777head\u0100lr\u3797\u37a0eftarro\xf7\u084fightarrow\xbb\u0f5d\u0900AHabcdfghlmoprstuw\u37d0\u37d3\u37d7\u37e4\u37f0\u37fc\u380e\u381c\u3823\u3834\u3851\u385d\u386b\u38a9\u38cc\u38d2\u38ea\u38f6r\xf2\u03edar;\u6963\u0100cr\u37dc\u37e2ute\u803b\xfa\u40fa\xf2\u1150r\u01e3\u37ea\0\u37edy;\u445eve;\u416d\u0100iy\u37f5\u37farc\u803b\xfb\u40fb;\u4443\u0180abh\u3803\u3806\u380br\xf2\u13adlac;\u4171a\xf2\u13c3\u0100ir\u3813\u3818sht;\u697e;\uc000\ud835\udd32rave\u803b\xf9\u40f9\u0161\u3827\u3831r\u0100lr\u382c\u382e\xbb\u0957\xbb\u1083lk;\u6580\u0100ct\u3839\u384d\u026f\u383f\0\0\u384arn\u0100;e\u3845\u3846\u631cr\xbb\u3846op;\u630fri;\u65f8\u0100al\u3856\u385acr;\u416b\u80bb\xa8\u0349\u0100gp\u3862\u3866on;\u4173f;\uc000\ud835\udd66\u0300adhlsu\u114b\u3878\u387d\u1372\u3891\u38a0own\xe1\u13b3arpoon\u0100lr\u3888\u388cef\xf4\u382digh\xf4\u382fi\u0180;hl\u3899\u389a\u389c\u43c5\xbb\u13faon\xbb\u389aparrows;\u61c8\u0180cit\u38b0\u38c4\u38c8\u026f\u38b6\0\0\u38c1rn\u0100;e\u38bc\u38bd\u631dr\xbb\u38bdop;\u630eng;\u416fri;\u65f9cr;\uc000\ud835\udcca\u0180dir\u38d9\u38dd\u38e2ot;\u62f0lde;\u4169i\u0100;f\u3730\u38e8\xbb\u1813\u0100am\u38ef\u38f2r\xf2\u38a8l\u803b\xfc\u40fcangle;\u69a7\u0780ABDacdeflnoprsz\u391c\u391f\u3929\u392d\u39b5\u39b8\u39bd\u39df\u39e4\u39e8\u39f3\u39f9\u39fd\u3a01\u3a20r\xf2\u03f7ar\u0100;v\u3926\u3927\u6ae8;\u6ae9as\xe8\u03e1\u0100nr\u3932\u3937grt;\u699c\u0380eknprst\u34e3\u3946\u394b\u3952\u395d\u3964\u3996app\xe1\u2415othin\xe7\u1e96\u0180hir\u34eb\u2ec8\u3959op\xf4\u2fb5\u0100;h\u13b7\u3962\xef\u318d\u0100iu\u3969\u396dgm\xe1\u33b3\u0100bp\u3972\u3984setneq\u0100;q\u397d\u3980\uc000\u228a\ufe00;\uc000\u2acb\ufe00setneq\u0100;q\u398f\u3992\uc000\u228b\ufe00;\uc000\u2acc\ufe00\u0100hr\u399b\u399fet\xe1\u369ciangle\u0100lr\u39aa\u39afeft\xbb\u0925ight\xbb\u1051y;\u4432ash\xbb\u1036\u0180elr\u39c4\u39d2\u39d7\u0180;be\u2dea\u39cb\u39cfar;\u62bbq;\u625alip;\u62ee\u0100bt\u39dc\u1468a\xf2\u1469r;\uc000\ud835\udd33tr\xe9\u39aesu\u0100bp\u39ef\u39f1\xbb\u0d1c\xbb\u0d59pf;\uc000\ud835\udd67ro\xf0\u0efbtr\xe9\u39b4\u0100cu\u3a06\u3a0br;\uc000\ud835\udccb\u0100bp\u3a10\u3a18n\u0100Ee\u3980\u3a16\xbb\u397en\u0100Ee\u3992\u3a1e\xbb\u3990igzag;\u699a\u0380cefoprs\u3a36\u3a3b\u3a56\u3a5b\u3a54\u3a61\u3a6airc;\u4175\u0100di\u3a40\u3a51\u0100bg\u3a45\u3a49ar;\u6a5fe\u0100;q\u15fa\u3a4f;\u6259erp;\u6118r;\uc000\ud835\udd34pf;\uc000\ud835\udd68\u0100;e\u1479\u3a66at\xe8\u1479cr;\uc000\ud835\udccc\u0ae3\u178e\u3a87\0\u3a8b\0\u3a90\u3a9b\0\0\u3a9d\u3aa8\u3aab\u3aaf\0\0\u3ac3\u3ace\0\u3ad8\u17dc\u17dftr\xe9\u17d1r;\uc000\ud835\udd35\u0100Aa\u3a94\u3a97r\xf2\u03c3r\xf2\u09f6;\u43be\u0100Aa\u3aa1\u3aa4r\xf2\u03b8r\xf2\u09eba\xf0\u2713is;\u62fb\u0180dpt\u17a4\u3ab5\u3abe\u0100fl\u3aba\u17a9;\uc000\ud835\udd69im\xe5\u17b2\u0100Aa\u3ac7\u3acar\xf2\u03cer\xf2\u0a01\u0100cq\u3ad2\u17b8r;\uc000\ud835\udccd\u0100pt\u17d6\u3adcr\xe9\u17d4\u0400acefiosu\u3af0\u3afd\u3b08\u3b0c\u3b11\u3b15\u3b1b\u3b21c\u0100uy\u3af6\u3afbte\u803b\xfd\u40fd;\u444f\u0100iy\u3b02\u3b06rc;\u4177;\u444bn\u803b\xa5\u40a5r;\uc000\ud835\udd36cy;\u4457pf;\uc000\ud835\udd6acr;\uc000\ud835\udcce\u0100cm\u3b26\u3b29y;\u444el\u803b\xff\u40ff\u0500acdefhiosw\u3b42\u3b48\u3b54\u3b58\u3b64\u3b69\u3b6d\u3b74\u3b7a\u3b80cute;\u417a\u0100ay\u3b4d\u3b52ron;\u417e;\u4437ot;\u417c\u0100et\u3b5d\u3b61tr\xe6\u155fa;\u43b6r;\uc000\ud835\udd37cy;\u4436grarr;\u61ddpf;\uc000\ud835\udd6bcr;\uc000\ud835\udccf\u0100jn\u3b85\u3b87;\u600dj;\u600c"
.split("")
.map(function (c) { return c.charCodeAt(0); }));
var decodeDataXml = {};
// Generated using scripts/write-decode-map.ts
Object.defineProperty(decodeDataXml, "__esModule", { value: true });
decodeDataXml.default = new Uint16Array(
// prettier-ignore
"\u0200aglq\t\x15\x18\x1b\u026d\x0f\0\0\x12p;\u4026os;\u4027t;\u403et;\u403cuot;\u4022"
.split("")
.map(function (c) { return c.charCodeAt(0); }));
var decode_codepoint = {};
(function (exports) {
// Adapted from https://github.com/mathiasbynens/he/blob/36afe179392226cf1b6ccdb16ebbb7a5a844d93a/src/he.js#L106-L134
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.replaceCodePoint = exports.fromCodePoint = void 0;
var decodeMap = new Map([
[0, 65533],
// C1 Unicode control character reference replacements
[128, 8364],
[130, 8218],
[131, 402],
[132, 8222],
[133, 8230],
[134, 8224],
[135, 8225],
[136, 710],
[137, 8240],
[138, 352],
[139, 8249],
[140, 338],
[142, 381],
[145, 8216],
[146, 8217],
[147, 8220],
[148, 8221],
[149, 8226],
[150, 8211],
[151, 8212],
[152, 732],
[153, 8482],
[154, 353],
[155, 8250],
[156, 339],
[158, 382],
[159, 376],
]);
/**
* Polyfill for `String.fromCodePoint`. It is used to create a string from a Unicode code point.
*/
exports.fromCodePoint =
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, node/no-unsupported-features/es-builtins
(_a = String.fromCodePoint) !== null && _a !== void 0 ? _a : function (codePoint) {
var output = "";
if (codePoint > 0xffff) {
codePoint -= 0x10000;
output += String.fromCharCode(((codePoint >>> 10) & 0x3ff) | 0xd800);
codePoint = 0xdc00 | (codePoint & 0x3ff);
}
output += String.fromCharCode(codePoint);
return output;
};
/**
* Replace the given code point with a replacement character if it is a
* surrogate or is outside the valid range. Otherwise return the code
* point unchanged.
*/
function replaceCodePoint(codePoint) {
var _a;
if ((codePoint >= 0xd800 && codePoint <= 0xdfff) || codePoint > 0x10ffff) {
return 0xfffd;
}
return (_a = decodeMap.get(codePoint)) !== null && _a !== void 0 ? _a : codePoint;
}
exports.replaceCodePoint = replaceCodePoint;
/**
* Replace the code point if relevant, then convert it to a string.
*
* @deprecated Use `fromCodePoint(replaceCodePoint(codePoint))` instead.
* @param codePoint The code point to decode.
* @returns The decoded code point.
*/
function decodeCodePoint(codePoint) {
return (0, exports.fromCodePoint)(replaceCodePoint(codePoint));
}
exports.default = decodeCodePoint;
} (decode_codepoint));
(function (exports) {
var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (commonjsGlobal && commonjsGlobal.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (commonjsGlobal && commonjsGlobal.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.decodeXML = exports.decodeHTMLStrict = exports.decodeHTMLAttribute = exports.decodeHTML = exports.determineBranch = exports.EntityDecoder = exports.DecodingMode = exports.BinTrieFlags = exports.fromCodePoint = exports.replaceCodePoint = exports.decodeCodePoint = exports.xmlDecodeTree = exports.htmlDecodeTree = void 0;
var decode_data_html_js_1 = __importDefault(decodeDataHtml);
exports.htmlDecodeTree = decode_data_html_js_1.default;
var decode_data_xml_js_1 = __importDefault(decodeDataXml);
exports.xmlDecodeTree = decode_data_xml_js_1.default;
var decode_codepoint_js_1 = __importStar(decode_codepoint);
exports.decodeCodePoint = decode_codepoint_js_1.default;
var decode_codepoint_js_2 = decode_codepoint;
Object.defineProperty(exports, "replaceCodePoint", { enumerable: true, get: function () { return decode_codepoint_js_2.replaceCodePoint; } });
Object.defineProperty(exports, "fromCodePoint", { enumerable: true, get: function () { return decode_codepoint_js_2.fromCodePoint; } });
var CharCodes;
(function (CharCodes) {
CharCodes[CharCodes["NUM"] = 35] = "NUM";
CharCodes[CharCodes["SEMI"] = 59] = "SEMI";
CharCodes[CharCodes["EQUALS"] = 61] = "EQUALS";
CharCodes[CharCodes["ZERO"] = 48] = "ZERO";
CharCodes[CharCodes["NINE"] = 57] = "NINE";
CharCodes[CharCodes["LOWER_A"] = 97] = "LOWER_A";
CharCodes[CharCodes["LOWER_F"] = 102] = "LOWER_F";
CharCodes[CharCodes["LOWER_X"] = 120] = "LOWER_X";
CharCodes[CharCodes["LOWER_Z"] = 122] = "LOWER_Z";
CharCodes[CharCodes["UPPER_A"] = 65] = "UPPER_A";
CharCodes[CharCodes["UPPER_F"] = 70] = "UPPER_F";
CharCodes[CharCodes["UPPER_Z"] = 90] = "UPPER_Z";
})(CharCodes || (CharCodes = {}));
/** Bit that needs to be set to convert an upper case ASCII character to lower case */
var TO_LOWER_BIT = 32;
var BinTrieFlags;
(function (BinTrieFlags) {
BinTrieFlags[BinTrieFlags["VALUE_LENGTH"] = 49152] = "VALUE_LENGTH";
BinTrieFlags[BinTrieFlags["BRANCH_LENGTH"] = 16256] = "BRANCH_LENGTH";
BinTrieFlags[BinTrieFlags["JUMP_TABLE"] = 127] = "JUMP_TABLE";
})(BinTrieFlags = exports.BinTrieFlags || (exports.BinTrieFlags = {}));
function isNumber(code) {
return code >= CharCodes.ZERO && code <= CharCodes.NINE;
}
function isHexadecimalCharacter(code) {
return ((code >= CharCodes.UPPER_A && code <= CharCodes.UPPER_F) ||
(code >= CharCodes.LOWER_A && code <= CharCodes.LOWER_F));
}
function isAsciiAlphaNumeric(code) {
return ((code >= CharCodes.UPPER_A && code <= CharCodes.UPPER_Z) ||
(code >= CharCodes.LOWER_A && code <= CharCodes.LOWER_Z) ||
isNumber(code));
}
/**
* Checks if the given character is a valid end character for an entity in an attribute.
*
* Attribute values that aren't terminated properly aren't parsed, and shouldn't lead to a parser error.
* See the example in https://html.spec.whatwg.org/multipage/parsing.html#named-character-reference-state
*/
function isEntityInAttributeInvalidEnd(code) {
return code === CharCodes.EQUALS || isAsciiAlphaNumeric(code);
}
var EntityDecoderState;
(function (EntityDecoderState) {
EntityDecoderState[EntityDecoderState["EntityStart"] = 0] = "EntityStart";
EntityDecoderState[EntityDecoderState["NumericStart"] = 1] = "NumericStart";
EntityDecoderState[EntityDecoderState["NumericDecimal"] = 2] = "NumericDecimal";
EntityDecoderState[EntityDecoderState["NumericHex"] = 3] = "NumericHex";
EntityDecoderState[EntityDecoderState["NamedEntity"] = 4] = "NamedEntity";
})(EntityDecoderState || (EntityDecoderState = {}));
var DecodingMode;
(function (DecodingMode) {
/** Entities in text nodes that can end with any character. */
DecodingMode[DecodingMode["Legacy"] = 0] = "Legacy";
/** Only allow entities terminated with a semicolon. */
DecodingMode[DecodingMode["Strict"] = 1] = "Strict";
/** Entities in attributes have limitations on ending characters. */
DecodingMode[DecodingMode["Attribute"] = 2] = "Attribute";
})(DecodingMode = exports.DecodingMode || (exports.DecodingMode = {}));
/**
* Token decoder with support of writing partial entities.
*/
var EntityDecoder = /** @class */ (function () {
function EntityDecoder(
/** The tree used to decode entities. */
decodeTree,
/**
* The function that is called when a codepoint is decoded.
*
* For multi-byte named entities, this will be called multiple times,
* with the second codepoint, and the same `consumed` value.
*
* @param codepoint The decoded codepoint.
* @param consumed The number of bytes consumed by the decoder.
*/
emitCodePoint,
/** An object that is used to produce errors. */
errors) {
this.decodeTree = decodeTree;
this.emitCodePoint = emitCodePoint;
this.errors = errors;
/** The current state of the decoder. */
this.state = EntityDecoderState.EntityStart;
/** Characters that were consumed while parsing an entity. */
this.consumed = 1;
/**
* The result of the entity.
*
* Either the result index of a numeric entity, or the codepoint of a
* numeric entity.
*/
this.result = 0;
/** The current index in the decode tree. */
this.treeIndex = 0;
/** The number of characters that were consumed in excess. */
this.excess = 1;
/** The mode in which the decoder is operating. */
this.decodeMode = DecodingMode.Strict;
}
/** Resets the instance to make it reusable. */
EntityDecoder.prototype.startEntity = function (decodeMode) {
this.decodeMode = decodeMode;
this.state = EntityDecoderState.EntityStart;
this.result = 0;
this.treeIndex = 0;
this.excess = 1;
this.consumed = 1;
};
/**
* Write an entity to the decoder. This can be called multiple times with partial entities.
* If the entity is incomplete, the decoder will return -1.
*
* Mirrors the implementation of `getDecoder`, but with the ability to stop decoding if the
* entity is incomplete, and resume when the next string is written.
*
* @param string The string containing the entity (or a continuation of the entity).
* @param offset The offset at which the entity begins. Should be 0 if this is not the first call.
* @returns The number of characters that were consumed, or -1 if the entity is incomplete.
*/
EntityDecoder.prototype.write = function (str, offset) {
switch (this.state) {
case EntityDecoderState.EntityStart: {
if (str.charCodeAt(offset) === CharCodes.NUM) {
this.state = EntityDecoderState.NumericStart;
this.consumed += 1;
return this.stateNumericStart(str, offset + 1);
}
this.state = EntityDecoderState.NamedEntity;
return this.stateNamedEntity(str, offset);
}
case EntityDecoderState.NumericStart: {
return this.stateNumericStart(str, offset);
}
case EntityDecoderState.NumericDecimal: {
return this.stateNumericDecimal(str, offset);
}
case EntityDecoderState.NumericHex: {
return this.stateNumericHex(str, offset);
}
case EntityDecoderState.NamedEntity: {
return this.stateNamedEntity(str, offset);
}
}
};
/**
* Switches between the numeric decimal and hexadecimal states.
*
* Equivalent to the `Numeric character reference state` in the HTML spec.
*
* @param str The string containing the entity (or a continuation of the entity).
* @param offset The current offset.
* @returns The number of characters that were consumed, or -1 if the entity is incomplete.
*/
EntityDecoder.prototype.stateNumericStart = function (str, offset) {
if (offset >= str.length) {
return -1;
}
if ((str.charCodeAt(offset) | TO_LOWER_BIT) === CharCodes.LOWER_X) {
this.state = EntityDecoderState.NumericHex;
this.consumed += 1;
return this.stateNumericHex(str, offset + 1);
}
this.state = EntityDecoderState.NumericDecimal;
return this.stateNumericDecimal(str, offset);
};
EntityDecoder.prototype.addToNumericResult = function (str, start, end, base) {
if (start !== end) {
var digitCount = end - start;
this.result =
this.result * Math.pow(base, digitCount) +
parseInt(str.substr(start, digitCount), base);
this.consumed += digitCount;
}
};
/**
* Parses a hexadecimal numeric entity.
*
* Equivalent to the `Hexademical character reference state` in the HTML spec.
*
* @param str The string containing the entity (or a continuation of the entity).
* @param offset The current offset.
* @returns The number of characters that were consumed, or -1 if the entity is incomplete.
*/
EntityDecoder.prototype.stateNumericHex = function (str, offset) {
var startIdx = offset;
while (offset < str.length) {
var char = str.charCodeAt(offset);
if (isNumber(char) || isHexadecimalCharacter(char)) {
offset += 1;
}
else {
this.addToNumericResult(str, startIdx, offset, 16);
return this.emitNumericEntity(char, 3);
}
}
this.addToNumericResult(str, startIdx, offset, 16);
return -1;
};
/**
* Parses a decimal numeric entity.
*
* Equivalent to the `Decimal character reference state` in the HTML spec.
*
* @param str The string containing the entity (or a continuation of the entity).
* @param offset The current offset.
* @returns The number of characters that were consumed, or -1 if the entity is incomplete.
*/
EntityDecoder.prototype.stateNumericDecimal = function (str, offset) {
var startIdx = offset;
while (offset < str.length) {
var char = str.charCodeAt(offset);
if (isNumber(char)) {
offset += 1;
}
else {
this.addToNumericResult(str, startIdx, offset, 10);
return this.emitNumericEntity(char, 2);
}
}
this.addToNumericResult(str, startIdx, offset, 10);
return -1;
};
/**
* Validate and emit a numeric entity.
*
* Implements the logic from the `Hexademical character reference start
* state` and `Numeric character reference end state` in the HTML spec.
*
* @param lastCp The last code point of the entity. Used to see if the
* entity was terminated with a semicolon.
* @param expectedLength The minimum number of characters that should be
* consumed. Used to validate that at least one digit
* was consumed.
* @returns The number of characters that were consumed.
*/
EntityDecoder.prototype.emitNumericEntity = function (lastCp, expectedLength) {
var _a;
// Ensure we consumed at least one digit.
if (this.consumed <= expectedLength) {
(_a = this.errors) === null || _a === void 0 ? void 0 : _a.absenceOfDigitsInNumericCharacterReference(this.consumed);
return 0;
}
// Figure out if this is a legit end of the entity
if (lastCp === CharCodes.SEMI) {
this.consumed += 1;
}
else if (this.decodeMode === DecodingMode.Strict) {
return 0;
}
this.emitCodePoint((0, decode_codepoint_js_1.replaceCodePoint)(this.result), this.consumed);
if (this.errors) {
if (lastCp !== CharCodes.SEMI) {
this.errors.missingSemicolonAfterCharacterReference();
}
this.errors.validateNumericCharacterReference(this.result);
}
return this.consumed;
};
/**
* Parses a named entity.
*
* Equivalent to the `Named character reference state` in the HTML spec.
*
* @param str The string containing the entity (or a continuation of the entity).
* @param offset The current offset.
* @returns The number of characters that were consumed, or -1 if the entity is incomplete.
*/
EntityDecoder.prototype.stateNamedEntity = function (str, offset) {
var decodeTree = this.decodeTree;
var current = decodeTree[this.treeIndex];
// The mask is the number of bytes of the value, including the current byte.
var valueLength = (current & BinTrieFlags.VALUE_LENGTH) >> 14;
for (; offset < str.length; offset++, this.excess++) {
var char = str.charCodeAt(offset);
this.treeIndex = determineBranch(decodeTree, current, this.treeIndex + Math.max(1, valueLength), char);
if (this.treeIndex < 0) {
return this.result === 0 ||
// If we are parsing an attribute
(this.decodeMode === DecodingMode.Attribute &&
// We shouldn't have consumed any characters after the entity,
(valueLength === 0 ||
// And there should be no invalid characters.
isEntityInAttributeInvalidEnd(char)))
? 0
: this.emitNotTerminatedNamedEntity();
}
current = decodeTree[this.treeIndex];
valueLength = (current & BinTrieFlags.VALUE_LENGTH) >> 14;
// If the branch is a value, store it and continue
if (valueLength !== 0) {
// If the entity is terminated by a semicolon, we are done.
if (char === CharCodes.SEMI) {
return this.emitNamedEntityData(this.treeIndex, valueLength, this.consumed + this.excess);
}
// If we encounter a non-terminated (legacy) entity while parsing strictly, then ignore it.
if (this.decodeMode !== DecodingMode.Strict) {
this.result = this.treeIndex;
this.consumed += this.excess;
this.excess = 0;
}
}
}
return -1;
};
/**
* Emit a named entity that was not terminated with a semicolon.
*
* @returns The number of characters consumed.
*/
EntityDecoder.prototype.emitNotTerminatedNamedEntity = function () {
var _a;
var _b = this, result = _b.result, decodeTree = _b.decodeTree;
var valueLength = (decodeTree[result] & BinTrieFlags.VALUE_LENGTH) >> 14;
this.emitNamedEntityData(result, valueLength, this.consumed);
(_a = this.errors) === null || _a === void 0 ? void 0 : _a.missingSemicolonAfterCharacterReference();
return this.consumed;
};
/**
* Emit a named entity.
*
* @param result The index of the entity in the decode tree.
* @param valueLength The number of bytes in the entity.
* @param consumed The number of characters consumed.
*
* @returns The number of characters consumed.
*/
EntityDecoder.prototype.emitNamedEntityData = function (result, valueLength, consumed) {
var decodeTree = this.decodeTree;
this.emitCodePoint(valueLength === 1
? decodeTree[result] & ~BinTrieFlags.VALUE_LENGTH
: decodeTree[result + 1], consumed);
if (valueLength === 3) {
// For multi-byte values, we need to emit the second byte.
this.emitCodePoint(decodeTree[result + 2], consumed);
}
return consumed;
};
/**
* Signal to the parser that the end of the input was reached.
*
* Remaining data will be emitted and relevant errors will be produced.
*
* @returns The number of characters consumed.
*/
EntityDecoder.prototype.end = function () {
var _a;
switch (this.state) {
case EntityDecoderState.NamedEntity: {
// Emit a named entity if we have one.
return this.result !== 0 &&
(this.decodeMode !== DecodingMode.Attribute ||
this.result === this.treeIndex)
? this.emitNotTerminatedNamedEntity()
: 0;
}
// Otherwise, emit a numeric entity if we have one.
case EntityDecoderState.NumericDecimal: {
return this.emitNumericEntity(0, 2);
}
case EntityDecoderState.NumericHex: {
return this.emitNumericEntity(0, 3);
}
case EntityDecoderState.NumericStart: {
(_a = this.errors) === null || _a === void 0 ? void 0 : _a.absenceOfDigitsInNumericCharacterReference(this.consumed);
return 0;
}
case EntityDecoderState.EntityStart: {
// Return 0 if we have no entity.
return 0;
}
}
};
return EntityDecoder;
}());
exports.EntityDecoder = EntityDecoder;
/**
* Creates a function that decodes entities in a string.
*
* @param decodeTree The decode tree.
* @returns A function that decodes entities in a string.
*/
function getDecoder(decodeTree) {
var ret = "";
var decoder = new EntityDecoder(decodeTree, function (str) { return (ret += (0, decode_codepoint_js_1.fromCodePoint)(str)); });
return function decodeWithTrie(str, decodeMode) {
var lastIndex = 0;
var offset = 0;
while ((offset = str.indexOf("&", offset)) >= 0) {
ret += str.slice(lastIndex, offset);
decoder.startEntity(decodeMode);
var len = decoder.write(str,
// Skip the "&"
offset + 1);
if (len < 0) {
lastIndex = offset + decoder.end();
break;
}
lastIndex = offset + len;
// If `len` is 0, skip the current `&` and continue.
offset = len === 0 ? lastIndex + 1 : lastIndex;
}
var result = ret + str.slice(lastIndex);
// Make sure we don't keep a reference to the final string.
ret = "";
return result;
};
}
/**
* Determines the branch of the current node that is taken given the current
* character. This function is used to traverse the trie.
*
* @param decodeTree The trie.
* @param current The current node.
* @param nodeIdx The index right after the current node and its value.
* @param char The current character.
* @returns The index of the next node, or -1 if no branch is taken.
*/
function determineBranch(decodeTree, current, nodeIdx, char) {
var branchCount = (current & BinTrieFlags.BRANCH_LENGTH) >> 7;
var jumpOffset = current & BinTrieFlags.JUMP_TABLE;
// Case 1: Single branch encoded in jump offset
if (branchCount === 0) {
return jumpOffset !== 0 && char === jumpOffset ? nodeIdx : -1;
}
// Case 2: Multiple branches encoded in jump table
if (jumpOffset) {
var value = char - jumpOffset;
return value < 0 || value >= branchCount
? -1
: decodeTree[nodeIdx + value] - 1;
}
// Case 3: Multiple branches encoded in dictionary
// Binary search for the character.
var lo = nodeIdx;
var hi = lo + branchCount - 1;
while (lo <= hi) {
var mid = (lo + hi) >>> 1;
var midVal = decodeTree[mid];
if (midVal < char) {
lo = mid + 1;
}
else if (midVal > char) {
hi = mid - 1;
}
else {
return decodeTree[mid + branchCount];
}
}
return -1;
}
exports.determineBranch = determineBranch;
var htmlDecoder = getDecoder(decode_data_html_js_1.default);
var xmlDecoder = getDecoder(decode_data_xml_js_1.default);
/**
* Decodes an HTML string.
*
* @param str The string to decode.
* @param mode The decoding mode.
* @returns The decoded string.
*/
function decodeHTML(str, mode) {
if (mode === void 0) { mode = DecodingMode.Legacy; }
return htmlDecoder(str, mode);
}
exports.decodeHTML = decodeHTML;
/**
* Decodes an HTML string in an attribute.
*
* @param str The string to decode.
* @returns The decoded string.
*/
function decodeHTMLAttribute(str) {
return htmlDecoder(str, DecodingMode.Attribute);
}
exports.decodeHTMLAttribute = decodeHTMLAttribute;
/**
* Decodes an HTML string, requiring all entities to be terminated by a semicolon.
*
* @param str The string to decode.
* @returns The decoded string.
*/
function decodeHTMLStrict(str) {
return htmlDecoder(str, DecodingMode.Strict);
}
exports.decodeHTMLStrict = decodeHTMLStrict;
/**
* Decodes an XML string, requiring all entities to be terminated by a semicolon.
*
* @param str The string to decode.
* @returns The decoded string.
*/
function decodeXML(str) {
return xmlDecoder(str, DecodingMode.Strict);
}
exports.decodeXML = decodeXML;
} (decode$6));
var encode$6 = {};
var encodeHtml = {};
// Generated using scripts/write-encode-map.ts
Object.defineProperty(encodeHtml, "__esModule", { value: true });
function restoreDiff(arr) {
for (var i = 1; i < arr.length; i++) {
arr[i][0] += arr[i - 1][0] + 1;
}
return arr;
}
// prettier-ignore
encodeHtml.default = new Map(/* #__PURE__ */ restoreDiff([[9, "&Tab;"], [0, "&NewLine;"], [22, "&excl;"], [0, "&quot;"], [0, "&num;"], [0, "&dollar;"], [0, "&percnt;"], [0, "&amp;"], [0, "&apos;"], [0, "&lpar;"], [0, "&rpar;"], [0, "&ast;"], [0, "&plus;"], [0, "&comma;"], [1, "&period;"], [0, "&sol;"], [10, "&colon;"], [0, "&semi;"], [0, { v: "&lt;", n: 8402, o: "&nvlt;" }], [0, { v: "&equals;", n: 8421, o: "&bne;" }], [0, { v: "&gt;", n: 8402, o: "&nvgt;" }], [0, "&quest;"], [0, "&commat;"], [26, "&lbrack;"], [0, "&bsol;"], [0, "&rbrack;"], [0, "&Hat;"], [0, "&lowbar;"], [0, "&DiacriticalGrave;"], [5, { n: 106, o: "&fjlig;" }], [20, "&lbrace;"], [0, "&verbar;"], [0, "&rbrace;"], [34, "&nbsp;"], [0, "&iexcl;"], [0, "&cent;"], [0, "&pound;"], [0, "&curren;"], [0, "&yen;"], [0, "&brvbar;"], [0, "&sect;"], [0, "&die;"], [0, "&copy;"], [0, "&ordf;"], [0, "&laquo;"], [0, "&not;"], [0, "&shy;"], [0, "&circledR;"], [0, "&macr;"], [0, "&deg;"], [0, "&PlusMinus;"], [0, "&sup2;"], [0, "&sup3;"], [0, "&acute;"], [0, "&micro;"], [0, "&para;"], [0, "&centerdot;"], [0, "&cedil;"], [0, "&sup1;"], [0, "&ordm;"], [0, "&raquo;"], [0, "&frac14;"], [0, "&frac12;"], [0, "&frac34;"], [0, "&iquest;"], [0, "&Agrave;"], [0, "&Aacute;"], [0, "&Acirc;"], [0, "&Atilde;"], [0, "&Auml;"], [0, "&angst;"], [0, "&AElig;"], [0, "&Ccedil;"], [0, "&Egrave;"], [0, "&Eacute;"], [0, "&Ecirc;"], [0, "&Euml;"], [0, "&Igrave;"], [0, "&Iacute;"], [0, "&Icirc;"], [0, "&Iuml;"], [0, "&ETH;"], [0, "&Ntilde;"], [0, "&Ograve;"], [0, "&Oacute;"], [0, "&Ocirc;"], [0, "&Otilde;"], [0, "&Ouml;"], [0, "&times;"], [0, "&Oslash;"], [0, "&Ugrave;"], [0, "&Uacute;"], [0, "&Ucirc;"], [0, "&Uuml;"], [0, "&Yacute;"], [0, "&THORN;"], [0, "&szlig;"], [0, "&agrave;"], [0, "&aacute;"], [0, "&acirc;"], [0, "&atilde;"], [0, "&auml;"], [0, "&aring;"], [0, "&aelig;"], [0, "&ccedil;"], [0, "&egrave;"], [0, "&eacute;"], [0, "&ecirc;"], [0, "&euml;"], [0, "&igrave;"], [0, "&iacute;"], [0, "&icirc;"], [0, "&iuml;"], [0, "&eth;"], [0, "&ntilde;"], [0, "&ograve;"], [0, "&oacute;"], [0, "&ocirc;"], [0, "&otilde;"], [0, "&ouml;"], [0, "&div;"], [0, "&oslash;"], [0, "&ugrave;"], [0, "&uacute;"], [0, "&ucirc;"], [0, "&uuml;"], [0, "&yacute;"], [0, "&thorn;"], [0, "&yuml;"], [0, "&Amacr;"], [0, "&amacr;"], [0, "&Abreve;"], [0, "&abreve;"], [0, "&Aogon;"], [0, "&aogon;"], [0, "&Cacute;"], [0, "&cacute;"], [0, "&Ccirc;"], [0, "&ccirc;"], [0, "&Cdot;"], [0, "&cdot;"], [0, "&Ccaron;"], [0, "&ccaron;"], [0, "&Dcaron;"], [0, "&dcaron;"], [0, "&Dstrok;"], [0, "&dstrok;"], [0, "&Emacr;"], [0, "&emacr;"], [2, "&Edot;"], [0, "&edot;"], [0, "&Eogon;"], [0, "&eogon;"], [0, "&Ecaron;"], [0, "&ecaron;"], [0, "&Gcirc;"], [0, "&gcirc;"], [0, "&Gbreve;"], [0, "&gbreve;"], [0, "&Gdot;"], [0, "&gdot;"], [0, "&Gcedil;"], [1, "&Hcirc;"], [0, "&hcirc;"], [0, "&Hstrok;"], [0, "&hstrok;"], [0, "&Itilde;"], [0, "&itilde;"], [0, "&Imacr;"], [0, "&imacr;"], [2, "&Iogon;"], [0, "&iogon;"], [0, "&Idot;"], [0, "&imath;"], [0, "&IJlig;"], [0, "&ijlig;"], [0, "&Jcirc;"], [0, "&jcirc;"], [0, "&Kcedil;"], [0, "&kcedil;"], [0, "&kgreen;"], [0, "&Lacute;"], [0, "&lacute;"], [0, "&Lcedil;"], [0, "&lcedil;"], [0, "&Lcaron;"], [0, "&lcaron;"], [0, "&Lmidot;"], [0, "&lmidot;"], [0, "&Lstrok;"], [0, "&lstrok;"], [0, "&Nacute;"], [0, "&nacute;"], [0, "&Ncedil;"], [0, "&ncedil;"], [0, "&Ncaron;"], [0, "&ncaron;"], [0, "&napos;"], [0, "&ENG;"], [0, "&eng;"], [0, "&Omacr;"], [0, "&omacr;"], [2, "&Odblac;"], [0, "&odblac;"], [0, "&OElig;"], [0, "&oelig;"], [0, "&Racute;"], [0, "&racute;"], [0, "&Rcedil;"], [0, "&rcedil;"], [0, "&Rcaron;"], [0, "&rcaron;"], [0, "&Sacute;"], [0, "&sacute;"], [0, "&Scirc;"], [0, "&scirc;"], [0, "&Scedil;"], [0, "&scedil;"], [0, "&Scaron;"], [0, "&scaron;"], [0, "&Tcedil;"], [0, "&tcedil;"], [0, "&Tcaron;"], [0, "&tcaron;"], [0, "&Tstrok;"], [0, "&tstrok;"], [0, "&Utilde;"], [0, "&utilde;"], [0, "&Umacr;"], [0, "&umacr;"], [0, "&Ubreve;"], [0, "&ubreve;"], [0, "&Uring;"], [0, "&uring;"], [0, "&Udblac;"], [0, "&udblac;"], [0, "&Uogon;"], [0, "&uogon;"], [0, "&Wcirc;"], [0, "&wcirc;"], [0, "&Ycirc;"], [0, "&ycirc;"], [0, "&Yuml;"], [0, "&Zacute;"], [0, "&zacute;"], [0, "&Zdot;"], [0, "&zdot;"], [0, "&Zcaron;"], [0, "&zcaron;"], [19, "&fnof;"], [34, "&imped;"], [63, "&gacute;"], [65, "&jmath;"], [142, "&circ;"], [0, "&caron;"], [16, "&breve;"], [0, "&DiacriticalDot;"], [0, "&ring;"], [0, "&ogon;"], [0, "&DiacriticalTilde;"], [0, "&dblac;"], [51, "&DownBreve;"], [127, "&Alpha;"], [0, "&Beta;"], [0, "&Gamma;"], [0, "&Delta;"], [0, "&Epsilon;"], [0, "&Zeta;"], [0, "&Eta;"], [0, "&Theta;"], [0, "&Iota;"], [0, "&Kappa;"], [0, "&Lambda;"], [0, "&Mu;"], [0, "&Nu;"], [0, "&Xi;"], [0, "&Omicron;"], [0, "&Pi;"], [0, "&Rho;"], [1, "&Sigma;"], [0, "&Tau;"], [0, "&Upsilon;"], [0, "&Phi;"], [0, "&Chi;"], [0, "&Psi;"], [0, "&ohm;"], [7, "&alpha;"], [0, "&beta;"], [0, "&gamma;"], [0, "&delta;"], [0, "&epsi;"], [0, "&zeta;"], [0, "&eta;"], [0, "&theta;"], [0, "&iota;"], [0, "&kappa;"], [0, "&lambda;"], [0, "&mu;"], [0, "&nu;"], [0, "&xi;"], [0, "&omicron;"], [0, "&pi;"], [0, "&rho;"], [0, "&sigmaf;"], [0, "&sigma;"], [0, "&tau;"], [0, "&upsi;"], [0, "&phi;"], [0, "&chi;"], [0, "&psi;"], [0, "&omega;"], [7, "&thetasym;"], [0, "&Upsi;"], [2, "&phiv;"], [0, "&piv;"], [5, "&Gammad;"], [0, "&digamma;"], [18, "&kappav;"], [0, "&rhov;"], [3, "&epsiv;"], [0, "&backepsilon;"], [10, "&IOcy;"], [0, "&DJcy;"], [0, "&GJcy;"], [0, "&Jukcy;"], [0, "&DScy;"], [0, "&Iukcy;"], [0, "&YIcy;"], [0, "&Jsercy;"], [0, "&LJcy;"], [0, "&NJcy;"], [0, "&TSHcy;"], [0, "&KJcy;"], [1, "&Ubrcy;"], [0, "&DZcy;"], [0, "&Acy;"], [0, "&Bcy;"], [0, "&Vcy;"], [0, "&Gcy;"], [0, "&Dcy;"], [0, "&IEcy;"], [0, "&ZHcy;"], [0, "&Zcy;"], [0, "&Icy;"], [0, "&Jcy;"], [0, "&Kcy;"], [0, "&Lcy;"], [0, "&Mcy;"], [0, "&Ncy;"], [0, "&Ocy;"], [0, "&Pcy;"], [0, "&Rcy;"], [0, "&Scy;"], [0, "&Tcy;"], [0, "&Ucy;"], [0, "&Fcy;"], [0, "&KHcy;"], [0, "&TScy;"], [0, "&CHcy;"], [0, "&SHcy;"], [0, "&SHCHcy;"], [0, "&HARDcy;"], [0, "&Ycy;"], [0, "&SOFTcy;"], [0, "&Ecy;"], [0, "&YUcy;"], [0, "&YAcy;"], [0, "&acy;"], [0, "&bcy;"], [0, "&vcy;"], [0, "&gcy;"], [0, "&dcy;"], [0, "&iecy;"], [0, "&zhcy;"], [0, "&zcy;"], [0, "&icy;"], [0, "&jcy;"], [0, "&kcy;"], [0, "&lcy;"], [0, "&mcy;"], [0, "&ncy;"], [0, "&ocy;"], [0, "&pcy;"], [0, "&rcy;"], [0, "&scy;"], [0, "&tcy;"], [0, "&ucy;"], [0, "&fcy;"], [0, "&khcy;"], [0, "&tscy;"], [0, "&chcy;"], [0, "&shcy;"], [0, "&shchcy;"], [0, "&hardcy;"], [0, "&ycy;"], [0, "&softcy;"], [0, "&ecy;"], [0, "&yucy;"], [0, "&yacy;"], [1, "&iocy;"], [0, "&djcy;"], [0, "&gjcy;"], [0, "&jukcy;"], [0, "&dscy;"], [0, "&iukcy;"], [0, "&yicy;"], [0, "&jsercy;"], [0, "&ljcy;"], [0, "&njcy;"], [0, "&tshcy;"], [0, "&kjcy;"], [1, "&ubrcy;"], [0, "&dzcy;"], [7074, "&ensp;"], [0, "&emsp;"], [0, "&emsp13;"], [0, "&emsp14;"], [1, "&numsp;"], [0, "&puncsp;"], [0, "&ThinSpace;"], [0, "&hairsp;"], [0, "&NegativeMediumSpace;"], [0, "&zwnj;"], [0, "&zwj;"], [0, "&lrm;"], [0, "&rlm;"], [0, "&dash;"], [2, "&ndash;"], [0, "&mdash;"], [0, "&horbar;"], [0, "&Verbar;"], [1, "&lsquo;"], [0, "&CloseCurlyQuote;"], [0, "&lsquor;"], [1, "&ldquo;"], [0, "&CloseCurlyDoubleQuote;"], [0, "&bdquo;"], [1, "&dagger;"], [0, "&Dagger;"], [0, "&bull;"], [2, "&nldr;"], [0, "&hellip;"], [9, "&permil;"], [0, "&pertenk;"], [0, "&prime;"], [0, "&Prime;"], [0, "&tprime;"], [0, "&backprime;"], [3, "&lsaquo;"], [0, "&rsaquo;"], [3, "&oline;"], [2, "&caret;"], [1, "&hybull;"], [0, "&frasl;"], [10, "&bsemi;"], [7, "&qprime;"], [7, { v: "&MediumSpace;", n: 8202, o: "&ThickSpace;" }], [0, "&NoBreak;"], [0, "&af;"], [0, "&InvisibleTimes;"], [0, "&ic;"], [72, "&euro;"], [46, "&tdot;"], [0, "&DotDot;"], [37, "&complexes;"], [2, "&incare;"], [4, "&gscr;"], [0, "&hamilt;"], [0, "&Hfr;"], [0, "&Hopf;"], [0, "&planckh;"], [0, "&hbar;"], [0, "&imagline;"], [0, "&Ifr;"], [0, "&lagran;"], [0, "&ell;"], [1, "&naturals;"], [0, "&numero;"], [0, "&copysr;"], [0, "&weierp;"], [0, "&Popf;"], [0, "&Qopf;"], [0, "&realine;"], [0, "&real;"], [0, "&reals;"], [0, "&rx;"], [3, "&trade;"], [1, "&integers;"], [2, "&mho;"], [0, "&zeetrf;"], [0, "&iiota;"], [2, "&bernou;"], [0, "&Cayleys;"], [1, "&escr;"], [0, "&Escr;"], [0, "&Fouriertrf;"], [1, "&Mellintrf;"], [0, "&order;"], [0, "&alefsym;"], [0, "&beth;"], [0, "&gimel;"], [0, "&daleth;"], [12, "&CapitalDifferentialD;"], [0, "&dd;"], [0, "&ee;"], [0, "&ii;"], [10, "&frac13;"], [0, "&frac23;"], [0, "&frac15;"], [0, "&frac25;"], [0, "&frac35;"], [0, "&frac45;"], [0, "&frac16;"], [0, "&frac56;"], [0, "&frac18;"], [0, "&frac38;"], [0, "&frac58;"], [0, "&frac78;"], [49, "&larr;"], [0, "&ShortUpArrow;"], [0, "&rarr;"], [0, "&darr;"], [0, "&harr;"], [0, "&updownarrow;"], [0, "&nwarr;"], [0, "&nearr;"], [0, "&LowerRightArrow;"], [0, "&LowerLeftArrow;"], [0, "&nlarr;"], [0, "&nrarr;"], [1, { v: "&rarrw;", n: 824, o: "&nrarrw;" }], [0, "&Larr;"], [0, "&Uarr;"], [0, "&Rarr;"], [0, "&Darr;"], [0, "&larrtl;"], [0, "&rarrtl;"], [0, "&LeftTeeArrow;"], [0, "&mapstoup;"], [0, "&map;"], [0, "&DownTeeArrow;"], [1, "&hookleftarrow;"], [0, "&hookrightarrow;"], [0, "&larrlp;"], [0, "&looparrowright;"], [0, "&harrw;"], [0, "&nharr;"], [1, "&lsh;"], [0, "&rsh;"], [0, "&ldsh;"], [0, "&rdsh;"], [1, "&crarr;"], [0, "&cularr;"], [0, "&curarr;"], [2, "&circlearrowleft;"], [0, "&circlearrowright;"], [0, "&leftharpoonup;"], [0, "&DownLeftVector;"], [0, "&RightUpVector;"], [0, "&LeftUpVector;"], [0, "&rharu;"], [0, "&DownRightVector;"], [0, "&dharr;"], [0, "&dharl;"], [0, "&RightArrowLeftArrow;"], [0, "&udarr;"], [0, "&LeftArrowRightArrow;"], [0, "&leftleftarrows;"], [0, "&upuparrows;"], [0, "&rightrightarrows;"], [0, "&ddarr;"], [0, "&leftrightharpoons;"], [0, "&Equilibrium;"], [0, "&nlArr;"], [0, "&nhArr;"], [0, "&nrArr;"], [0, "&DoubleLeftArrow;"], [0, "&DoubleUpArrow;"], [0, "&DoubleRightArrow;"], [0, "&dArr;"], [0, "&DoubleLeftRightArrow;"], [0, "&DoubleUpDownArrow;"], [0, "&nwArr;"], [0, "&neArr;"], [0, "&seArr;"], [0, "&swArr;"], [0, "&lAarr;"], [0, "&rAarr;"], [1, "&zigrarr;"], [6, "&larrb;"], [0, "&rarrb;"], [15, "&DownArrowUpArrow;"], [7, "&loarr;"], [0, "&roarr;"], [0, "&hoarr;"], [0, "&forall;"], [0, "&comp;"], [0, { v: "&part;", n: 824, o: "&npart;" }], [0, "&exist;"], [0, "&nexist;"], [0, "&empty;"], [1, "&Del;"], [0, "&Element;"], [0, "&NotElement;"], [1, "&ni;"], [0, "&notni;"], [2, "&prod;"], [0, "&coprod;"], [0, "&sum;"], [0, "&minus;"], [0, "&MinusPlus;"], [0, "&dotplus;"], [1, "&Backslash;"], [0, "&lowast;"], [0, "&compfn;"], [1, "&radic;"], [2, "&prop;"], [0, "&infin;"], [0, "&angrt;"], [0, { v: "&ang;", n: 8402, o: "&nang;" }], [0, "&angmsd;"], [0, "&angsph;"], [0, "&mid;"], [0, "&nmid;"], [0, "&DoubleVerticalBar;"], [0, "&NotDoubleVerticalBar;"], [0, "&and;"], [0, "&or;"], [0, { v: "&cap;", n: 65024, o: "&caps;" }], [0, { v: "&cup;", n: 65024, o: "&cups;" }], [0, "&int;"], [0, "&Int;"], [0, "&iiint;"], [0, "&conint;"], [0, "&Conint;"], [0, "&Cconint;"], [0, "&cwint;"], [0, "&ClockwiseContourIntegral;"], [0, "&awconint;"], [0, "&there4;"], [0, "&becaus;"], [0, "&ratio;"], [0, "&Colon;"], [0, "&dotminus;"], [1, "&mDDot;"], [0, "&homtht;"], [0, { v: "&sim;", n: 8402, o: "&nvsim;" }], [0, { v: "&backsim;", n: 817, o: "&race;" }], [0, { v: "&ac;", n: 819, o: "&acE;" }], [0, "&acd;"], [0, "&VerticalTilde;"], [0, "&NotTilde;"], [0, { v: "&eqsim;", n: 824, o: "&nesim;" }], [0, "&sime;"], [0, "&NotTildeEqual;"], [0, "&cong;"], [0, "&simne;"], [0, "&ncong;"], [0, "&ap;"], [0, "&nap;"], [0, "&ape;"], [0, { v: "&apid;", n: 824, o: "&napid;" }], [0, "&backcong;"], [0, { v: "&asympeq;", n: 8402, o: "&nvap;" }], [0, { v: "&bump;", n: 824, o: "&nbump;" }], [0, { v: "&bumpe;", n: 824, o: "&nbumpe;" }], [0, { v: "&doteq;", n: 824, o: "&nedot;" }], [0, "&doteqdot;"], [0, "&efDot;"], [0, "&erDot;"], [0, "&Assign;"], [0, "&ecolon;"], [0, "&ecir;"], [0, "&circeq;"], [1, "&wedgeq;"], [0, "&veeeq;"], [1, "&triangleq;"], [2, "&equest;"], [0, "&ne;"], [0, { v: "&Congruent;", n: 8421, o: "&bnequiv;" }], [0, "&nequiv;"], [1, { v: "&le;", n: 8402, o: "&nvle;" }], [0, { v: "&ge;", n: 8402, o: "&nvge;" }], [0, { v: "&lE;", n: 824, o: "&nlE;" }], [0, { v: "&gE;", n: 824, o: "&ngE;" }], [0, { v: "&lnE;", n: 65024, o: "&lvertneqq;" }], [0, { v: "&gnE;", n: 65024, o: "&gvertneqq;" }], [0, { v: "&ll;", n: new Map(/* #__PURE__ */ restoreDiff([[824, "&nLtv;"], [7577, "&nLt;"]])) }], [0, { v: "&gg;", n: new Map(/* #__PURE__ */ restoreDiff([[824, "&nGtv;"], [7577, "&nGt;"]])) }], [0, "&between;"], [0, "&NotCupCap;"], [0, "&nless;"], [0, "&ngt;"], [0, "&nle;"], [0, "&nge;"], [0, "&lesssim;"], [0, "&GreaterTilde;"], [0, "&nlsim;"], [0, "&ngsim;"], [0, "&LessGreater;"], [0, "&gl;"], [0, "&NotLessGreater;"], [0, "&NotGreaterLess;"], [0, "&pr;"], [0, "&sc;"], [0, "&prcue;"], [0, "&sccue;"], [0, "&PrecedesTilde;"], [0, { v: "&scsim;", n: 824, o: "&NotSucceedsTilde;" }], [0, "&NotPrecedes;"], [0, "&NotSucceeds;"], [0, { v: "&sub;", n: 8402, o: "&NotSubset;" }], [0, { v: "&sup;", n: 8402, o: "&NotSuperset;" }], [0, "&nsub;"], [0, "&nsup;"], [0, "&sube;"], [0, "&supe;"], [0, "&NotSubsetEqual;"], [0, "&NotSupersetEqual;"], [0, { v: "&subne;", n: 65024, o: "&varsubsetneq;" }], [0, { v: "&supne;", n: 65024, o: "&varsupsetneq;" }], [1, "&cupdot;"], [0, "&UnionPlus;"], [0, { v: "&sqsub;", n: 824, o: "&NotSquareSubset;" }], [0, { v: "&sqsup;", n: 824, o: "&NotSquareSuperset;" }], [0, "&sqsube;"], [0, "&sqsupe;"], [0, { v: "&sqcap;", n: 65024, o: "&sqcaps;" }], [0, { v: "&sqcup;", n: 65024, o: "&sqcups;" }], [0, "&CirclePlus;"], [0, "&CircleMinus;"], [0, "&CircleTimes;"], [0, "&osol;"], [0, "&CircleDot;"], [0, "&circledcirc;"], [0, "&circledast;"], [1, "&circleddash;"], [0, "&boxplus;"], [0, "&boxminus;"], [0, "&boxtimes;"], [0, "&dotsquare;"], [0, "&RightTee;"], [0, "&dashv;"], [0, "&DownTee;"], [0, "&bot;"], [1, "&models;"], [0, "&DoubleRightTee;"], [0, "&Vdash;"], [0, "&Vvdash;"], [0, "&VDash;"], [0, "&nvdash;"], [0, "&nvDash;"], [0, "&nVdash;"], [0, "&nVDash;"], [0, "&prurel;"], [1, "&LeftTriangle;"], [0, "&RightTriangle;"], [0, { v: "&LeftTriangleEqual;", n: 8402, o: "&nvltrie;" }], [0, { v: "&RightTriangleEqual;", n: 8402, o: "&nvrtrie;" }], [0, "&origof;"], [0, "&imof;"], [0, "&multimap;"], [0, "&hercon;"], [0, "&intcal;"], [0, "&veebar;"], [1, "&barvee;"], [0, "&angrtvb;"], [0, "&lrtri;"], [0, "&bigwedge;"], [0, "&bigvee;"], [0, "&bigcap;"], [0, "&bigcup;"], [0, "&diam;"], [0, "&sdot;"], [0, "&sstarf;"], [0, "&divideontimes;"], [0, "&bowtie;"], [0, "&ltimes;"], [0, "&rtimes;"], [0, "&leftthreetimes;"], [0, "&rightthreetimes;"], [0, "&backsimeq;"], [0, "&curlyvee;"], [0, "&curlywedge;"], [0, "&Sub;"], [0, "&Sup;"], [0, "&Cap;"], [0, "&Cup;"], [0, "&fork;"], [0, "&epar;"], [0, "&lessdot;"], [0, "&gtdot;"], [0, { v: "&Ll;", n: 824, o: "&nLl;" }], [0, { v: "&Gg;", n: 824, o: "&nGg;" }], [0, { v: "&leg;", n: 65024, o: "&lesg;" }], [0, { v: "&gel;", n: 65024, o: "&gesl;" }], [2, "&cuepr;"], [0, "&cuesc;"], [0, "&NotPrecedesSlantEqual;"], [0, "&NotSucceedsSlantEqual;"], [0, "&NotSquareSubsetEqual;"], [0, "&NotSquareSupersetEqual;"], [2, "&lnsim;"], [0, "&gnsim;"], [0, "&precnsim;"], [0, "&scnsim;"], [0, "&nltri;"], [0, "&NotRightTriangle;"], [0, "&nltrie;"], [0, "&NotRightTriangleEqual;"], [0, "&vellip;"], [0, "&ctdot;"], [0, "&utdot;"], [0, "&dtdot;"], [0, "&disin;"], [0, "&isinsv;"], [0, "&isins;"], [0, { v: "&isindot;", n: 824, o: "&notindot;" }], [0, "&notinvc;"], [0, "&notinvb;"], [1, { v: "&isinE;", n: 824, o: "&notinE;" }], [0, "&nisd;"], [0, "&xnis;"], [0, "&nis;"], [0, "&notnivc;"], [0, "&notnivb;"], [6, "&barwed;"], [0, "&Barwed;"], [1, "&lceil;"], [0, "&rceil;"], [0, "&LeftFloor;"], [0, "&rfloor;"], [0, "&drcrop;"], [0, "&dlcrop;"], [0, "&urcrop;"], [0, "&ulcrop;"], [0, "&bnot;"], [1, "&profline;"], [0, "&profsurf;"], [1, "&telrec;"], [0, "&target;"], [5, "&ulcorn;"], [0, "&urcorn;"], [0, "&dlcorn;"], [0, "&drcorn;"], [2, "&frown;"], [0, "&smile;"], [9, "&cylcty;"], [0, "&profalar;"], [7, "&topbot;"], [6, "&ovbar;"], [1, "&solbar;"], [60, "&angzarr;"], [51, "&lmoustache;"], [0, "&rmoustache;"], [2, "&OverBracket;"], [0, "&bbrk;"], [0, "&bbrktbrk;"], [37, "&OverParenthesis;"], [0, "&UnderParenthesis;"], [0, "&OverBrace;"], [0, "&UnderBrace;"], [2, "&trpezium;"], [4, "&elinters;"], [59, "&blank;"], [164, "&circledS;"], [55, "&boxh;"], [1, "&boxv;"], [9, "&boxdr;"], [3, "&boxdl;"], [3, "&boxur;"], [3, "&boxul;"], [3, "&boxvr;"], [7, "&boxvl;"], [7, "&boxhd;"], [7, "&boxhu;"], [7, "&boxvh;"], [19, "&boxH;"], [0, "&boxV;"], [0, "&boxdR;"], [0, "&boxDr;"], [0, "&boxDR;"], [0, "&boxdL;"], [0, "&boxDl;"], [0, "&boxDL;"], [0, "&boxuR;"], [0, "&boxUr;"], [0, "&boxUR;"], [0, "&boxuL;"], [0, "&boxUl;"], [0, "&boxUL;"], [0, "&boxvR;"], [0, "&boxVr;"], [0, "&boxVR;"], [0, "&boxvL;"], [0, "&boxVl;"], [0, "&boxVL;"], [0, "&boxHd;"], [0, "&boxhD;"], [0, "&boxHD;"], [0, "&boxHu;"], [0, "&boxhU;"], [0, "&boxHU;"], [0, "&boxvH;"], [0, "&boxVh;"], [0, "&boxVH;"], [19, "&uhblk;"], [3, "&lhblk;"], [3, "&block;"], [8, "&blk14;"], [0, "&blk12;"], [0, "&blk34;"], [13, "&square;"], [8, "&blacksquare;"], [0, "&EmptyVerySmallSquare;"], [1, "&rect;"], [0, "&marker;"], [2, "&fltns;"], [1, "&bigtriangleup;"], [0, "&blacktriangle;"], [0, "&triangle;"], [2, "&blacktriangleright;"], [0, "&rtri;"], [3, "&bigtriangledown;"], [0, "&blacktriangledown;"], [0, "&dtri;"], [2, "&blacktriangleleft;"], [0, "&ltri;"], [6, "&loz;"], [0, "&cir;"], [32, "&tridot;"], [2, "&bigcirc;"], [8, "&ultri;"], [0, "&urtri;"], [0, "&lltri;"], [0, "&EmptySmallSquare;"], [0, "&FilledSmallSquare;"], [8, "&bigstar;"], [0, "&star;"], [7, "&phone;"], [49, "&female;"], [1, "&male;"], [29, "&spades;"], [2, "&clubs;"], [1, "&hearts;"], [0, "&diamondsuit;"], [3, "&sung;"], [2, "&flat;"], [0, "&natural;"], [0, "&sharp;"], [163, "&check;"], [3, "&cross;"], [8, "&malt;"], [21, "&sext;"], [33, "&VerticalSeparator;"], [25, "&lbbrk;"], [0, "&rbbrk;"], [84, "&bsolhsub;"], [0, "&suphsol;"], [28, "&LeftDoubleBracket;"], [0, "&RightDoubleBracket;"], [0, "&lang;"], [0, "&rang;"], [0, "&Lang;"], [0, "&Rang;"], [0, "&loang;"], [0, "&roang;"], [7, "&longleftarrow;"], [0, "&longrightarrow;"], [0, "&longleftrightarrow;"], [0, "&DoubleLongLeftArrow;"], [0, "&DoubleLongRightArrow;"], [0, "&DoubleLongLeftRightArrow;"], [1, "&longmapsto;"], [2, "&dzigrarr;"], [258, "&nvlArr;"], [0, "&nvrArr;"], [0, "&nvHarr;"], [0, "&Map;"], [6, "&lbarr;"], [0, "&bkarow;"], [0, "&lBarr;"], [0, "&dbkarow;"], [0, "&drbkarow;"], [0, "&DDotrahd;"], [0, "&UpArrowBar;"], [0, "&DownArrowBar;"], [2, "&Rarrtl;"], [2, "&latail;"], [0, "&ratail;"], [0, "&lAtail;"], [0, "&rAtail;"], [0, "&larrfs;"], [0, "&rarrfs;"], [0, "&larrbfs;"], [0, "&rarrbfs;"], [2, "&nwarhk;"], [0, "&nearhk;"], [0, "&hksearow;"], [0, "&hkswarow;"], [0, "&nwnear;"], [0, "&nesear;"], [0, "&seswar;"], [0, "&swnwar;"], [8, { v: "&rarrc;", n: 824, o: "&nrarrc;" }], [1, "&cudarrr;"], [0, "&ldca;"], [0, "&rdca;"], [0, "&cudarrl;"], [0, "&larrpl;"], [2, "&curarrm;"], [0, "&cularrp;"], [7, "&rarrpl;"], [2, "&harrcir;"], [0, "&Uarrocir;"], [0, "&lurdshar;"], [0, "&ldrushar;"], [2, "&LeftRightVector;"], [0, "&RightUpDownVector;"], [0, "&DownLeftRightVector;"], [0, "&LeftUpDownVector;"], [0, "&LeftVectorBar;"], [0, "&RightVectorBar;"], [0, "&RightUpVectorBar;"], [0, "&RightDownVectorBar;"], [0, "&DownLeftVectorBar;"], [0, "&DownRightVectorBar;"], [0, "&LeftUpVectorBar;"], [0, "&LeftDownVectorBar;"], [0, "&LeftTeeVector;"], [0, "&RightTeeVector;"], [0, "&RightUpTeeVector;"], [0, "&RightDownTeeVector;"], [0, "&DownLeftTeeVector;"], [0, "&DownRightTeeVector;"], [0, "&LeftUpTeeVector;"], [0, "&LeftDownTeeVector;"], [0, "&lHar;"], [0, "&uHar;"], [0, "&rHar;"], [0, "&dHar;"], [0, "&luruhar;"], [0, "&ldrdhar;"], [0, "&ruluhar;"], [0, "&rdldhar;"], [0, "&lharul;"], [0, "&llhard;"], [0, "&rharul;"], [0, "&lrhard;"], [0, "&udhar;"], [0, "&duhar;"], [0, "&RoundImplies;"], [0, "&erarr;"], [0, "&simrarr;"], [0, "&larrsim;"], [0, "&rarrsim;"], [0, "&rarrap;"], [0, "&ltlarr;"], [1, "&gtrarr;"], [0, "&subrarr;"], [1, "&suplarr;"], [0, "&lfisht;"], [0, "&rfisht;"], [0, "&ufisht;"], [0, "&dfisht;"], [5, "&lopar;"], [0, "&ropar;"], [4, "&lbrke;"], [0, "&rbrke;"], [0, "&lbrkslu;"], [0, "&rbrksld;"], [0, "&lbrksld;"], [0, "&rbrkslu;"], [0, "&langd;"], [0, "&rangd;"], [0, "&lparlt;"], [0, "&rpargt;"], [0, "&gtlPar;"], [0, "&ltrPar;"], [3, "&vzigzag;"], [1, "&vangrt;"], [0, "&angrtvbd;"], [6, "&ange;"], [0, "&range;"], [0, "&dwangle;"], [0, "&uwangle;"], [0, "&angmsdaa;"], [0, "&angmsdab;"], [0, "&angmsdac;"], [0, "&angmsdad;"], [0, "&angmsdae;"], [0, "&angmsdaf;"], [0, "&angmsdag;"], [0, "&angmsdah;"], [0, "&bemptyv;"], [0, "&demptyv;"], [0, "&cemptyv;"], [0, "&raemptyv;"], [0, "&laemptyv;"], [0, "&ohbar;"], [0, "&omid;"], [0, "&opar;"], [1, "&operp;"], [1, "&olcross;"], [0, "&odsold;"], [1, "&olcir;"], [0, "&ofcir;"], [0, "&olt;"], [0, "&ogt;"], [0, "&cirscir;"], [0, "&cirE;"], [0, "&solb;"], [0, "&bsolb;"], [3, "&boxbox;"], [3, "&trisb;"], [0, "&rtriltri;"], [0, { v: "&LeftTriangleBar;", n: 824, o: "&NotLeftTriangleBar;" }], [0, { v: "&RightTriangleBar;", n: 824, o: "&NotRightTriangleBar;" }], [11, "&iinfin;"], [0, "&infintie;"], [0, "&nvinfin;"], [4, "&eparsl;"], [0, "&smeparsl;"], [0, "&eqvparsl;"], [5, "&blacklozenge;"], [8, "&RuleDelayed;"], [1, "&dsol;"], [9, "&bigodot;"], [0, "&bigoplus;"], [0, "&bigotimes;"], [1, "&biguplus;"], [1, "&bigsqcup;"], [5, "&iiiint;"], [0, "&fpartint;"], [2, "&cirfnint;"], [0, "&awint;"], [0, "&rppolint;"], [0, "&scpolint;"], [0, "&npolint;"], [0, "&pointint;"], [0, "&quatint;"], [0, "&intlarhk;"], [10, "&pluscir;"], [0, "&plusacir;"], [0, "&simplus;"], [0, "&plusdu;"], [0, "&plussim;"], [0, "&plustwo;"], [1, "&mcomma;"], [0, "&minusdu;"], [2, "&loplus;"], [0, "&roplus;"], [0, "&Cross;"], [0, "&timesd;"], [0, "&timesbar;"], [1, "&smashp;"], [0, "&lotimes;"], [0, "&rotimes;"], [0, "&otimesas;"], [0, "&Otimes;"], [0, "&odiv;"], [0, "&triplus;"], [0, "&triminus;"], [0, "&tritime;"], [0, "&intprod;"], [2, "&amalg;"], [0, "&capdot;"], [1, "&ncup;"], [0, "&ncap;"], [0, "&capand;"], [0, "&cupor;"], [0, "&cupcap;"], [0, "&capcup;"], [0, "&cupbrcap;"], [0, "&capbrcup;"], [0, "&cupcup;"], [0, "&capcap;"], [0, "&ccups;"], [0, "&ccaps;"], [2, "&ccupssm;"], [2, "&And;"], [0, "&Or;"], [0, "&andand;"], [0, "&oror;"], [0, "&orslope;"], [0, "&andslope;"], [1, "&andv;"], [0, "&orv;"], [0, "&andd;"], [0, "&ord;"], [1, "&wedbar;"], [6, "&sdote;"], [3, "&simdot;"], [2, { v: "&congdot;", n: 824, o: "&ncongdot;" }], [0, "&easter;"], [0, "&apacir;"], [0, { v: "&apE;", n: 824, o: "&napE;" }], [0, "&eplus;"], [0, "&pluse;"], [0, "&Esim;"], [0, "&Colone;"], [0, "&Equal;"], [1, "&ddotseq;"], [0, "&equivDD;"], [0, "&ltcir;"], [0, "&gtcir;"], [0, "&ltquest;"], [0, "&gtquest;"], [0, { v: "&leqslant;", n: 824, o: "&nleqslant;" }], [0, { v: "&geqslant;", n: 824, o: "&ngeqslant;" }], [0, "&lesdot;"], [0, "&gesdot;"], [0, "&lesdoto;"], [0, "&gesdoto;"], [0, "&lesdotor;"], [0, "&gesdotol;"], [0, "&lap;"], [0, "&gap;"], [0, "&lne;"], [0, "&gne;"], [0, "&lnap;"], [0, "&gnap;"], [0, "&lEg;"], [0, "&gEl;"], [0, "&lsime;"], [0, "&gsime;"], [0, "&lsimg;"], [0, "&gsiml;"], [0, "&lgE;"], [0, "&glE;"], [0, "&lesges;"], [0, "&gesles;"], [0, "&els;"], [0, "&egs;"], [0, "&elsdot;"], [0, "&egsdot;"], [0, "&el;"], [0, "&eg;"], [2, "&siml;"], [0, "&simg;"], [0, "&simlE;"], [0, "&simgE;"], [0, { v: "&LessLess;", n: 824, o: "&NotNestedLessLess;" }], [0, { v: "&GreaterGreater;", n: 824, o: "&NotNestedGreaterGreater;" }], [1, "&glj;"], [0, "&gla;"], [0, "&ltcc;"], [0, "&gtcc;"], [0, "&lescc;"], [0, "&gescc;"], [0, "&smt;"], [0, "&lat;"], [0, { v: "&smte;", n: 65024, o: "&smtes;" }], [0, { v: "&late;", n: 65024, o: "&lates;" }], [0, "&bumpE;"], [0, { v: "&PrecedesEqual;", n: 824, o: "&NotPrecedesEqual;" }], [0, { v: "&sce;", n: 824, o: "&NotSucceedsEqual;" }], [2, "&prE;"], [0, "&scE;"], [0, "&precneqq;"], [0, "&scnE;"], [0, "&prap;"], [0, "&scap;"], [0, "&precnapprox;"], [0, "&scnap;"], [0, "&Pr;"], [0, "&Sc;"], [0, "&subdot;"], [0, "&supdot;"], [0, "&subplus;"], [0, "&supplus;"], [0, "&submult;"], [0, "&supmult;"], [0, "&subedot;"], [0, "&supedot;"], [0, { v: "&subE;", n: 824, o: "&nsubE;" }], [0, { v: "&supE;", n: 824, o: "&nsupE;" }], [0, "&subsim;"], [0, "&supsim;"], [2, { v: "&subnE;", n: 65024, o: "&varsubsetneqq;" }], [0, { v: "&supnE;", n: 65024, o: "&varsupsetneqq;" }], [2, "&csub;"], [0, "&csup;"], [0, "&csube;"], [0, "&csupe;"], [0, "&subsup;"], [0, "&supsub;"], [0, "&subsub;"], [0, "&supsup;"], [0, "&suphsub;"], [0, "&supdsub;"], [0, "&forkv;"], [0, "&topfork;"], [0, "&mlcp;"], [8, "&Dashv;"], [1, "&Vdashl;"], [0, "&Barv;"], [0, "&vBar;"], [0, "&vBarv;"], [1, "&Vbar;"], [0, "&Not;"], [0, "&bNot;"], [0, "&rnmid;"], [0, "&cirmid;"], [0, "&midcir;"], [0, "&topcir;"], [0, "&nhpar;"], [0, "&parsim;"], [9, { v: "&parsl;", n: 8421, o: "&nparsl;" }], [44343, { n: new Map(/* #__PURE__ */ restoreDiff([[56476, "&Ascr;"], [1, "&Cscr;"], [0, "&Dscr;"], [2, "&Gscr;"], [2, "&Jscr;"], [0, "&Kscr;"], [2, "&Nscr;"], [0, "&Oscr;"], [0, "&Pscr;"], [0, "&Qscr;"], [1, "&Sscr;"], [0, "&Tscr;"], [0, "&Uscr;"], [0, "&Vscr;"], [0, "&Wscr;"], [0, "&Xscr;"], [0, "&Yscr;"], [0, "&Zscr;"], [0, "&ascr;"], [0, "&bscr;"], [0, "&cscr;"], [0, "&dscr;"], [1, "&fscr;"], [1, "&hscr;"], [0, "&iscr;"], [0, "&jscr;"], [0, "&kscr;"], [0, "&lscr;"], [0, "&mscr;"], [0, "&nscr;"], [1, "&pscr;"], [0, "&qscr;"], [0, "&rscr;"], [0, "&sscr;"], [0, "&tscr;"], [0, "&uscr;"], [0, "&vscr;"], [0, "&wscr;"], [0, "&xscr;"], [0, "&yscr;"], [0, "&zscr;"], [52, "&Afr;"], [0, "&Bfr;"], [1, "&Dfr;"], [0, "&Efr;"], [0, "&Ffr;"], [0, "&Gfr;"], [2, "&Jfr;"], [0, "&Kfr;"], [0, "&Lfr;"], [0, "&Mfr;"], [0, "&Nfr;"], [0, "&Ofr;"], [0, "&Pfr;"], [0, "&Qfr;"], [1, "&Sfr;"], [0, "&Tfr;"], [0, "&Ufr;"], [0, "&Vfr;"], [0, "&Wfr;"], [0, "&Xfr;"], [0, "&Yfr;"], [1, "&afr;"], [0, "&bfr;"], [0, "&cfr;"], [0, "&dfr;"], [0, "&efr;"], [0, "&ffr;"], [0, "&gfr;"], [0, "&hfr;"], [0, "&ifr;"], [0, "&jfr;"], [0, "&kfr;"], [0, "&lfr;"], [0, "&mfr;"], [0, "&nfr;"], [0, "&ofr;"], [0, "&pfr;"], [0, "&qfr;"], [0, "&rfr;"], [0, "&sfr;"], [0, "&tfr;"], [0, "&ufr;"], [0, "&vfr;"], [0, "&wfr;"], [0, "&xfr;"], [0, "&yfr;"], [0, "&zfr;"], [0, "&Aopf;"], [0, "&Bopf;"], [1, "&Dopf;"], [0, "&Eopf;"], [0, "&Fopf;"], [0, "&Gopf;"], [1, "&Iopf;"], [0, "&Jopf;"], [0, "&Kopf;"], [0, "&Lopf;"], [0, "&Mopf;"], [1, "&Oopf;"], [3, "&Sopf;"], [0, "&Topf;"], [0, "&Uopf;"], [0, "&Vopf;"], [0, "&Wopf;"], [0, "&Xopf;"], [0, "&Yopf;"], [1, "&aopf;"], [0, "&bopf;"], [0, "&copf;"], [0, "&dopf;"], [0, "&eopf;"], [0, "&fopf;"], [0, "&gopf;"], [0, "&hopf;"], [0, "&iopf;"], [0, "&jopf;"], [0, "&kopf;"], [0, "&lopf;"], [0, "&mopf;"], [0, "&nopf;"], [0, "&oopf;"], [0, "&popf;"], [0, "&qopf;"], [0, "&ropf;"], [0, "&sopf;"], [0, "&topf;"], [0, "&uopf;"], [0, "&vopf;"], [0, "&wopf;"], [0, "&xopf;"], [0, "&yopf;"], [0, "&zopf;"]])) }], [8906, "&fflig;"], [0, "&filig;"], [0, "&fllig;"], [0, "&ffilig;"], [0, "&ffllig;"]]));
var _escape = {};
(function (exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.escapeText = exports.escapeAttribute = exports.escapeUTF8 = exports.escape = exports.encodeXML = exports.getCodePoint = exports.xmlReplacer = void 0;
exports.xmlReplacer = /["&'<>$\x80-\uFFFF]/g;
var xmlCodeMap = new Map([
[34, "&quot;"],
[38, "&amp;"],
[39, "&apos;"],
[60, "&lt;"],
[62, "&gt;"],
]);
// For compatibility with node < 4, we wrap `codePointAt`
exports.getCodePoint =
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
String.prototype.codePointAt != null
? function (str, index) { return str.codePointAt(index); }
: // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
function (c, index) {
return (c.charCodeAt(index) & 0xfc00) === 0xd800
? (c.charCodeAt(index) - 0xd800) * 0x400 +
c.charCodeAt(index + 1) -
0xdc00 +
0x10000
: c.charCodeAt(index);
};
/**
* Encodes all non-ASCII characters, as well as characters not valid in XML
* documents using XML entities.
*
* If a character has no equivalent entity, a
* numeric hexadecimal reference (eg. `&#xfc;`) will be used.
*/
function encodeXML(str) {
var ret = "";
var lastIdx = 0;
var match;
while ((match = exports.xmlReplacer.exec(str)) !== null) {
var i = match.index;
var char = str.charCodeAt(i);
var next = xmlCodeMap.get(char);
if (next !== undefined) {
ret += str.substring(lastIdx, i) + next;
lastIdx = i + 1;
}
else {
ret += "".concat(str.substring(lastIdx, i), "&#x").concat((0, exports.getCodePoint)(str, i).toString(16), ";");
// Increase by 1 if we have a surrogate pair
lastIdx = exports.xmlReplacer.lastIndex += Number((char & 0xfc00) === 0xd800);
}
}
return ret + str.substr(lastIdx);
}
exports.encodeXML = encodeXML;
/**
* Encodes all non-ASCII characters, as well as characters not valid in XML
* documents using numeric hexadecimal reference (eg. `&#xfc;`).
*
* Have a look at `escapeUTF8` if you want a more concise output at the expense
* of reduced transportability.
*
* @param data String to escape.
*/
exports.escape = encodeXML;
/**
* Creates a function that escapes all characters matched by the given regular
* expression using the given map of characters to escape to their entities.
*
* @param regex Regular expression to match characters to escape.
* @param map Map of characters to escape to their entities.
*
* @returns Function that escapes all characters matched by the given regular
* expression using the given map of characters to escape to their entities.
*/
function getEscaper(regex, map) {
return function escape(data) {
var match;
var lastIdx = 0;
var result = "";
while ((match = regex.exec(data))) {
if (lastIdx !== match.index) {
result += data.substring(lastIdx, match.index);
}
// We know that this character will be in the map.
result += map.get(match[0].charCodeAt(0));
// Every match will be of length 1
lastIdx = match.index + 1;
}
return result + data.substring(lastIdx);
};
}
/**
* Encodes all characters not valid in XML documents using XML entities.
*
* Note that the output will be character-set dependent.
*
* @param data String to escape.
*/
exports.escapeUTF8 = getEscaper(/[&<>'"]/g, xmlCodeMap);
/**
* Encodes all characters that have to be escaped in HTML attributes,
* following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}.
*
* @param data String to escape.
*/
exports.escapeAttribute = getEscaper(/["&\u00A0]/g, new Map([
[34, "&quot;"],
[38, "&amp;"],
[160, "&nbsp;"],
]));
/**
* Encodes all characters that have to be escaped in HTML text,
* following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}.
*
* @param data String to escape.
*/
exports.escapeText = getEscaper(/[&<>\u00A0]/g, new Map([
[38, "&amp;"],
[60, "&lt;"],
[62, "&gt;"],
[160, "&nbsp;"],
]));
} (_escape));
var __importDefault$3 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(encode$6, "__esModule", { value: true });
encode$6.encodeNonAsciiHTML = encode$6.encodeHTML = void 0;
var encode_html_js_1 = __importDefault$3(encodeHtml);
var escape_js_1 = _escape;
var htmlReplacer = /[\t\n!-,./:-@[-`\f{-}$\x80-\uFFFF]/g;
/**
* Encodes all characters in the input using HTML entities. This includes
* characters that are valid ASCII characters in HTML documents, such as `#`.
*
* To get a more compact output, consider using the `encodeNonAsciiHTML`
* function, which will only encode characters that are not valid in HTML
* documents, as well as non-ASCII characters.
*
* If a character has no equivalent entity, a numeric hexadecimal reference
* (eg. `&#xfc;`) will be used.
*/
function encodeHTML(data) {
return encodeHTMLTrieRe(htmlReplacer, data);
}
encode$6.encodeHTML = encodeHTML;
/**
* Encodes all non-ASCII characters, as well as characters not valid in HTML
* documents using HTML entities. This function will not encode characters that
* are valid in HTML documents, such as `#`.
*
* If a character has no equivalent entity, a numeric hexadecimal reference
* (eg. `&#xfc;`) will be used.
*/
function encodeNonAsciiHTML(data) {
return encodeHTMLTrieRe(escape_js_1.xmlReplacer, data);
}
encode$6.encodeNonAsciiHTML = encodeNonAsciiHTML;
function encodeHTMLTrieRe(regExp, str) {
var ret = "";
var lastIdx = 0;
var match;
while ((match = regExp.exec(str)) !== null) {
var i = match.index;
ret += str.substring(lastIdx, i);
var char = str.charCodeAt(i);
var next = encode_html_js_1.default.get(char);
if (typeof next === "object") {
// We are in a branch. Try to match the next char.
if (i + 1 < str.length) {
var nextChar = str.charCodeAt(i + 1);
var value = typeof next.n === "number"
? next.n === nextChar
? next.o
: undefined
: next.n.get(nextChar);
if (value !== undefined) {
ret += value;
lastIdx = regExp.lastIndex += 1;
continue;
}
}
next = next.v;
}
// We might have a tree node without a value; skip and use a numeric entity.
if (next !== undefined) {
ret += next;
lastIdx = i + 1;
}
else {
var cp = (0, escape_js_1.getCodePoint)(str, i);
ret += "&#x".concat(cp.toString(16), ";");
// Increase by 1 if we have a surrogate pair
lastIdx = regExp.lastIndex += Number(cp !== char);
}
}
return ret + str.substr(lastIdx);
}
(function (exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.decodeXMLStrict = exports.decodeHTML5Strict = exports.decodeHTML4Strict = exports.decodeHTML5 = exports.decodeHTML4 = exports.decodeHTMLAttribute = exports.decodeHTMLStrict = exports.decodeHTML = exports.decodeXML = exports.DecodingMode = exports.EntityDecoder = exports.encodeHTML5 = exports.encodeHTML4 = exports.encodeNonAsciiHTML = exports.encodeHTML = exports.escapeText = exports.escapeAttribute = exports.escapeUTF8 = exports.escape = exports.encodeXML = exports.encode = exports.decodeStrict = exports.decode = exports.EncodingMode = exports.EntityLevel = void 0;
var decode_js_1 = decode$6;
var encode_js_1 = encode$6;
var escape_js_1 = _escape;
/** The level of entities to support. */
var EntityLevel;
(function (EntityLevel) {
/** Support only XML entities. */
EntityLevel[EntityLevel["XML"] = 0] = "XML";
/** Support HTML entities, which are a superset of XML entities. */
EntityLevel[EntityLevel["HTML"] = 1] = "HTML";
})(EntityLevel = exports.EntityLevel || (exports.EntityLevel = {}));
var EncodingMode;
(function (EncodingMode) {
/**
* The output is UTF-8 encoded. Only characters that need escaping within
* XML will be escaped.
*/
EncodingMode[EncodingMode["UTF8"] = 0] = "UTF8";
/**
* The output consists only of ASCII characters. Characters that need
* escaping within HTML, and characters that aren't ASCII characters will
* be escaped.
*/
EncodingMode[EncodingMode["ASCII"] = 1] = "ASCII";
/**
* Encode all characters that have an equivalent entity, as well as all
* characters that are not ASCII characters.
*/
EncodingMode[EncodingMode["Extensive"] = 2] = "Extensive";
/**
* Encode all characters that have to be escaped in HTML attributes,
* following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}.
*/
EncodingMode[EncodingMode["Attribute"] = 3] = "Attribute";
/**
* Encode all characters that have to be escaped in HTML text,
* following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}.
*/
EncodingMode[EncodingMode["Text"] = 4] = "Text";
})(EncodingMode = exports.EncodingMode || (exports.EncodingMode = {}));
/**
* Decodes a string with entities.
*
* @param data String to decode.
* @param options Decoding options.
*/
function decode(data, options) {
if (options === void 0) { options = EntityLevel.XML; }
var level = typeof options === "number" ? options : options.level;
if (level === EntityLevel.HTML) {
var mode = typeof options === "object" ? options.mode : undefined;
return (0, decode_js_1.decodeHTML)(data, mode);
}
return (0, decode_js_1.decodeXML)(data);
}
exports.decode = decode;
/**
* Decodes a string with entities. Does not allow missing trailing semicolons for entities.
*
* @param data String to decode.
* @param options Decoding options.
* @deprecated Use `decode` with the `mode` set to `Strict`.
*/
function decodeStrict(data, options) {
var _a;
if (options === void 0) { options = EntityLevel.XML; }
var opts = typeof options === "number" ? { level: options } : options;
(_a = opts.mode) !== null && _a !== void 0 ? _a : (opts.mode = decode_js_1.DecodingMode.Strict);
return decode(data, opts);
}
exports.decodeStrict = decodeStrict;
/**
* Encodes a string with entities.
*
* @param data String to encode.
* @param options Encoding options.
*/
function encode(data, options) {
if (options === void 0) { options = EntityLevel.XML; }
var opts = typeof options === "number" ? { level: options } : options;
// Mode `UTF8` just escapes XML entities
if (opts.mode === EncodingMode.UTF8)
return (0, escape_js_1.escapeUTF8)(data);
if (opts.mode === EncodingMode.Attribute)
return (0, escape_js_1.escapeAttribute)(data);
if (opts.mode === EncodingMode.Text)
return (0, escape_js_1.escapeText)(data);
if (opts.level === EntityLevel.HTML) {
if (opts.mode === EncodingMode.ASCII) {
return (0, encode_js_1.encodeNonAsciiHTML)(data);
}
return (0, encode_js_1.encodeHTML)(data);
}
// ASCII and Extensive are equivalent
return (0, escape_js_1.encodeXML)(data);
}
exports.encode = encode;
var escape_js_2 = _escape;
Object.defineProperty(exports, "encodeXML", { enumerable: true, get: function () { return escape_js_2.encodeXML; } });
Object.defineProperty(exports, "escape", { enumerable: true, get: function () { return escape_js_2.escape; } });
Object.defineProperty(exports, "escapeUTF8", { enumerable: true, get: function () { return escape_js_2.escapeUTF8; } });
Object.defineProperty(exports, "escapeAttribute", { enumerable: true, get: function () { return escape_js_2.escapeAttribute; } });
Object.defineProperty(exports, "escapeText", { enumerable: true, get: function () { return escape_js_2.escapeText; } });
var encode_js_2 = encode$6;
Object.defineProperty(exports, "encodeHTML", { enumerable: true, get: function () { return encode_js_2.encodeHTML; } });
Object.defineProperty(exports, "encodeNonAsciiHTML", { enumerable: true, get: function () { return encode_js_2.encodeNonAsciiHTML; } });
// Legacy aliases (deprecated)
Object.defineProperty(exports, "encodeHTML4", { enumerable: true, get: function () { return encode_js_2.encodeHTML; } });
Object.defineProperty(exports, "encodeHTML5", { enumerable: true, get: function () { return encode_js_2.encodeHTML; } });
var decode_js_2 = decode$6;
Object.defineProperty(exports, "EntityDecoder", { enumerable: true, get: function () { return decode_js_2.EntityDecoder; } });
Object.defineProperty(exports, "DecodingMode", { enumerable: true, get: function () { return decode_js_2.DecodingMode; } });
Object.defineProperty(exports, "decodeXML", { enumerable: true, get: function () { return decode_js_2.decodeXML; } });
Object.defineProperty(exports, "decodeHTML", { enumerable: true, get: function () { return decode_js_2.decodeHTML; } });
Object.defineProperty(exports, "decodeHTMLStrict", { enumerable: true, get: function () { return decode_js_2.decodeHTMLStrict; } });
Object.defineProperty(exports, "decodeHTMLAttribute", { enumerable: true, get: function () { return decode_js_2.decodeHTMLAttribute; } });
// Legacy aliases (deprecated)
Object.defineProperty(exports, "decodeHTML4", { enumerable: true, get: function () { return decode_js_2.decodeHTML; } });
Object.defineProperty(exports, "decodeHTML5", { enumerable: true, get: function () { return decode_js_2.decodeHTML; } });
Object.defineProperty(exports, "decodeHTML4Strict", { enumerable: true, get: function () { return decode_js_2.decodeHTMLStrict; } });
Object.defineProperty(exports, "decodeHTML5Strict", { enumerable: true, get: function () { return decode_js_2.decodeHTMLStrict; } });
Object.defineProperty(exports, "decodeXMLStrict", { enumerable: true, get: function () { return decode_js_2.decodeXML; } });
} (lib));
var foreignNames = {};
Object.defineProperty(foreignNames, "__esModule", { value: true });
foreignNames.attributeNames = foreignNames.elementNames = void 0;
foreignNames.elementNames = new Map([
"altGlyph",
"altGlyphDef",
"altGlyphItem",
"animateColor",
"animateMotion",
"animateTransform",
"clipPath",
"feBlend",
"feColorMatrix",
"feComponentTransfer",
"feComposite",
"feConvolveMatrix",
"feDiffuseLighting",
"feDisplacementMap",
"feDistantLight",
"feDropShadow",
"feFlood",
"feFuncA",
"feFuncB",
"feFuncG",
"feFuncR",
"feGaussianBlur",
"feImage",
"feMerge",
"feMergeNode",
"feMorphology",
"feOffset",
"fePointLight",
"feSpecularLighting",
"feSpotLight",
"feTile",
"feTurbulence",
"foreignObject",
"glyphRef",
"linearGradient",
"radialGradient",
"textPath",
].map(function (val) { return [val.toLowerCase(), val]; }));
foreignNames.attributeNames = new Map([
"definitionURL",
"attributeName",
"attributeType",
"baseFrequency",
"baseProfile",
"calcMode",
"clipPathUnits",
"diffuseConstant",
"edgeMode",
"filterUnits",
"glyphRef",
"gradientTransform",
"gradientUnits",
"kernelMatrix",
"kernelUnitLength",
"keyPoints",
"keySplines",
"keyTimes",
"lengthAdjust",
"limitingConeAngle",
"markerHeight",
"markerUnits",
"markerWidth",
"maskContentUnits",
"maskUnits",
"numOctaves",
"pathLength",
"patternContentUnits",
"patternTransform",
"patternUnits",
"pointsAtX",
"pointsAtY",
"pointsAtZ",
"preserveAlpha",
"preserveAspectRatio",
"primitiveUnits",
"refX",
"refY",
"repeatCount",
"repeatDur",
"requiredExtensions",
"requiredFeatures",
"specularConstant",
"specularExponent",
"spreadMethod",
"startOffset",
"stdDeviation",
"stitchTiles",
"surfaceScale",
"systemLanguage",
"tableValues",
"targetX",
"targetY",
"textLength",
"viewBox",
"viewTarget",
"xChannelSelector",
"yChannelSelector",
"zoomAndPan",
].map(function (val) { return [val.toLowerCase(), val]; }));
var __assign = (commonjsGlobal && commonjsGlobal.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __createBinding$1 = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault$1 = (commonjsGlobal && commonjsGlobal.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar$1 = (commonjsGlobal && commonjsGlobal.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding$1(result, mod, k);
__setModuleDefault$1(result, mod);
return result;
};
Object.defineProperty(lib$1, "__esModule", { value: true });
lib$1.render = void 0;
/*
* Module dependencies
*/
var ElementType = __importStar$1(require$$0$6);
var entities_1 = lib;
/**
* Mixed-case SVG and MathML tags & attributes
* recognized by the HTML parser.
*
* @see https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inforeign
*/
var foreignNames_js_1 = foreignNames;
var unencodedElements = new Set([
"style",
"script",
"xmp",
"iframe",
"noembed",
"noframes",
"plaintext",
"noscript",
]);
function replaceQuotes(value) {
return value.replace(/"/g, "&quot;");
}
/**
* Format attributes
*/
function formatAttributes(attributes, opts) {
var _a;
if (!attributes)
return;
var encode = ((_a = opts.encodeEntities) !== null && _a !== void 0 ? _a : opts.decodeEntities) === false
? replaceQuotes
: opts.xmlMode || opts.encodeEntities !== "utf8"
? entities_1.encodeXML
: entities_1.escapeAttribute;
return Object.keys(attributes)
.map(function (key) {
var _a, _b;
var value = (_a = attributes[key]) !== null && _a !== void 0 ? _a : "";
if (opts.xmlMode === "foreign") {
/* Fix up mixed-case attribute names */
key = (_b = foreignNames_js_1.attributeNames.get(key)) !== null && _b !== void 0 ? _b : key;
}
if (!opts.emptyAttrs && !opts.xmlMode && value === "") {
return key;
}
return "".concat(key, "=\"").concat(encode(value), "\"");
})
.join(" ");
}
/**
* Self-enclosing tags
*/
var singleTag = new Set([
"area",
"base",
"basefont",
"br",
"col",
"command",
"embed",
"frame",
"hr",
"img",
"input",
"isindex",
"keygen",
"link",
"meta",
"param",
"source",
"track",
"wbr",
]);
/**
* Renders a DOM node or an array of DOM nodes to a string.
*
* Can be thought of as the equivalent of the `outerHTML` of the passed node(s).
*
* @param node Node to be rendered.
* @param options Changes serialization behavior
*/
function render(node, options) {
if (options === void 0) { options = {}; }
var nodes = "length" in node ? node : [node];
var output = "";
for (var i = 0; i < nodes.length; i++) {
output += renderNode(nodes[i], options);
}
return output;
}
lib$1.render = render;
lib$1.default = render;
function renderNode(node, options) {
switch (node.type) {
case ElementType.Root:
return render(node.children, options);
// @ts-expect-error We don't use `Doctype` yet
case ElementType.Doctype:
case ElementType.Directive:
return renderDirective(node);
case ElementType.Comment:
return renderComment(node);
case ElementType.CDATA:
return renderCdata(node);
case ElementType.Script:
case ElementType.Style:
case ElementType.Tag:
return renderTag(node, options);
case ElementType.Text:
return renderText(node, options);
}
}
var foreignModeIntegrationPoints = new Set([
"mi",
"mo",
"mn",
"ms",
"mtext",
"annotation-xml",
"foreignObject",
"desc",
"title",
]);
var foreignElements = new Set(["svg", "math"]);
function renderTag(elem, opts) {
var _a;
// Handle SVG / MathML in HTML
if (opts.xmlMode === "foreign") {
/* Fix up mixed-case element names */
elem.name = (_a = foreignNames_js_1.elementNames.get(elem.name)) !== null && _a !== void 0 ? _a : elem.name;
/* Exit foreign mode at integration points */
if (elem.parent &&
foreignModeIntegrationPoints.has(elem.parent.name)) {
opts = __assign(__assign({}, opts), { xmlMode: false });
}
}
if (!opts.xmlMode && foreignElements.has(elem.name)) {
opts = __assign(__assign({}, opts), { xmlMode: "foreign" });
}
var tag = "<".concat(elem.name);
var attribs = formatAttributes(elem.attribs, opts);
if (attribs) {
tag += " ".concat(attribs);
}
if (elem.children.length === 0 &&
(opts.xmlMode
? // In XML mode or foreign mode, and user hasn't explicitly turned off self-closing tags
opts.selfClosingTags !== false
: // User explicitly asked for self-closing tags, even in HTML mode
opts.selfClosingTags && singleTag.has(elem.name))) {
if (!opts.xmlMode)
tag += " ";
tag += "/>";
}
else {
tag += ">";
if (elem.children.length > 0) {
tag += render(elem.children, opts);
}
if (opts.xmlMode || !singleTag.has(elem.name)) {
tag += "</".concat(elem.name, ">");
}
}
return tag;
}
function renderDirective(elem) {
return "<".concat(elem.data, ">");
}
function renderText(elem, opts) {
var _a;
var data = elem.data || "";
// If entities weren't decoded, no need to encode them back
if (((_a = opts.encodeEntities) !== null && _a !== void 0 ? _a : opts.decodeEntities) !== false &&
!(!opts.xmlMode &&
elem.parent &&
unencodedElements.has(elem.parent.name))) {
data =
opts.xmlMode || opts.encodeEntities !== "utf8"
? (0, entities_1.encodeXML)(data)
: (0, entities_1.escapeText)(data);
}
return data;
}
function renderCdata(elem) {
return "<![CDATA[".concat(elem.children[0].data, "]]>");
}
function renderComment(elem) {
return "<!--".concat(elem.data, "-->");
}
var __importDefault$2 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(stringify, "__esModule", { value: true });
stringify.innerText = stringify.textContent = stringify.getText = stringify.getInnerHTML = stringify.getOuterHTML = void 0;
var domhandler_1$3 = lib$2;
var dom_serializer_1 = __importDefault$2(lib$1);
var domelementtype_1 = require$$0$6;
/**
* @category Stringify
* @deprecated Use the `dom-serializer` module directly.
* @param node Node to get the outer HTML of.
* @param options Options for serialization.
* @returns `node`'s outer HTML.
*/
function getOuterHTML(node, options) {
return (0, dom_serializer_1.default)(node, options);
}
stringify.getOuterHTML = getOuterHTML;
/**
* @category Stringify
* @deprecated Use the `dom-serializer` module directly.
* @param node Node to get the inner HTML of.
* @param options Options for serialization.
* @returns `node`'s inner HTML.
*/
function getInnerHTML(node, options) {
return (0, domhandler_1$3.hasChildren)(node)
? node.children.map(function (node) { return getOuterHTML(node, options); }).join("")
: "";
}
stringify.getInnerHTML = getInnerHTML;
/**
* Get a node's inner text. Same as `textContent`, but inserts newlines for `<br>` tags. Ignores comments.
*
* @category Stringify
* @deprecated Use `textContent` instead.
* @param node Node to get the inner text of.
* @returns `node`'s inner text.
*/
function getText$1(node) {
if (Array.isArray(node))
return node.map(getText$1).join("");
if ((0, domhandler_1$3.isTag)(node))
return node.name === "br" ? "\n" : getText$1(node.children);
if ((0, domhandler_1$3.isCDATA)(node))
return getText$1(node.children);
if ((0, domhandler_1$3.isText)(node))
return node.data;
return "";
}
stringify.getText = getText$1;
/**
* Get a node's text content. Ignores comments.
*
* @category Stringify
* @param node Node to get the text content of.
* @returns `node`'s text content.
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent}
*/
function textContent(node) {
if (Array.isArray(node))
return node.map(textContent).join("");
if ((0, domhandler_1$3.hasChildren)(node) && !(0, domhandler_1$3.isComment)(node)) {
return textContent(node.children);
}
if ((0, domhandler_1$3.isText)(node))
return node.data;
return "";
}
stringify.textContent = textContent;
/**
* Get a node's inner text, ignoring `<script>` and `<style>` tags. Ignores comments.
*
* @category Stringify
* @param node Node to get the inner text of.
* @returns `node`'s inner text.
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/innerText}
*/
function innerText(node) {
if (Array.isArray(node))
return node.map(innerText).join("");
if ((0, domhandler_1$3.hasChildren)(node) && (node.type === domelementtype_1.ElementType.Tag || (0, domhandler_1$3.isCDATA)(node))) {
return innerText(node.children);
}
if ((0, domhandler_1$3.isText)(node))
return node.data;
return "";
}
stringify.innerText = innerText;
var traversal = {};
Object.defineProperty(traversal, "__esModule", { value: true });
traversal.prevElementSibling = traversal.nextElementSibling = traversal.getName = traversal.hasAttrib = traversal.getAttributeValue = traversal.getSiblings = traversal.getParent = traversal.getChildren = void 0;
var domhandler_1$2 = lib$2;
/**
* Get a node's children.
*
* @category Traversal
* @param elem Node to get the children of.
* @returns `elem`'s children, or an empty array.
*/
function getChildren$1(elem) {
return (0, domhandler_1$2.hasChildren)(elem) ? elem.children : [];
}
traversal.getChildren = getChildren$1;
/**
* Get a node's parent.
*
* @category Traversal
* @param elem Node to get the parent of.
* @returns `elem`'s parent node, or `null` if `elem` is a root node.
*/
function getParent$1(elem) {
return elem.parent || null;
}
traversal.getParent = getParent$1;
/**
* Gets an elements siblings, including the element itself.
*
* Attempts to get the children through the element's parent first. If we don't
* have a parent (the element is a root node), we walk the element's `prev` &
* `next` to get all remaining nodes.
*
* @category Traversal
* @param elem Element to get the siblings of.
* @returns `elem`'s siblings, including `elem`.
*/
function getSiblings$1(elem) {
var _a, _b;
var parent = getParent$1(elem);
if (parent != null)
return getChildren$1(parent);
var siblings = [elem];
var prev = elem.prev, next = elem.next;
while (prev != null) {
siblings.unshift(prev);
(_a = prev, prev = _a.prev);
}
while (next != null) {
siblings.push(next);
(_b = next, next = _b.next);
}
return siblings;
}
traversal.getSiblings = getSiblings$1;
/**
* Gets an attribute from an element.
*
* @category Traversal
* @param elem Element to check.
* @param name Attribute name to retrieve.
* @returns The element's attribute value, or `undefined`.
*/
function getAttributeValue$1(elem, name) {
var _a;
return (_a = elem.attribs) === null || _a === void 0 ? void 0 : _a[name];
}
traversal.getAttributeValue = getAttributeValue$1;
/**
* Checks whether an element has an attribute.
*
* @category Traversal
* @param elem Element to check.
* @param name Attribute name to look for.
* @returns Returns whether `elem` has the attribute `name`.
*/
function hasAttrib$1(elem, name) {
return (elem.attribs != null &&
Object.prototype.hasOwnProperty.call(elem.attribs, name) &&
elem.attribs[name] != null);
}
traversal.hasAttrib = hasAttrib$1;
/**
* Get the tag name of an element.
*
* @category Traversal
* @param elem The element to get the name for.
* @returns The tag name of `elem`.
*/
function getName$1(elem) {
return elem.name;
}
traversal.getName = getName$1;
/**
* Returns the next element sibling of a node.
*
* @category Traversal
* @param elem The element to get the next sibling of.
* @returns `elem`'s next sibling that is a tag, or `null` if there is no next
* sibling.
*/
function nextElementSibling(elem) {
var _a;
var next = elem.next;
while (next !== null && !(0, domhandler_1$2.isTag)(next))
(_a = next, next = _a.next);
return next;
}
traversal.nextElementSibling = nextElementSibling;
/**
* Returns the previous element sibling of a node.
*
* @category Traversal
* @param elem The element to get the previous sibling of.
* @returns `elem`'s previous sibling that is a tag, or `null` if there is no
* previous sibling.
*/
function prevElementSibling(elem) {
var _a;
var prev = elem.prev;
while (prev !== null && !(0, domhandler_1$2.isTag)(prev))
(_a = prev, prev = _a.prev);
return prev;
}
traversal.prevElementSibling = prevElementSibling;
var manipulation = {};
Object.defineProperty(manipulation, "__esModule", { value: true });
manipulation.prepend = manipulation.prependChild = manipulation.append = manipulation.appendChild = manipulation.replaceElement = manipulation.removeElement = void 0;
/**
* Remove an element from the dom
*
* @category Manipulation
* @param elem The element to be removed
*/
function removeElement(elem) {
if (elem.prev)
elem.prev.next = elem.next;
if (elem.next)
elem.next.prev = elem.prev;
if (elem.parent) {
var childs = elem.parent.children;
var childsIndex = childs.lastIndexOf(elem);
if (childsIndex >= 0) {
childs.splice(childsIndex, 1);
}
}
elem.next = null;
elem.prev = null;
elem.parent = null;
}
manipulation.removeElement = removeElement;
/**
* Replace an element in the dom
*
* @category Manipulation
* @param elem The element to be replaced
* @param replacement The element to be added
*/
function replaceElement(elem, replacement) {
var prev = (replacement.prev = elem.prev);
if (prev) {
prev.next = replacement;
}
var next = (replacement.next = elem.next);
if (next) {
next.prev = replacement;
}
var parent = (replacement.parent = elem.parent);
if (parent) {
var childs = parent.children;
childs[childs.lastIndexOf(elem)] = replacement;
elem.parent = null;
}
}
manipulation.replaceElement = replaceElement;
/**
* Append a child to an element.
*
* @category Manipulation
* @param parent The element to append to.
* @param child The element to be added as a child.
*/
function appendChild(parent, child) {
removeElement(child);
child.next = null;
child.parent = parent;
if (parent.children.push(child) > 1) {
var sibling = parent.children[parent.children.length - 2];
sibling.next = child;
child.prev = sibling;
}
else {
child.prev = null;
}
}
manipulation.appendChild = appendChild;
/**
* Append an element after another.
*
* @category Manipulation
* @param elem The element to append after.
* @param next The element be added.
*/
function append$1(elem, next) {
removeElement(next);
var parent = elem.parent;
var currNext = elem.next;
next.next = currNext;
next.prev = elem;
elem.next = next;
next.parent = parent;
if (currNext) {
currNext.prev = next;
if (parent) {
var childs = parent.children;
childs.splice(childs.lastIndexOf(currNext), 0, next);
}
}
else if (parent) {
parent.children.push(next);
}
}
manipulation.append = append$1;
/**
* Prepend a child to an element.
*
* @category Manipulation
* @param parent The element to prepend before.
* @param child The element to be added as a child.
*/
function prependChild(parent, child) {
removeElement(child);
child.parent = parent;
child.prev = null;
if (parent.children.unshift(child) !== 1) {
var sibling = parent.children[1];
sibling.prev = child;
child.next = sibling;
}
else {
child.next = null;
}
}
manipulation.prependChild = prependChild;
/**
* Prepend an element before another.
*
* @category Manipulation
* @param elem The element to prepend before.
* @param prev The element be added.
*/
function prepend(elem, prev) {
removeElement(prev);
var parent = elem.parent;
if (parent) {
var childs = parent.children;
childs.splice(childs.indexOf(elem), 0, prev);
}
if (elem.prev) {
elem.prev.next = prev;
}
prev.parent = parent;
prev.prev = elem.prev;
prev.next = elem;
elem.prev = prev;
}
manipulation.prepend = prepend;
var querying = {};
Object.defineProperty(querying, "__esModule", { value: true });
querying.findAll = querying.existsOne = querying.findOne = querying.findOneChild = querying.find = querying.filter = void 0;
var domhandler_1$1 = lib$2;
/**
* Search a node and its children for nodes passing a test function. If `node` is not an array, it will be wrapped in one.
*
* @category Querying
* @param test Function to test nodes on.
* @param node Node to search. Will be included in the result set if it matches.
* @param recurse Also consider child nodes.
* @param limit Maximum number of nodes to return.
* @returns All nodes passing `test`.
*/
function filter$2(test, node, recurse, limit) {
if (recurse === void 0) { recurse = true; }
if (limit === void 0) { limit = Infinity; }
return find$3(test, Array.isArray(node) ? node : [node], recurse, limit);
}
querying.filter = filter$2;
/**
* Search an array of nodes and their children for nodes passing a test function.
*
* @category Querying
* @param test Function to test nodes on.
* @param nodes Array of nodes to search.
* @param recurse Also consider child nodes.
* @param limit Maximum number of nodes to return.
* @returns All nodes passing `test`.
*/
function find$3(test, nodes, recurse, limit) {
var result = [];
/** Stack of the arrays we are looking at. */
var nodeStack = [nodes];
/** Stack of the indices within the arrays. */
var indexStack = [0];
for (;;) {
// First, check if the current array has any more elements to look at.
if (indexStack[0] >= nodeStack[0].length) {
// If we have no more arrays to look at, we are done.
if (indexStack.length === 1) {
return result;
}
// Otherwise, remove the current array from the stack.
nodeStack.shift();
indexStack.shift();
// Loop back to the start to continue with the next array.
continue;
}
var elem = nodeStack[0][indexStack[0]++];
if (test(elem)) {
result.push(elem);
if (--limit <= 0)
return result;
}
if (recurse && (0, domhandler_1$1.hasChildren)(elem) && elem.children.length > 0) {
/*
* Add the children to the stack. We are depth-first, so this is
* the next array we look at.
*/
indexStack.unshift(0);
nodeStack.unshift(elem.children);
}
}
}
querying.find = find$3;
/**
* Finds the first element inside of an array that matches a test function. This is an alias for `Array.prototype.find`.
*
* @category Querying
* @param test Function to test nodes on.
* @param nodes Array of nodes to search.
* @returns The first node in the array that passes `test`.
* @deprecated Use `Array.prototype.find` directly.
*/
function findOneChild(test, nodes) {
return nodes.find(test);
}
querying.findOneChild = findOneChild;
/**
* Finds one element in a tree that passes a test.
*
* @category Querying
* @param test Function to test nodes on.
* @param nodes Node or array of nodes to search.
* @param recurse Also consider child nodes.
* @returns The first node that passes `test`.
*/
function findOne$1(test, nodes, recurse) {
if (recurse === void 0) { recurse = true; }
var elem = null;
for (var i = 0; i < nodes.length && !elem; i++) {
var node = nodes[i];
if (!(0, domhandler_1$1.isTag)(node)) {
continue;
}
else if (test(node)) {
elem = node;
}
else if (recurse && node.children.length > 0) {
elem = findOne$1(test, node.children, true);
}
}
return elem;
}
querying.findOne = findOne$1;
/**
* Checks if a tree of nodes contains at least one node passing a test.
*
* @category Querying
* @param test Function to test nodes on.
* @param nodes Array of nodes to search.
* @returns Whether a tree of nodes contains at least one node passing the test.
*/
function existsOne$1(test, nodes) {
return nodes.some(function (checked) {
return (0, domhandler_1$1.isTag)(checked) &&
(test(checked) || existsOne$1(test, checked.children));
});
}
querying.existsOne = existsOne$1;
/**
* Search an array of nodes and their children for elements passing a test function.
*
* Same as `find`, but limited to elements and with less options, leading to reduced complexity.
*
* @category Querying
* @param test Function to test nodes on.
* @param nodes Array of nodes to search.
* @returns All nodes passing `test`.
*/
function findAll$4(test, nodes) {
var result = [];
var nodeStack = [nodes];
var indexStack = [0];
for (;;) {
if (indexStack[0] >= nodeStack[0].length) {
if (nodeStack.length === 1) {
return result;
}
// Otherwise, remove the current array from the stack.
nodeStack.shift();
indexStack.shift();
// Loop back to the start to continue with the next array.
continue;
}
var elem = nodeStack[0][indexStack[0]++];
if (!(0, domhandler_1$1.isTag)(elem))
continue;
if (test(elem))
result.push(elem);
if (elem.children.length > 0) {
indexStack.unshift(0);
nodeStack.unshift(elem.children);
}
}
}
querying.findAll = findAll$4;
var legacy = {};
Object.defineProperty(legacy, "__esModule", { value: true });
legacy.getElementsByTagType = legacy.getElementsByTagName = legacy.getElementById = legacy.getElements = legacy.testElement = void 0;
var domhandler_1 = lib$2;
var querying_js_1 = querying;
/**
* A map of functions to check nodes against.
*/
var Checks = {
tag_name: function (name) {
if (typeof name === "function") {
return function (elem) { return (0, domhandler_1.isTag)(elem) && name(elem.name); };
}
else if (name === "*") {
return domhandler_1.isTag;
}
return function (elem) { return (0, domhandler_1.isTag)(elem) && elem.name === name; };
},
tag_type: function (type) {
if (typeof type === "function") {
return function (elem) { return type(elem.type); };
}
return function (elem) { return elem.type === type; };
},
tag_contains: function (data) {
if (typeof data === "function") {
return function (elem) { return (0, domhandler_1.isText)(elem) && data(elem.data); };
}
return function (elem) { return (0, domhandler_1.isText)(elem) && elem.data === data; };
},
};
/**
* Returns a function to check whether a node has an attribute with a particular
* value.
*
* @param attrib Attribute to check.
* @param value Attribute value to look for.
* @returns A function to check whether the a node has an attribute with a
* particular value.
*/
function getAttribCheck(attrib, value) {
if (typeof value === "function") {
return function (elem) { return (0, domhandler_1.isTag)(elem) && value(elem.attribs[attrib]); };
}
return function (elem) { return (0, domhandler_1.isTag)(elem) && elem.attribs[attrib] === value; };
}
/**
* Returns a function that returns `true` if either of the input functions
* returns `true` for a node.
*
* @param a First function to combine.
* @param b Second function to combine.
* @returns A function taking a node and returning `true` if either of the input
* functions returns `true` for the node.
*/
function combineFuncs(a, b) {
return function (elem) { return a(elem) || b(elem); };
}
/**
* Returns a function that executes all checks in `options` and returns `true`
* if any of them match a node.
*
* @param options An object describing nodes to look for.
* @returns A function that executes all checks in `options` and returns `true`
* if any of them match a node.
*/
function compileTest(options) {
var funcs = Object.keys(options).map(function (key) {
var value = options[key];
return Object.prototype.hasOwnProperty.call(Checks, key)
? Checks[key](value)
: getAttribCheck(key, value);
});
return funcs.length === 0 ? null : funcs.reduce(combineFuncs);
}
/**
* Checks whether a node matches the description in `options`.
*
* @category Legacy Query Functions
* @param options An object describing nodes to look for.
* @param node The element to test.
* @returns Whether the element matches the description in `options`.
*/
function testElement(options, node) {
var test = compileTest(options);
return test ? test(node) : true;
}
legacy.testElement = testElement;
/**
* Returns all nodes that match `options`.
*
* @category Legacy Query Functions
* @param options An object describing nodes to look for.
* @param nodes Nodes to search through.
* @param recurse Also consider child nodes.
* @param limit Maximum number of nodes to return.
* @returns All nodes that match `options`.
*/
function getElements(options, nodes, recurse, limit) {
if (limit === void 0) { limit = Infinity; }
var test = compileTest(options);
return test ? (0, querying_js_1.filter)(test, nodes, recurse, limit) : [];
}
legacy.getElements = getElements;
/**
* Returns the node with the supplied ID.
*
* @category Legacy Query Functions
* @param id The unique ID attribute value to look for.
* @param nodes Nodes to search through.
* @param recurse Also consider child nodes.
* @returns The node with the supplied ID.
*/
function getElementById(id, nodes, recurse) {
if (recurse === void 0) { recurse = true; }
if (!Array.isArray(nodes))
nodes = [nodes];
return (0, querying_js_1.findOne)(getAttribCheck("id", id), nodes, recurse);
}
legacy.getElementById = getElementById;
/**
* Returns all nodes with the supplied `tagName`.
*
* @category Legacy Query Functions
* @param tagName Tag name to search for.
* @param nodes Nodes to search through.
* @param recurse Also consider child nodes.
* @param limit Maximum number of nodes to return.
* @returns All nodes with the supplied `tagName`.
*/
function getElementsByTagName(tagName, nodes, recurse, limit) {
if (recurse === void 0) { recurse = true; }
if (limit === void 0) { limit = Infinity; }
return (0, querying_js_1.filter)(Checks["tag_name"](tagName), nodes, recurse, limit);
}
legacy.getElementsByTagName = getElementsByTagName;
/**
* Returns all nodes with the supplied `type`.
*
* @category Legacy Query Functions
* @param type Element type to look for.
* @param nodes Nodes to search through.
* @param recurse Also consider child nodes.
* @param limit Maximum number of nodes to return.
* @returns All nodes with the supplied `type`.
*/
function getElementsByTagType(type, nodes, recurse, limit) {
if (recurse === void 0) { recurse = true; }
if (limit === void 0) { limit = Infinity; }
return (0, querying_js_1.filter)(Checks["tag_type"](type), nodes, recurse, limit);
}
legacy.getElementsByTagType = getElementsByTagType;
var helpers = {};
(function (exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.uniqueSort = exports.compareDocumentPosition = exports.DocumentPosition = exports.removeSubsets = void 0;
var domhandler_1 = lib$2;
/**
* Given an array of nodes, remove any member that is contained by another
* member.
*
* @category Helpers
* @param nodes Nodes to filter.
* @returns Remaining nodes that aren't contained by other nodes.
*/
function removeSubsets(nodes) {
var idx = nodes.length;
/*
* Check if each node (or one of its ancestors) is already contained in the
* array.
*/
while (--idx >= 0) {
var node = nodes[idx];
/*
* Remove the node if it is not unique.
* We are going through the array from the end, so we only
* have to check nodes that preceed the node under consideration in the array.
*/
if (idx > 0 && nodes.lastIndexOf(node, idx - 1) >= 0) {
nodes.splice(idx, 1);
continue;
}
for (var ancestor = node.parent; ancestor; ancestor = ancestor.parent) {
if (nodes.includes(ancestor)) {
nodes.splice(idx, 1);
break;
}
}
}
return nodes;
}
exports.removeSubsets = removeSubsets;
/**
* @category Helpers
* @see {@link http://dom.spec.whatwg.org/#dom-node-comparedocumentposition}
*/
var DocumentPosition;
(function (DocumentPosition) {
DocumentPosition[DocumentPosition["DISCONNECTED"] = 1] = "DISCONNECTED";
DocumentPosition[DocumentPosition["PRECEDING"] = 2] = "PRECEDING";
DocumentPosition[DocumentPosition["FOLLOWING"] = 4] = "FOLLOWING";
DocumentPosition[DocumentPosition["CONTAINS"] = 8] = "CONTAINS";
DocumentPosition[DocumentPosition["CONTAINED_BY"] = 16] = "CONTAINED_BY";
})(DocumentPosition = exports.DocumentPosition || (exports.DocumentPosition = {}));
/**
* Compare the position of one node against another node in any other document,
* returning a bitmask with the values from {@link DocumentPosition}.
*
* Document order:
* > There is an ordering, document order, defined on all the nodes in the
* > document corresponding to the order in which the first character of the
* > XML representation of each node occurs in the XML representation of the
* > document after expansion of general entities. Thus, the document element
* > node will be the first node. Element nodes occur before their children.
* > Thus, document order orders element nodes in order of the occurrence of
* > their start-tag in the XML (after expansion of entities). The attribute
* > nodes of an element occur after the element and before its children. The
* > relative order of attribute nodes is implementation-dependent.
*
* Source:
* http://www.w3.org/TR/DOM-Level-3-Core/glossary.html#dt-document-order
*
* @category Helpers
* @param nodeA The first node to use in the comparison
* @param nodeB The second node to use in the comparison
* @returns A bitmask describing the input nodes' relative position.
*
* See http://dom.spec.whatwg.org/#dom-node-comparedocumentposition for
* a description of these values.
*/
function compareDocumentPosition(nodeA, nodeB) {
var aParents = [];
var bParents = [];
if (nodeA === nodeB) {
return 0;
}
var current = (0, domhandler_1.hasChildren)(nodeA) ? nodeA : nodeA.parent;
while (current) {
aParents.unshift(current);
current = current.parent;
}
current = (0, domhandler_1.hasChildren)(nodeB) ? nodeB : nodeB.parent;
while (current) {
bParents.unshift(current);
current = current.parent;
}
var maxIdx = Math.min(aParents.length, bParents.length);
var idx = 0;
while (idx < maxIdx && aParents[idx] === bParents[idx]) {
idx++;
}
if (idx === 0) {
return DocumentPosition.DISCONNECTED;
}
var sharedParent = aParents[idx - 1];
var siblings = sharedParent.children;
var aSibling = aParents[idx];
var bSibling = bParents[idx];
if (siblings.indexOf(aSibling) > siblings.indexOf(bSibling)) {
if (sharedParent === nodeB) {
return DocumentPosition.FOLLOWING | DocumentPosition.CONTAINED_BY;
}
return DocumentPosition.FOLLOWING;
}
if (sharedParent === nodeA) {
return DocumentPosition.PRECEDING | DocumentPosition.CONTAINS;
}
return DocumentPosition.PRECEDING;
}
exports.compareDocumentPosition = compareDocumentPosition;
/**
* Sort an array of nodes based on their relative position in the document,
* removing any duplicate nodes. If the array contains nodes that do not belong
* to the same document, sort order is unspecified.
*
* @category Helpers
* @param nodes Array of DOM nodes.
* @returns Collection of unique nodes, sorted in document order.
*/
function uniqueSort(nodes) {
nodes = nodes.filter(function (node, i, arr) { return !arr.includes(node, i + 1); });
nodes.sort(function (a, b) {
var relative = compareDocumentPosition(a, b);
if (relative & DocumentPosition.PRECEDING) {
return -1;
}
else if (relative & DocumentPosition.FOLLOWING) {
return 1;
}
return 0;
});
return nodes;
}
exports.uniqueSort = uniqueSort;
} (helpers));
var feeds = {};
Object.defineProperty(feeds, "__esModule", { value: true });
feeds.getFeed = void 0;
var stringify_js_1 = stringify;
var legacy_js_1 = legacy;
/**
* Get the feed object from the root of a DOM tree.
*
* @category Feeds
* @param doc - The DOM to to extract the feed from.
* @returns The feed.
*/
function getFeed(doc) {
var feedRoot = getOneElement(isValidFeed, doc);
return !feedRoot
? null
: feedRoot.name === "feed"
? getAtomFeed(feedRoot)
: getRssFeed(feedRoot);
}
feeds.getFeed = getFeed;
/**
* Parse an Atom feed.
*
* @param feedRoot The root of the feed.
* @returns The parsed feed.
*/
function getAtomFeed(feedRoot) {
var _a;
var childs = feedRoot.children;
var feed = {
type: "atom",
items: (0, legacy_js_1.getElementsByTagName)("entry", childs).map(function (item) {
var _a;
var children = item.children;
var entry = { media: getMediaElements(children) };
addConditionally(entry, "id", "id", children);
addConditionally(entry, "title", "title", children);
var href = (_a = getOneElement("link", children)) === null || _a === void 0 ? void 0 : _a.attribs["href"];
if (href) {
entry.link = href;
}
var description = fetch$1("summary", children) || fetch$1("content", children);
if (description) {
entry.description = description;
}
var pubDate = fetch$1("updated", children);
if (pubDate) {
entry.pubDate = new Date(pubDate);
}
return entry;
}),
};
addConditionally(feed, "id", "id", childs);
addConditionally(feed, "title", "title", childs);
var href = (_a = getOneElement("link", childs)) === null || _a === void 0 ? void 0 : _a.attribs["href"];
if (href) {
feed.link = href;
}
addConditionally(feed, "description", "subtitle", childs);
var updated = fetch$1("updated", childs);
if (updated) {
feed.updated = new Date(updated);
}
addConditionally(feed, "author", "email", childs, true);
return feed;
}
/**
* Parse a RSS feed.
*
* @param feedRoot The root of the feed.
* @returns The parsed feed.
*/
function getRssFeed(feedRoot) {
var _a, _b;
var childs = (_b = (_a = getOneElement("channel", feedRoot.children)) === null || _a === void 0 ? void 0 : _a.children) !== null && _b !== void 0 ? _b : [];
var feed = {
type: feedRoot.name.substr(0, 3),
id: "",
items: (0, legacy_js_1.getElementsByTagName)("item", feedRoot.children).map(function (item) {
var children = item.children;
var entry = { media: getMediaElements(children) };
addConditionally(entry, "id", "guid", children);
addConditionally(entry, "title", "title", children);
addConditionally(entry, "link", "link", children);
addConditionally(entry, "description", "description", children);
var pubDate = fetch$1("pubDate", children) || fetch$1("dc:date", children);
if (pubDate)
entry.pubDate = new Date(pubDate);
return entry;
}),
};
addConditionally(feed, "title", "title", childs);
addConditionally(feed, "link", "link", childs);
addConditionally(feed, "description", "description", childs);
var updated = fetch$1("lastBuildDate", childs);
if (updated) {
feed.updated = new Date(updated);
}
addConditionally(feed, "author", "managingEditor", childs, true);
return feed;
}
var MEDIA_KEYS_STRING = ["url", "type", "lang"];
var MEDIA_KEYS_INT = [
"fileSize",
"bitrate",
"framerate",
"samplingrate",
"channels",
"duration",
"height",
"width",
];
/**
* Get all media elements of a feed item.
*
* @param where Nodes to search in.
* @returns Media elements.
*/
function getMediaElements(where) {
return (0, legacy_js_1.getElementsByTagName)("media:content", where).map(function (elem) {
var attribs = elem.attribs;
var media = {
medium: attribs["medium"],
isDefault: !!attribs["isDefault"],
};
for (var _i = 0, MEDIA_KEYS_STRING_1 = MEDIA_KEYS_STRING; _i < MEDIA_KEYS_STRING_1.length; _i++) {
var attrib = MEDIA_KEYS_STRING_1[_i];
if (attribs[attrib]) {
media[attrib] = attribs[attrib];
}
}
for (var _a = 0, MEDIA_KEYS_INT_1 = MEDIA_KEYS_INT; _a < MEDIA_KEYS_INT_1.length; _a++) {
var attrib = MEDIA_KEYS_INT_1[_a];
if (attribs[attrib]) {
media[attrib] = parseInt(attribs[attrib], 10);
}
}
if (attribs["expression"]) {
media.expression = attribs["expression"];
}
return media;
});
}
/**
* Get one element by tag name.
*
* @param tagName Tag name to look for
* @param node Node to search in
* @returns The element or null
*/
function getOneElement(tagName, node) {
return (0, legacy_js_1.getElementsByTagName)(tagName, node, true, 1)[0];
}
/**
* Get the text content of an element with a certain tag name.
*
* @param tagName Tag name to look for.
* @param where Node to search in.
* @param recurse Whether to recurse into child nodes.
* @returns The text content of the element.
*/
function fetch$1(tagName, where, recurse) {
if (recurse === void 0) { recurse = false; }
return (0, stringify_js_1.textContent)((0, legacy_js_1.getElementsByTagName)(tagName, where, recurse, 1)).trim();
}
/**
* Adds a property to an object if it has a value.
*
* @param obj Object to be extended
* @param prop Property name
* @param tagName Tag name that contains the conditionally added property
* @param where Element to search for the property
* @param recurse Whether to recurse into child nodes.
*/
function addConditionally(obj, prop, tagName, where, recurse) {
if (recurse === void 0) { recurse = false; }
var val = fetch$1(tagName, where, recurse);
if (val)
obj[prop] = val;
}
/**
* Checks if an element is a feed root node.
*
* @param value The name of the element to check.
* @returns Whether an element is a feed root node.
*/
function isValidFeed(value) {
return value === "rss" || value === "feed" || value === "rdf:RDF";
}
(function (exports) {
var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.hasChildren = exports.isDocument = exports.isComment = exports.isText = exports.isCDATA = exports.isTag = void 0;
__exportStar(stringify, exports);
__exportStar(traversal, exports);
__exportStar(manipulation, exports);
__exportStar(querying, exports);
__exportStar(legacy, exports);
__exportStar(helpers, exports);
__exportStar(feeds, exports);
/** @deprecated Use these methods from `domhandler` directly. */
var domhandler_1 = lib$2;
Object.defineProperty(exports, "isTag", { enumerable: true, get: function () { return domhandler_1.isTag; } });
Object.defineProperty(exports, "isCDATA", { enumerable: true, get: function () { return domhandler_1.isCDATA; } });
Object.defineProperty(exports, "isText", { enumerable: true, get: function () { return domhandler_1.isText; } });
Object.defineProperty(exports, "isComment", { enumerable: true, get: function () { return domhandler_1.isComment; } });
Object.defineProperty(exports, "isDocument", { enumerable: true, get: function () { return domhandler_1.isDocument; } });
Object.defineProperty(exports, "hasChildren", { enumerable: true, get: function () { return domhandler_1.hasChildren; } });
} (lib$3));
var compile$1 = {};
var sort = {};
Object.defineProperty(sort, "__esModule", { value: true });
sort.isTraversal = void 0;
var css_what_1$2 = require$$0$7;
var procedure = new Map([
[css_what_1$2.SelectorType.Universal, 50],
[css_what_1$2.SelectorType.Tag, 30],
[css_what_1$2.SelectorType.Attribute, 1],
[css_what_1$2.SelectorType.Pseudo, 0],
]);
function isTraversal(token) {
return !procedure.has(token.type);
}
sort.isTraversal = isTraversal;
var attributes$1 = new Map([
[css_what_1$2.AttributeAction.Exists, 10],
[css_what_1$2.AttributeAction.Equals, 8],
[css_what_1$2.AttributeAction.Not, 7],
[css_what_1$2.AttributeAction.Start, 6],
[css_what_1$2.AttributeAction.End, 6],
[css_what_1$2.AttributeAction.Any, 5],
]);
/**
* Sort the parts of the passed selector,
* as there is potential for optimization
* (some types of selectors are faster than others)
*
* @param arr Selector to sort
*/
function sortByProcedure(arr) {
var procs = arr.map(getProcedure);
for (var i = 1; i < arr.length; i++) {
var procNew = procs[i];
if (procNew < 0)
continue;
for (var j = i - 1; j >= 0 && procNew < procs[j]; j--) {
var token = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = token;
procs[j + 1] = procs[j];
procs[j] = procNew;
}
}
}
sort.default = sortByProcedure;
function getProcedure(token) {
var _a, _b;
var proc = (_a = procedure.get(token.type)) !== null && _a !== void 0 ? _a : -1;
if (token.type === css_what_1$2.SelectorType.Attribute) {
proc = (_b = attributes$1.get(token.action)) !== null && _b !== void 0 ? _b : 4;
if (token.action === css_what_1$2.AttributeAction.Equals && token.name === "id") {
// Prefer ID selectors (eg. #ID)
proc = 9;
}
if (token.ignoreCase) {
/*
* IgnoreCase adds some overhead, prefer "normal" token
* this is a binary operation, to ensure it's still an int
*/
proc >>= 1;
}
}
else if (token.type === css_what_1$2.SelectorType.Pseudo) {
if (!token.data) {
proc = 3;
}
else if (token.name === "has" || token.name === "contains") {
proc = 0; // Expensive in any case
}
else if (Array.isArray(token.data)) {
// Eg. :matches, :not
proc = Math.min.apply(Math, token.data.map(function (d) { return Math.min.apply(Math, d.map(getProcedure)); }));
// If we have traversals, try to avoid executing this selector
if (proc < 0) {
proc = 0;
}
}
else {
proc = 2;
}
}
return proc;
}
var general = {};
var attributes = {};
var __importDefault$1 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(attributes, "__esModule", { value: true });
attributes.attributeRules = void 0;
var boolbase_1$1 = __importDefault$1(require$$1$2);
/**
* All reserved characters in a regex, used for escaping.
*
* Taken from XRegExp, (c) 2007-2020 Steven Levithan under the MIT license
* https://github.com/slevithan/xregexp/blob/95eeebeb8fac8754d54eafe2b4743661ac1cf028/src/xregexp.js#L794
*/
var reChars = /[-[\]{}()*+?.,\\^$|#\s]/g;
function escapeRegex(value) {
return value.replace(reChars, "\\$&");
}
/**
* Attributes that are case-insensitive in HTML.
*
* @private
* @see https://html.spec.whatwg.org/multipage/semantics-other.html#case-sensitivity-of-selectors
*/
var caseInsensitiveAttributes = new Set([
"accept",
"accept-charset",
"align",
"alink",
"axis",
"bgcolor",
"charset",
"checked",
"clear",
"codetype",
"color",
"compact",
"declare",
"defer",
"dir",
"direction",
"disabled",
"enctype",
"face",
"frame",
"hreflang",
"http-equiv",
"lang",
"language",
"link",
"media",
"method",
"multiple",
"nohref",
"noresize",
"noshade",
"nowrap",
"readonly",
"rel",
"rev",
"rules",
"scope",
"scrolling",
"selected",
"shape",
"target",
"text",
"type",
"valign",
"valuetype",
"vlink",
]);
function shouldIgnoreCase(selector, options) {
return typeof selector.ignoreCase === "boolean"
? selector.ignoreCase
: selector.ignoreCase === "quirks"
? !!options.quirksMode
: !options.xmlMode && caseInsensitiveAttributes.has(selector.name);
}
/**
* Attribute selectors
*/
attributes.attributeRules = {
equals: function (next, data, options) {
var adapter = options.adapter;
var name = data.name;
var value = data.value;
if (shouldIgnoreCase(data, options)) {
value = value.toLowerCase();
return function (elem) {
var attr = adapter.getAttributeValue(elem, name);
return (attr != null &&
attr.length === value.length &&
attr.toLowerCase() === value &&
next(elem));
};
}
return function (elem) {
return adapter.getAttributeValue(elem, name) === value && next(elem);
};
},
hyphen: function (next, data, options) {
var adapter = options.adapter;
var name = data.name;
var value = data.value;
var len = value.length;
if (shouldIgnoreCase(data, options)) {
value = value.toLowerCase();
return function hyphenIC(elem) {
var attr = adapter.getAttributeValue(elem, name);
return (attr != null &&
(attr.length === len || attr.charAt(len) === "-") &&
attr.substr(0, len).toLowerCase() === value &&
next(elem));
};
}
return function hyphen(elem) {
var attr = adapter.getAttributeValue(elem, name);
return (attr != null &&
(attr.length === len || attr.charAt(len) === "-") &&
attr.substr(0, len) === value &&
next(elem));
};
},
element: function (next, data, options) {
var adapter = options.adapter;
var name = data.name, value = data.value;
if (/\s/.test(value)) {
return boolbase_1$1.default.falseFunc;
}
var regex = new RegExp("(?:^|\\s)".concat(escapeRegex(value), "(?:$|\\s)"), shouldIgnoreCase(data, options) ? "i" : "");
return function element(elem) {
var attr = adapter.getAttributeValue(elem, name);
return (attr != null &&
attr.length >= value.length &&
regex.test(attr) &&
next(elem));
};
},
exists: function (next, _a, _b) {
var name = _a.name;
var adapter = _b.adapter;
return function (elem) { return adapter.hasAttrib(elem, name) && next(elem); };
},
start: function (next, data, options) {
var adapter = options.adapter;
var name = data.name;
var value = data.value;
var len = value.length;
if (len === 0) {
return boolbase_1$1.default.falseFunc;
}
if (shouldIgnoreCase(data, options)) {
value = value.toLowerCase();
return function (elem) {
var attr = adapter.getAttributeValue(elem, name);
return (attr != null &&
attr.length >= len &&
attr.substr(0, len).toLowerCase() === value &&
next(elem));
};
}
return function (elem) {
var _a;
return !!((_a = adapter.getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.startsWith(value)) &&
next(elem);
};
},
end: function (next, data, options) {
var adapter = options.adapter;
var name = data.name;
var value = data.value;
var len = -value.length;
if (len === 0) {
return boolbase_1$1.default.falseFunc;
}
if (shouldIgnoreCase(data, options)) {
value = value.toLowerCase();
return function (elem) {
var _a;
return ((_a = adapter
.getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.substr(len).toLowerCase()) === value && next(elem);
};
}
return function (elem) {
var _a;
return !!((_a = adapter.getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.endsWith(value)) &&
next(elem);
};
},
any: function (next, data, options) {
var adapter = options.adapter;
var name = data.name, value = data.value;
if (value === "") {
return boolbase_1$1.default.falseFunc;
}
if (shouldIgnoreCase(data, options)) {
var regex_1 = new RegExp(escapeRegex(value), "i");
return function anyIC(elem) {
var attr = adapter.getAttributeValue(elem, name);
return (attr != null &&
attr.length >= value.length &&
regex_1.test(attr) &&
next(elem));
};
}
return function (elem) {
var _a;
return !!((_a = adapter.getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.includes(value)) &&
next(elem);
};
},
not: function (next, data, options) {
var adapter = options.adapter;
var name = data.name;
var value = data.value;
if (value === "") {
return function (elem) {
return !!adapter.getAttributeValue(elem, name) && next(elem);
};
}
else if (shouldIgnoreCase(data, options)) {
value = value.toLowerCase();
return function (elem) {
var attr = adapter.getAttributeValue(elem, name);
return ((attr == null ||
attr.length !== value.length ||
attr.toLowerCase() !== value) &&
next(elem));
};
}
return function (elem) {
return adapter.getAttributeValue(elem, name) !== value && next(elem);
};
},
};
var pseudoSelectors = {};
var filters$1 = {};
(function (exports) {
var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.filters = void 0;
var nth_check_1 = __importDefault(require$$0$8);
var boolbase_1 = __importDefault(require$$1$2);
function getChildFunc(next, adapter) {
return function (elem) {
var parent = adapter.getParent(elem);
return parent != null && adapter.isTag(parent) && next(elem);
};
}
exports.filters = {
contains: function (next, text, _a) {
var adapter = _a.adapter;
return function contains(elem) {
return next(elem) && adapter.getText(elem).includes(text);
};
},
icontains: function (next, text, _a) {
var adapter = _a.adapter;
var itext = text.toLowerCase();
return function icontains(elem) {
return (next(elem) &&
adapter.getText(elem).toLowerCase().includes(itext));
};
},
// Location specific methods
"nth-child": function (next, rule, _a) {
var adapter = _a.adapter, equals = _a.equals;
var func = (0, nth_check_1.default)(rule);
if (func === boolbase_1.default.falseFunc)
return boolbase_1.default.falseFunc;
if (func === boolbase_1.default.trueFunc)
return getChildFunc(next, adapter);
return function nthChild(elem) {
var siblings = adapter.getSiblings(elem);
var pos = 0;
for (var i = 0; i < siblings.length; i++) {
if (equals(elem, siblings[i]))
break;
if (adapter.isTag(siblings[i])) {
pos++;
}
}
return func(pos) && next(elem);
};
},
"nth-last-child": function (next, rule, _a) {
var adapter = _a.adapter, equals = _a.equals;
var func = (0, nth_check_1.default)(rule);
if (func === boolbase_1.default.falseFunc)
return boolbase_1.default.falseFunc;
if (func === boolbase_1.default.trueFunc)
return getChildFunc(next, adapter);
return function nthLastChild(elem) {
var siblings = adapter.getSiblings(elem);
var pos = 0;
for (var i = siblings.length - 1; i >= 0; i--) {
if (equals(elem, siblings[i]))
break;
if (adapter.isTag(siblings[i])) {
pos++;
}
}
return func(pos) && next(elem);
};
},
"nth-of-type": function (next, rule, _a) {
var adapter = _a.adapter, equals = _a.equals;
var func = (0, nth_check_1.default)(rule);
if (func === boolbase_1.default.falseFunc)
return boolbase_1.default.falseFunc;
if (func === boolbase_1.default.trueFunc)
return getChildFunc(next, adapter);
return function nthOfType(elem) {
var siblings = adapter.getSiblings(elem);
var pos = 0;
for (var i = 0; i < siblings.length; i++) {
var currentSibling = siblings[i];
if (equals(elem, currentSibling))
break;
if (adapter.isTag(currentSibling) &&
adapter.getName(currentSibling) === adapter.getName(elem)) {
pos++;
}
}
return func(pos) && next(elem);
};
},
"nth-last-of-type": function (next, rule, _a) {
var adapter = _a.adapter, equals = _a.equals;
var func = (0, nth_check_1.default)(rule);
if (func === boolbase_1.default.falseFunc)
return boolbase_1.default.falseFunc;
if (func === boolbase_1.default.trueFunc)
return getChildFunc(next, adapter);
return function nthLastOfType(elem) {
var siblings = adapter.getSiblings(elem);
var pos = 0;
for (var i = siblings.length - 1; i >= 0; i--) {
var currentSibling = siblings[i];
if (equals(elem, currentSibling))
break;
if (adapter.isTag(currentSibling) &&
adapter.getName(currentSibling) === adapter.getName(elem)) {
pos++;
}
}
return func(pos) && next(elem);
};
},
// TODO determine the actual root element
root: function (next, _rule, _a) {
var adapter = _a.adapter;
return function (elem) {
var parent = adapter.getParent(elem);
return (parent == null || !adapter.isTag(parent)) && next(elem);
};
},
scope: function (next, rule, options, context) {
var equals = options.equals;
if (!context || context.length === 0) {
// Equivalent to :root
return exports.filters["root"](next, rule, options);
}
if (context.length === 1) {
// NOTE: can't be unpacked, as :has uses this for side-effects
return function (elem) { return equals(context[0], elem) && next(elem); };
}
return function (elem) { return context.includes(elem) && next(elem); };
},
hover: dynamicStatePseudo("isHovered"),
visited: dynamicStatePseudo("isVisited"),
active: dynamicStatePseudo("isActive"),
};
/**
* Dynamic state pseudos. These depend on optional Adapter methods.
*
* @param name The name of the adapter method to call.
* @returns Pseudo for the `filters` object.
*/
function dynamicStatePseudo(name) {
return function dynamicPseudo(next, _rule, _a) {
var adapter = _a.adapter;
var func = adapter[name];
if (typeof func !== "function") {
return boolbase_1.default.falseFunc;
}
return function active(elem) {
return func(elem) && next(elem);
};
};
}
} (filters$1));
var pseudos = {};
Object.defineProperty(pseudos, "__esModule", { value: true });
pseudos.verifyPseudoArgs = pseudos.pseudos = void 0;
// While filters are precompiled, pseudos get called when they are needed
pseudos.pseudos = {
empty: function (elem, _a) {
var adapter = _a.adapter;
return !adapter.getChildren(elem).some(function (elem) {
// FIXME: `getText` call is potentially expensive.
return adapter.isTag(elem) || adapter.getText(elem) !== "";
});
},
"first-child": function (elem, _a) {
var adapter = _a.adapter, equals = _a.equals;
if (adapter.prevElementSibling) {
return adapter.prevElementSibling(elem) == null;
}
var firstChild = adapter
.getSiblings(elem)
.find(function (elem) { return adapter.isTag(elem); });
return firstChild != null && equals(elem, firstChild);
},
"last-child": function (elem, _a) {
var adapter = _a.adapter, equals = _a.equals;
var siblings = adapter.getSiblings(elem);
for (var i = siblings.length - 1; i >= 0; i--) {
if (equals(elem, siblings[i]))
return true;
if (adapter.isTag(siblings[i]))
break;
}
return false;
},
"first-of-type": function (elem, _a) {
var adapter = _a.adapter, equals = _a.equals;
var siblings = adapter.getSiblings(elem);
var elemName = adapter.getName(elem);
for (var i = 0; i < siblings.length; i++) {
var currentSibling = siblings[i];
if (equals(elem, currentSibling))
return true;
if (adapter.isTag(currentSibling) &&
adapter.getName(currentSibling) === elemName) {
break;
}
}
return false;
},
"last-of-type": function (elem, _a) {
var adapter = _a.adapter, equals = _a.equals;
var siblings = adapter.getSiblings(elem);
var elemName = adapter.getName(elem);
for (var i = siblings.length - 1; i >= 0; i--) {
var currentSibling = siblings[i];
if (equals(elem, currentSibling))
return true;
if (adapter.isTag(currentSibling) &&
adapter.getName(currentSibling) === elemName) {
break;
}
}
return false;
},
"only-of-type": function (elem, _a) {
var adapter = _a.adapter, equals = _a.equals;
var elemName = adapter.getName(elem);
return adapter
.getSiblings(elem)
.every(function (sibling) {
return equals(elem, sibling) ||
!adapter.isTag(sibling) ||
adapter.getName(sibling) !== elemName;
});
},
"only-child": function (elem, _a) {
var adapter = _a.adapter, equals = _a.equals;
return adapter
.getSiblings(elem)
.every(function (sibling) { return equals(elem, sibling) || !adapter.isTag(sibling); });
},
};
function verifyPseudoArgs(func, name, subselect, argIndex) {
if (subselect === null) {
if (func.length > argIndex) {
throw new Error("Pseudo-class :".concat(name, " requires an argument"));
}
}
else if (func.length === argIndex) {
throw new Error("Pseudo-class :".concat(name, " doesn't have any arguments"));
}
}
pseudos.verifyPseudoArgs = verifyPseudoArgs;
var aliases = {};
Object.defineProperty(aliases, "__esModule", { value: true });
aliases.aliases = void 0;
/**
* Aliases are pseudos that are expressed as selectors.
*/
aliases.aliases = {
// Links
"any-link": ":is(a, area, link)[href]",
link: ":any-link:not(:visited)",
// Forms
// https://html.spec.whatwg.org/multipage/scripting.html#disabled-elements
disabled: ":is(\n :is(button, input, select, textarea, optgroup, option)[disabled],\n optgroup[disabled] > option,\n fieldset[disabled]:not(fieldset[disabled] legend:first-of-type *)\n )",
enabled: ":not(:disabled)",
checked: ":is(:is(input[type=radio], input[type=checkbox])[checked], option:selected)",
required: ":is(input, select, textarea)[required]",
optional: ":is(input, select, textarea):not([required])",
// JQuery extensions
// https://html.spec.whatwg.org/multipage/form-elements.html#concept-option-selectedness
selected: "option:is([selected], select:not([multiple]):not(:has(> option[selected])) > :first-of-type)",
checkbox: "[type=checkbox]",
file: "[type=file]",
password: "[type=password]",
radio: "[type=radio]",
reset: "[type=reset]",
image: "[type=image]",
submit: "[type=submit]",
parent: ":not(:empty)",
header: ":is(h1, h2, h3, h4, h5, h6)",
button: ":is(button, input[type=button])",
input: ":is(input, textarea, select, button)",
text: "input:is(:not([type!='']), [type=text])",
};
var subselects = {};
(function (exports) {
var __spreadArray = (commonjsGlobal && commonjsGlobal.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.subselects = exports.getNextSiblings = exports.ensureIsTag = exports.PLACEHOLDER_ELEMENT = void 0;
var boolbase_1 = __importDefault(require$$1$2);
var sort_js_1 = sort;
/** Used as a placeholder for :has. Will be replaced with the actual element. */
exports.PLACEHOLDER_ELEMENT = {};
function ensureIsTag(next, adapter) {
if (next === boolbase_1.default.falseFunc)
return boolbase_1.default.falseFunc;
return function (elem) { return adapter.isTag(elem) && next(elem); };
}
exports.ensureIsTag = ensureIsTag;
function getNextSiblings(elem, adapter) {
var siblings = adapter.getSiblings(elem);
if (siblings.length <= 1)
return [];
var elemIndex = siblings.indexOf(elem);
if (elemIndex < 0 || elemIndex === siblings.length - 1)
return [];
return siblings.slice(elemIndex + 1).filter(adapter.isTag);
}
exports.getNextSiblings = getNextSiblings;
function copyOptions(options) {
// Not copied: context, rootFunc
return {
xmlMode: !!options.xmlMode,
lowerCaseAttributeNames: !!options.lowerCaseAttributeNames,
lowerCaseTags: !!options.lowerCaseTags,
quirksMode: !!options.quirksMode,
cacheResults: !!options.cacheResults,
pseudos: options.pseudos,
adapter: options.adapter,
equals: options.equals,
};
}
var is = function (next, token, options, context, compileToken) {
var func = compileToken(token, copyOptions(options), context);
return func === boolbase_1.default.trueFunc
? next
: func === boolbase_1.default.falseFunc
? boolbase_1.default.falseFunc
: function (elem) { return func(elem) && next(elem); };
};
/*
* :not, :has, :is, :matches and :where have to compile selectors
* doing this in src/pseudos.ts would lead to circular dependencies,
* so we add them here
*/
exports.subselects = {
is: is,
/**
* `:matches` and `:where` are aliases for `:is`.
*/
matches: is,
where: is,
not: function (next, token, options, context, compileToken) {
var func = compileToken(token, copyOptions(options), context);
return func === boolbase_1.default.falseFunc
? next
: func === boolbase_1.default.trueFunc
? boolbase_1.default.falseFunc
: function (elem) { return !func(elem) && next(elem); };
},
has: function (next, subselect, options, _context, compileToken) {
var adapter = options.adapter;
var opts = copyOptions(options);
opts.relativeSelector = true;
var context = subselect.some(function (s) { return s.some(sort_js_1.isTraversal); })
? // Used as a placeholder. Will be replaced with the actual element.
[exports.PLACEHOLDER_ELEMENT]
: undefined;
var compiled = compileToken(subselect, opts, context);
if (compiled === boolbase_1.default.falseFunc)
return boolbase_1.default.falseFunc;
var hasElement = ensureIsTag(compiled, adapter);
// If `compiled` is `trueFunc`, we can skip this.
if (context && compiled !== boolbase_1.default.trueFunc) {
/*
* `shouldTestNextSiblings` will only be true if the query starts with
* a traversal (sibling or adjacent). That means we will always have a context.
*/
var _a = compiled.shouldTestNextSiblings, shouldTestNextSiblings_1 = _a === void 0 ? false : _a;
return function (elem) {
if (!next(elem))
return false;
context[0] = elem;
var childs = adapter.getChildren(elem);
var nextElements = shouldTestNextSiblings_1
? __spreadArray(__spreadArray([], childs, true), getNextSiblings(elem, adapter), true) : childs;
return adapter.existsOne(hasElement, nextElements);
};
}
return function (elem) {
return next(elem) &&
adapter.existsOne(hasElement, adapter.getChildren(elem));
};
},
};
} (subselects));
(function (exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.compilePseudoSelector = exports.aliases = exports.pseudos = exports.filters = void 0;
var css_what_1 = require$$0$7;
var filters_js_1 = filters$1;
Object.defineProperty(exports, "filters", { enumerable: true, get: function () { return filters_js_1.filters; } });
var pseudos_js_1 = pseudos;
Object.defineProperty(exports, "pseudos", { enumerable: true, get: function () { return pseudos_js_1.pseudos; } });
var aliases_js_1 = aliases;
Object.defineProperty(exports, "aliases", { enumerable: true, get: function () { return aliases_js_1.aliases; } });
var subselects_js_1 = subselects;
function compilePseudoSelector(next, selector, options, context, compileToken) {
var _a;
var name = selector.name, data = selector.data;
if (Array.isArray(data)) {
if (!(name in subselects_js_1.subselects)) {
throw new Error("Unknown pseudo-class :".concat(name, "(").concat(data, ")"));
}
return subselects_js_1.subselects[name](next, data, options, context, compileToken);
}
var userPseudo = (_a = options.pseudos) === null || _a === void 0 ? void 0 : _a[name];
var stringPseudo = typeof userPseudo === "string" ? userPseudo : aliases_js_1.aliases[name];
if (typeof stringPseudo === "string") {
if (data != null) {
throw new Error("Pseudo ".concat(name, " doesn't have any arguments"));
}
// The alias has to be parsed here, to make sure options are respected.
var alias = (0, css_what_1.parse)(stringPseudo);
return subselects_js_1.subselects["is"](next, alias, options, context, compileToken);
}
if (typeof userPseudo === "function") {
(0, pseudos_js_1.verifyPseudoArgs)(userPseudo, name, data, 1);
return function (elem) { return userPseudo(elem, data) && next(elem); };
}
if (name in filters_js_1.filters) {
return filters_js_1.filters[name](next, data, options, context);
}
if (name in pseudos_js_1.pseudos) {
var pseudo_1 = pseudos_js_1.pseudos[name];
(0, pseudos_js_1.verifyPseudoArgs)(pseudo_1, name, data, 2);
return function (elem) { return pseudo_1(elem, options, data) && next(elem); };
}
throw new Error("Unknown pseudo-class :".concat(name));
}
exports.compilePseudoSelector = compilePseudoSelector;
} (pseudoSelectors));
Object.defineProperty(general, "__esModule", { value: true });
general.compileGeneralSelector = void 0;
var attributes_js_1 = attributes;
var index_js_1 = pseudoSelectors;
var css_what_1$1 = require$$0$7;
function getElementParent(node, adapter) {
var parent = adapter.getParent(node);
if (parent && adapter.isTag(parent)) {
return parent;
}
return null;
}
/*
* All available rules
*/
function compileGeneralSelector(next, selector, options, context, compileToken) {
var adapter = options.adapter, equals = options.equals;
switch (selector.type) {
case css_what_1$1.SelectorType.PseudoElement: {
throw new Error("Pseudo-elements are not supported by css-select");
}
case css_what_1$1.SelectorType.ColumnCombinator: {
throw new Error("Column combinators are not yet supported by css-select");
}
case css_what_1$1.SelectorType.Attribute: {
if (selector.namespace != null) {
throw new Error("Namespaced attributes are not yet supported by css-select");
}
if (!options.xmlMode || options.lowerCaseAttributeNames) {
selector.name = selector.name.toLowerCase();
}
return attributes_js_1.attributeRules[selector.action](next, selector, options);
}
case css_what_1$1.SelectorType.Pseudo: {
return (0, index_js_1.compilePseudoSelector)(next, selector, options, context, compileToken);
}
// Tags
case css_what_1$1.SelectorType.Tag: {
if (selector.namespace != null) {
throw new Error("Namespaced tag names are not yet supported by css-select");
}
var name_1 = selector.name;
if (!options.xmlMode || options.lowerCaseTags) {
name_1 = name_1.toLowerCase();
}
return function tag(elem) {
return adapter.getName(elem) === name_1 && next(elem);
};
}
// Traversal
case css_what_1$1.SelectorType.Descendant: {
if (options.cacheResults === false ||
typeof WeakSet === "undefined") {
return function descendant(elem) {
var current = elem;
while ((current = getElementParent(current, adapter))) {
if (next(current)) {
return true;
}
}
return false;
};
}
// @ts-expect-error `ElementNode` is not extending object
var isFalseCache_1 = new WeakSet();
return function cachedDescendant(elem) {
var current = elem;
while ((current = getElementParent(current, adapter))) {
if (!isFalseCache_1.has(current)) {
if (adapter.isTag(current) && next(current)) {
return true;
}
isFalseCache_1.add(current);
}
}
return false;
};
}
case "_flexibleDescendant": {
// Include element itself, only used while querying an array
return function flexibleDescendant(elem) {
var current = elem;
do {
if (next(current))
return true;
} while ((current = getElementParent(current, adapter)));
return false;
};
}
case css_what_1$1.SelectorType.Parent: {
return function parent(elem) {
return adapter
.getChildren(elem)
.some(function (elem) { return adapter.isTag(elem) && next(elem); });
};
}
case css_what_1$1.SelectorType.Child: {
return function child(elem) {
var parent = adapter.getParent(elem);
return parent != null && adapter.isTag(parent) && next(parent);
};
}
case css_what_1$1.SelectorType.Sibling: {
return function sibling(elem) {
var siblings = adapter.getSiblings(elem);
for (var i = 0; i < siblings.length; i++) {
var currentSibling = siblings[i];
if (equals(elem, currentSibling))
break;
if (adapter.isTag(currentSibling) && next(currentSibling)) {
return true;
}
}
return false;
};
}
case css_what_1$1.SelectorType.Adjacent: {
if (adapter.prevElementSibling) {
return function adjacent(elem) {
var previous = adapter.prevElementSibling(elem);
return previous != null && next(previous);
};
}
return function adjacent(elem) {
var siblings = adapter.getSiblings(elem);
var lastElement;
for (var i = 0; i < siblings.length; i++) {
var currentSibling = siblings[i];
if (equals(elem, currentSibling))
break;
if (adapter.isTag(currentSibling)) {
lastElement = currentSibling;
}
}
return !!lastElement && next(lastElement);
};
}
case css_what_1$1.SelectorType.Universal: {
if (selector.namespace != null && selector.namespace !== "*") {
throw new Error("Namespaced universal selectors are not yet supported by css-select");
}
return next;
}
}
}
general.compileGeneralSelector = compileGeneralSelector;
var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (commonjsGlobal && commonjsGlobal.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (commonjsGlobal && commonjsGlobal.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(compile$1, "__esModule", { value: true });
compile$1.compileToken = compile$1.compileUnsafe = compile$1.compile = void 0;
var css_what_1 = require$$0$7;
var boolbase_1 = __importDefault(require$$1$2);
var sort_js_1 = __importStar(sort);
var general_js_1 = general;
var subselects_js_1 = subselects;
/**
* Compiles a selector to an executable function.
*
* @param selector Selector to compile.
* @param options Compilation options.
* @param context Optional context for the selector.
*/
function compile(selector, options, context) {
var next = compileUnsafe(selector, options, context);
return (0, subselects_js_1.ensureIsTag)(next, options.adapter);
}
compile$1.compile = compile;
function compileUnsafe(selector, options, context) {
var token = typeof selector === "string" ? (0, css_what_1.parse)(selector) : selector;
return compileToken(token, options, context);
}
compile$1.compileUnsafe = compileUnsafe;
function includesScopePseudo(t) {
return (t.type === css_what_1.SelectorType.Pseudo &&
(t.name === "scope" ||
(Array.isArray(t.data) &&
t.data.some(function (data) { return data.some(includesScopePseudo); }))));
}
var DESCENDANT_TOKEN = { type: css_what_1.SelectorType.Descendant };
var FLEXIBLE_DESCENDANT_TOKEN = {
type: "_flexibleDescendant",
};
var SCOPE_TOKEN = {
type: css_what_1.SelectorType.Pseudo,
name: "scope",
data: null,
};
/*
* CSS 4 Spec (Draft): 3.4.1. Absolutizing a Relative Selector
* http://www.w3.org/TR/selectors4/#absolutizing
*/
function absolutize(token, _a, context) {
var adapter = _a.adapter;
// TODO Use better check if the context is a document
var hasContext = !!(context === null || context === void 0 ? void 0 : context.every(function (e) {
var parent = adapter.isTag(e) && adapter.getParent(e);
return e === subselects_js_1.PLACEHOLDER_ELEMENT || (parent && adapter.isTag(parent));
}));
for (var _i = 0, token_1 = token; _i < token_1.length; _i++) {
var t = token_1[_i];
if (t.length > 0 &&
(0, sort_js_1.isTraversal)(t[0]) &&
t[0].type !== css_what_1.SelectorType.Descendant) ;
else if (hasContext && !t.some(includesScopePseudo)) {
t.unshift(DESCENDANT_TOKEN);
}
else {
continue;
}
t.unshift(SCOPE_TOKEN);
}
}
function compileToken(token, options, context) {
var _a;
token.forEach(sort_js_1.default);
context = (_a = options.context) !== null && _a !== void 0 ? _a : context;
var isArrayContext = Array.isArray(context);
var finalContext = context && (Array.isArray(context) ? context : [context]);
// Check if the selector is relative
if (options.relativeSelector !== false) {
absolutize(token, options, finalContext);
}
else if (token.some(function (t) { return t.length > 0 && (0, sort_js_1.isTraversal)(t[0]); })) {
throw new Error("Relative selectors are not allowed when the `relativeSelector` option is disabled");
}
var shouldTestNextSiblings = false;
var query = token
.map(function (rules) {
if (rules.length >= 2) {
var first = rules[0], second = rules[1];
if (first.type !== css_what_1.SelectorType.Pseudo ||
first.name !== "scope") ;
else if (isArrayContext &&
second.type === css_what_1.SelectorType.Descendant) {
rules[1] = FLEXIBLE_DESCENDANT_TOKEN;
}
else if (second.type === css_what_1.SelectorType.Adjacent ||
second.type === css_what_1.SelectorType.Sibling) {
shouldTestNextSiblings = true;
}
}
return compileRules(rules, options, finalContext);
})
.reduce(reduceRules, boolbase_1.default.falseFunc);
query.shouldTestNextSiblings = shouldTestNextSiblings;
return query;
}
compile$1.compileToken = compileToken;
function compileRules(rules, options, context) {
var _a;
return rules.reduce(function (previous, rule) {
return previous === boolbase_1.default.falseFunc
? boolbase_1.default.falseFunc
: (0, general_js_1.compileGeneralSelector)(previous, rule, options, context, compileToken);
}, (_a = options.rootFunc) !== null && _a !== void 0 ? _a : boolbase_1.default.trueFunc);
}
function reduceRules(a, b) {
if (b === boolbase_1.default.falseFunc || a === boolbase_1.default.trueFunc) {
return a;
}
if (a === boolbase_1.default.falseFunc || b === boolbase_1.default.trueFunc) {
return b;
}
return function combine(elem) {
return a(elem) || b(elem);
};
}
(function (exports) {
var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (commonjsGlobal && commonjsGlobal.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (commonjsGlobal && commonjsGlobal.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.aliases = exports.pseudos = exports.filters = exports.is = exports.selectOne = exports.selectAll = exports.prepareContext = exports._compileToken = exports._compileUnsafe = exports.compile = void 0;
var DomUtils = __importStar(lib$3);
var boolbase_1 = __importDefault(require$$1$2);
var compile_js_1 = compile$1;
var subselects_js_1 = subselects;
var defaultEquals = function (a, b) { return a === b; };
var defaultOptions = {
adapter: DomUtils,
equals: defaultEquals,
};
function convertOptionFormats(options) {
var _a, _b, _c, _d;
/*
* We force one format of options to the other one.
*/
// @ts-expect-error Default options may have incompatible `Node` / `ElementNode`.
var opts = options !== null && options !== void 0 ? options : defaultOptions;
// @ts-expect-error Same as above.
(_a = opts.adapter) !== null && _a !== void 0 ? _a : (opts.adapter = DomUtils);
// @ts-expect-error `equals` does not exist on `Options`
(_b = opts.equals) !== null && _b !== void 0 ? _b : (opts.equals = (_d = (_c = opts.adapter) === null || _c === void 0 ? void 0 : _c.equals) !== null && _d !== void 0 ? _d : defaultEquals);
return opts;
}
function wrapCompile(func) {
return function addAdapter(selector, options, context) {
var opts = convertOptionFormats(options);
return func(selector, opts, context);
};
}
/**
* Compiles the query, returns a function.
*/
exports.compile = wrapCompile(compile_js_1.compile);
exports._compileUnsafe = wrapCompile(compile_js_1.compileUnsafe);
exports._compileToken = wrapCompile(compile_js_1.compileToken);
function getSelectorFunc(searchFunc) {
return function select(query, elements, options) {
var opts = convertOptionFormats(options);
if (typeof query !== "function") {
query = (0, compile_js_1.compileUnsafe)(query, opts, elements);
}
var filteredElements = prepareContext(elements, opts.adapter, query.shouldTestNextSiblings);
return searchFunc(query, filteredElements, opts);
};
}
function prepareContext(elems, adapter, shouldTestNextSiblings) {
if (shouldTestNextSiblings === void 0) { shouldTestNextSiblings = false; }
/*
* Add siblings if the query requires them.
* See https://github.com/fb55/css-select/pull/43#issuecomment-225414692
*/
if (shouldTestNextSiblings) {
elems = appendNextSiblings(elems, adapter);
}
return Array.isArray(elems)
? adapter.removeSubsets(elems)
: adapter.getChildren(elems);
}
exports.prepareContext = prepareContext;
function appendNextSiblings(elem, adapter) {
// Order matters because jQuery seems to check the children before the siblings
var elems = Array.isArray(elem) ? elem.slice(0) : [elem];
var elemsLength = elems.length;
for (var i = 0; i < elemsLength; i++) {
var nextSiblings = (0, subselects_js_1.getNextSiblings)(elems[i], adapter);
elems.push.apply(elems, nextSiblings);
}
return elems;
}
/**
* @template Node The generic Node type for the DOM adapter being used.
* @template ElementNode The Node type for elements for the DOM adapter being used.
* @param elems Elements to query. If it is an element, its children will be queried..
* @param query can be either a CSS selector string or a compiled query function.
* @param [options] options for querying the document.
* @see compile for supported selector queries.
* @returns All matching elements.
*
*/
exports.selectAll = getSelectorFunc(function (query, elems, options) {
return query === boolbase_1.default.falseFunc || !elems || elems.length === 0
? []
: options.adapter.findAll(query, elems);
});
/**
* @template Node The generic Node type for the DOM adapter being used.
* @template ElementNode The Node type for elements for the DOM adapter being used.
* @param elems Elements to query. If it is an element, its children will be queried..
* @param query can be either a CSS selector string or a compiled query function.
* @param [options] options for querying the document.
* @see compile for supported selector queries.
* @returns the first match, or null if there was no match.
*/
exports.selectOne = getSelectorFunc(function (query, elems, options) {
return query === boolbase_1.default.falseFunc || !elems || elems.length === 0
? null
: options.adapter.findOne(query, elems);
});
/**
* Tests whether or not an element is matched by query.
*
* @template Node The generic Node type for the DOM adapter being used.
* @template ElementNode The Node type for elements for the DOM adapter being used.
* @param elem The element to test if it matches the query.
* @param query can be either a CSS selector string or a compiled query function.
* @param [options] options for querying the document.
* @see compile for supported selector queries.
* @returns
*/
function is(elem, query, options) {
var opts = convertOptionFormats(options);
return (typeof query === "function" ? query : (0, compile_js_1.compile)(query, opts))(elem);
}
exports.is = is;
/**
* Alias for selectAll(query, elems, options).
* @see [compile] for supported selector queries.
*/
exports.default = exports.selectAll;
// Export filters, pseudos and aliases to allow users to supply their own.
/** @deprecated Use the `pseudos` option instead. */
var index_js_1 = pseudoSelectors;
Object.defineProperty(exports, "filters", { enumerable: true, get: function () { return index_js_1.filters; } });
Object.defineProperty(exports, "pseudos", { enumerable: true, get: function () { return index_js_1.pseudos; } });
Object.defineProperty(exports, "aliases", { enumerable: true, get: function () { return index_js_1.aliases; } });
} (lib$4));
const isTag = (node) => {
return node.type === 'element';
};
const existsOne = (test, elems) => {
return elems.some((elem) => {
if (isTag(elem)) {
return test(elem) || existsOne(test, getChildren(elem));
} else {
return false;
}
});
};
const getAttributeValue = (elem, name) => {
return elem.attributes[name];
};
const getChildren = (node) => {
return node.children || [];
};
const getName = (elemAst) => {
return elemAst.name;
};
const getParent = (node) => {
return node.parentNode || null;
};
const getSiblings = (elem) => {
var parent = getParent(elem);
return parent ? getChildren(parent) : [];
};
const getText = (node) => {
if (node.children[0].type === 'text' && node.children[0].type === 'cdata') {
return node.children[0].value;
}
return '';
};
const hasAttrib = (elem, name) => {
return elem.attributes[name] !== undefined;
};
const removeSubsets = (nodes) => {
let idx = nodes.length;
let node;
let ancestor;
let replace;
// Check if each node (or one of its ancestors) is already contained in the
// array.
while (--idx > -1) {
node = ancestor = nodes[idx];
// Temporarily remove the node under consideration
nodes[idx] = null;
replace = true;
while (ancestor) {
if (nodes.includes(ancestor)) {
replace = false;
nodes.splice(idx, 1);
break;
}
ancestor = getParent(ancestor);
}
// If the node has been found to be unique, re-insert it.
if (replace) {
nodes[idx] = node;
}
}
return nodes;
};
const findAll$3 = (test, elems) => {
const result = [];
for (const elem of elems) {
if (isTag(elem)) {
if (test(elem)) {
result.push(elem);
}
result.push(...findAll$3(test, getChildren(elem)));
}
}
return result;
};
const findOne = (test, elems) => {
for (const elem of elems) {
if (isTag(elem)) {
if (test(elem)) {
return elem;
}
const result = findOne(test, getChildren(elem));
if (result) {
return result;
}
}
}
return null;
};
const svgoCssSelectAdapter = {
isTag,
existsOne,
getAttributeValue,
getChildren,
getName,
getParent,
getSiblings,
getText,
hasAttrib,
removeSubsets,
findAll: findAll$3,
findOne,
};
var cssSelectAdapter = svgoCssSelectAdapter;
/**
* @typedef {import('./types').XastNode} XastNode
* @typedef {import('./types').XastChild} XastChild
* @typedef {import('./types').XastParent} XastParent
* @typedef {import('./types').Visitor} Visitor
*/
const { selectAll, selectOne, is } = lib$4;
const xastAdaptor = cssSelectAdapter;
const cssSelectOptions = {
xmlMode: true,
adapter: xastAdaptor,
};
/**
* @type {(node: XastNode, selector: string) => Array<XastChild>}
*/
const querySelectorAll$2 = (node, selector) => {
return selectAll(selector, node, cssSelectOptions);
};
xast.querySelectorAll = querySelectorAll$2;
/**
* @type {(node: XastNode, selector: string) => null | XastChild}
*/
const querySelector$1 = (node, selector) => {
return selectOne(selector, node, cssSelectOptions);
};
xast.querySelector = querySelector$1;
/**
* @type {(node: XastChild, selector: string) => boolean}
*/
const matches$1 = (node, selector) => {
return is(node, selector, cssSelectOptions);
};
xast.matches = matches$1;
const visitSkip$7 = Symbol();
xast.visitSkip = visitSkip$7;
/**
* @type {(node: XastNode, visitor: Visitor, parentNode?: any) => void}
*/
const visit$7 = (node, visitor, parentNode) => {
const callbacks = visitor[node.type];
if (callbacks && callbacks.enter) {
// @ts-ignore hard to infer
const symbol = callbacks.enter(node, parentNode);
if (symbol === visitSkip$7) {
return;
}
}
// visit root children
if (node.type === 'root') {
// copy children array to not loose cursor when children is spliced
for (const child of node.children) {
visit$7(child, visitor, node);
}
}
// visit element children if still attached to parent
if (node.type === 'element') {
if (parentNode.children.includes(node)) {
for (const child of node.children) {
visit$7(child, visitor, node);
}
}
}
if (callbacks && callbacks.exit) {
// @ts-ignore hard to infer
callbacks.exit(node, parentNode);
}
};
xast.visit = visit$7;
/**
* @type {(node: XastChild, parentNode: XastParent) => void}
*/
const detachNodeFromParent$m = (node, parentNode) => {
// avoid splice to not break for loops
parentNode.children = parentNode.children.filter((child) => child !== node);
};
xast.detachNodeFromParent = detachNodeFromParent$m;
const { visit: visit$6 } = xast;
/**
* Plugins engine.
*
* @module plugins
*
* @param {Object} ast input ast
* @param {Object} info extra information
* @param {Array} plugins plugins object from config
* @return {Object} output ast
*/
const invokePlugins$1 = (ast, info, plugins, overrides, globalOverrides) => {
for (const plugin of plugins) {
const override = overrides == null ? null : overrides[plugin.name];
if (override === false) {
continue;
}
const params = { ...plugin.params, ...globalOverrides, ...override };
const visitor = plugin.fn(ast, params, info);
if (visitor != null) {
visit$6(ast, visitor);
}
}
};
plugins.invokePlugins = invokePlugins$1;
const createPreset$1 = ({ name, plugins }) => {
return {
name,
fn: (ast, params, info) => {
const { floatPrecision, overrides } = params;
const globalOverrides = {};
if (floatPrecision != null) {
globalOverrides.floatPrecision = floatPrecision;
}
if (overrides) {
const pluginNames = plugins.map(({ name }) => name);
for (const pluginName of Object.keys(overrides)) {
if (!pluginNames.includes(pluginName)) {
console.warn(
`You are trying to configure ${pluginName} which is not part of ${name}.\n` +
`Try to put it before or after, for example\n\n` +
`plugins: [\n` +
` {\n` +
` name: '${name}',\n` +
` },\n` +
` '${pluginName}'\n` +
`]\n`
);
}
}
}
invokePlugins$1(ast, info, plugins, overrides, globalOverrides);
},
};
};
plugins.createPreset = createPreset$1;
var removeDoctype$1 = {};
const { detachNodeFromParent: detachNodeFromParent$l } = xast;
removeDoctype$1.name = 'removeDoctype';
removeDoctype$1.description = 'removes doctype declaration';
/**
* Remove DOCTYPE declaration.
*
* "Unfortunately the SVG DTDs are a source of so many
* issues that the SVG WG has decided not to write one
* for the upcoming SVG 1.2 standard. In fact SVG WG
* members are even telling people not to use a DOCTYPE
* declaration in SVG 1.0 and 1.1 documents"
* https://jwatt.org/svg/authoring/#doctype-declaration
*
* @example
* <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
* q"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
*
* @example
* <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
* "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" [
* <!-- an internal subset can be embedded here -->
* ]>
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'removeDoctype'>}
*/
removeDoctype$1.fn = () => {
return {
doctype: {
enter: (node, parentNode) => {
detachNodeFromParent$l(node, parentNode);
},
},
};
};
var removeXMLProcInst$1 = {};
const { detachNodeFromParent: detachNodeFromParent$k } = xast;
removeXMLProcInst$1.name = 'removeXMLProcInst';
removeXMLProcInst$1.description = 'removes XML processing instructions';
/**
* Remove XML Processing Instruction.
*
* @example
* <?xml version="1.0" encoding="utf-8"?>
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'removeXMLProcInst'>}
*/
removeXMLProcInst$1.fn = () => {
return {
instruction: {
enter: (node, parentNode) => {
if (node.name === 'xml') {
detachNodeFromParent$k(node, parentNode);
}
},
},
};
};
var removeComments$1 = {};
const { detachNodeFromParent: detachNodeFromParent$j } = xast;
removeComments$1.name = 'removeComments';
removeComments$1.description = 'removes comments';
/**
* Remove comments.
*
* @example
* <!-- Generator: Adobe Illustrator 15.0.0, SVG Export
* Plug-In . SVG Version: 6.00 Build 0) -->
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'removeComments'>}
*/
removeComments$1.fn = () => {
return {
comment: {
enter: (node, parentNode) => {
if (node.value.charAt(0) !== '!') {
detachNodeFromParent$j(node, parentNode);
}
},
},
};
};
var removeMetadata$1 = {};
const { detachNodeFromParent: detachNodeFromParent$i } = xast;
removeMetadata$1.name = 'removeMetadata';
removeMetadata$1.description = 'removes <metadata>';
/**
* Remove <metadata>.
*
* https://www.w3.org/TR/SVG11/metadata.html
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'removeMetadata'>}
*/
removeMetadata$1.fn = () => {
return {
element: {
enter: (node, parentNode) => {
if (node.name === 'metadata') {
detachNodeFromParent$i(node, parentNode);
}
},
},
};
};
var removeEditorsNSData$1 = {};
const { detachNodeFromParent: detachNodeFromParent$h } = xast;
const { editorNamespaces } = _collections;
removeEditorsNSData$1.name = 'removeEditorsNSData';
removeEditorsNSData$1.description = 'removes editors namespaces, elements and attributes';
/**
* Remove editors namespaces, elements and attributes.
*
* @example
* <svg xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd">
* <sodipodi:namedview/>
* <path sodipodi:nodetypes="cccc"/>
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'removeEditorsNSData'>}
*/
removeEditorsNSData$1.fn = (_root, params) => {
let namespaces = editorNamespaces;
if (Array.isArray(params.additionalNamespaces)) {
namespaces = [...editorNamespaces, ...params.additionalNamespaces];
}
/**
* @type {Array<string>}
*/
const prefixes = [];
return {
element: {
enter: (node, parentNode) => {
// collect namespace aliases from svg element
if (node.name === 'svg') {
for (const [name, value] of Object.entries(node.attributes)) {
if (name.startsWith('xmlns:') && namespaces.includes(value)) {
prefixes.push(name.slice('xmlns:'.length));
// <svg xmlns:sodipodi="">
delete node.attributes[name];
}
}
}
// remove editor attributes, for example
// <* sodipodi:*="">
for (const name of Object.keys(node.attributes)) {
if (name.includes(':')) {
const [prefix] = name.split(':');
if (prefixes.includes(prefix)) {
delete node.attributes[name];
}
}
}
// remove editor elements, for example
// <sodipodi:*>
if (node.name.includes(':')) {
const [prefix] = node.name.split(':');
if (prefixes.includes(prefix)) {
detachNodeFromParent$h(node, parentNode);
}
}
},
},
};
};
var cleanupAttrs$1 = {};
cleanupAttrs$1.name = 'cleanupAttrs';
cleanupAttrs$1.description =
'cleanups attributes from newlines, trailing and repeating spaces';
const regNewlinesNeedSpace = /(\S)\r?\n(\S)/g;
const regNewlines = /\r?\n/g;
const regSpaces = /\s{2,}/g;
/**
* Cleanup attributes values from newlines, trailing and repeating spaces.
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'cleanupAttrs'>}
*/
cleanupAttrs$1.fn = (root, params) => {
const { newlines = true, trim = true, spaces = true } = params;
return {
element: {
enter: (node) => {
for (const name of Object.keys(node.attributes)) {
if (newlines) {
// new line which requires a space instead of themselve
node.attributes[name] = node.attributes[name].replace(
regNewlinesNeedSpace,
(match, p1, p2) => p1 + ' ' + p2
);
// simple new line
node.attributes[name] = node.attributes[name].replace(
regNewlines,
''
);
}
if (trim) {
node.attributes[name] = node.attributes[name].trim();
}
if (spaces) {
node.attributes[name] = node.attributes[name].replace(
regSpaces,
' '
);
}
}
},
},
};
};
var mergeStyles$1 = {};
/**
* @typedef {import('../lib/types').XastElement} XastElement
* @typedef {import('../lib/types').XastChild} XastChild
*/
const { visitSkip: visitSkip$6, detachNodeFromParent: detachNodeFromParent$g } = xast;
mergeStyles$1.name = 'mergeStyles';
mergeStyles$1.description = 'merge multiple style elements into one';
/**
* Merge multiple style elements into one.
*
* @author strarsis <strarsis@gmail.com>
*
* @type {import('./plugins-types').Plugin<'mergeStyles'>}
*/
mergeStyles$1.fn = () => {
/**
* @type {null | XastElement}
*/
let firstStyleElement = null;
let collectedStyles = '';
/**
* @type {'text' | 'cdata'}
*/
let styleContentType = 'text';
return {
element: {
enter: (node, parentNode) => {
// skip <foreignObject> content
if (node.name === 'foreignObject') {
return visitSkip$6;
}
// collect style elements
if (node.name !== 'style') {
return;
}
// skip <style> with invalid type attribute
if (
node.attributes.type != null &&
node.attributes.type !== '' &&
node.attributes.type !== 'text/css'
) {
return;
}
// extract style element content
let css = '';
for (const child of node.children) {
if (child.type === 'text') {
css += child.value;
}
if (child.type === 'cdata') {
styleContentType = 'cdata';
css += child.value;
}
}
// remove empty style elements
if (css.trim().length === 0) {
detachNodeFromParent$g(node, parentNode);
return;
}
// collect css and wrap with media query if present in attribute
if (node.attributes.media == null) {
collectedStyles += css;
} else {
collectedStyles += `@media ${node.attributes.media}{${css}}`;
delete node.attributes.media;
}
// combine collected styles in the first style element
if (firstStyleElement == null) {
firstStyleElement = node;
} else {
detachNodeFromParent$g(node, parentNode);
/**
* @type {XastChild}
*/
const child = { type: styleContentType, value: collectedStyles };
// TODO remove legacy parentNode in v4
Object.defineProperty(child, 'parentNode', {
writable: true,
value: firstStyleElement,
});
firstStyleElement.children = [child];
}
},
},
};
};
var inlineStyles$1 = {};
var cjs$2 = {};
var tokenizer$5 = {};
var types$1K = {};
// CSS Syntax Module Level 3
// https://www.w3.org/TR/css-syntax-3/
const EOF$3 = 0; // <EOF-token>
const Ident$1 = 1; // <ident-token>
const Function$5 = 2; // <function-token>
const AtKeyword$1 = 3; // <at-keyword-token>
const Hash$7 = 4; // <hash-token>
const String$4 = 5; // <string-token>
const BadString$1 = 6; // <bad-string-token>
const Url$9 = 7; // <url-token>
const BadUrl$1 = 8; // <bad-url-token>
const Delim$1 = 9; // <delim-token>
const Number$5 = 10; // <number-token>
const Percentage$9 = 11; // <percentage-token>
const Dimension$9 = 12; // <dimension-token>
const WhiteSpace$9 = 13; // <whitespace-token>
const CDO$7 = 14; // <CDO-token>
const CDC$7 = 15; // <CDC-token>
const Colon$1 = 16; // <colon-token> :
const Semicolon$1 = 17; // <semicolon-token> ;
const Comma$1 = 18; // <comma-token> ,
const LeftSquareBracket$1 = 19; // <[-token>
const RightSquareBracket$1 = 20; // <]-token>
const LeftParenthesis$1 = 21; // <(-token>
const RightParenthesis$1 = 22; // <)-token>
const LeftCurlyBracket$1 = 23; // <{-token>
const RightCurlyBracket$1 = 24; // <}-token>
const Comment$9 = 25;
types$1K.AtKeyword = AtKeyword$1;
types$1K.BadString = BadString$1;
types$1K.BadUrl = BadUrl$1;
types$1K.CDC = CDC$7;
types$1K.CDO = CDO$7;
types$1K.Colon = Colon$1;
types$1K.Comma = Comma$1;
types$1K.Comment = Comment$9;
types$1K.Delim = Delim$1;
types$1K.Dimension = Dimension$9;
types$1K.EOF = EOF$3;
types$1K.Function = Function$5;
types$1K.Hash = Hash$7;
types$1K.Ident = Ident$1;
types$1K.LeftCurlyBracket = LeftCurlyBracket$1;
types$1K.LeftParenthesis = LeftParenthesis$1;
types$1K.LeftSquareBracket = LeftSquareBracket$1;
types$1K.Number = Number$5;
types$1K.Percentage = Percentage$9;
types$1K.RightCurlyBracket = RightCurlyBracket$1;
types$1K.RightParenthesis = RightParenthesis$1;
types$1K.RightSquareBracket = RightSquareBracket$1;
types$1K.Semicolon = Semicolon$1;
types$1K.String = String$4;
types$1K.Url = Url$9;
types$1K.WhiteSpace = WhiteSpace$9;
var charCodeDefinitions$p = {};
const EOF$2 = 0;
// https://drafts.csswg.org/css-syntax-3/
// § 4.2. Definitions
// digit
// A code point between U+0030 DIGIT ZERO (0) and U+0039 DIGIT NINE (9).
function isDigit$2(code) {
return code >= 0x0030 && code <= 0x0039;
}
// hex digit
// A digit, or a code point between U+0041 LATIN CAPITAL LETTER A (A) and U+0046 LATIN CAPITAL LETTER F (F),
// or a code point between U+0061 LATIN SMALL LETTER A (a) and U+0066 LATIN SMALL LETTER F (f).
function isHexDigit$1(code) {
return (
isDigit$2(code) || // 0 .. 9
(code >= 0x0041 && code <= 0x0046) || // A .. F
(code >= 0x0061 && code <= 0x0066) // a .. f
);
}
// uppercase letter
// A code point between U+0041 LATIN CAPITAL LETTER A (A) and U+005A LATIN CAPITAL LETTER Z (Z).
function isUppercaseLetter$1(code) {
return code >= 0x0041 && code <= 0x005A;
}
// lowercase letter
// A code point between U+0061 LATIN SMALL LETTER A (a) and U+007A LATIN SMALL LETTER Z (z).
function isLowercaseLetter$1(code) {
return code >= 0x0061 && code <= 0x007A;
}
// letter
// An uppercase letter or a lowercase letter.
function isLetter$1(code) {
return isUppercaseLetter$1(code) || isLowercaseLetter$1(code);
}
// non-ASCII code point
// A code point with a value equal to or greater than U+0080 <control>.
function isNonAscii$1(code) {
return code >= 0x0080;
}
// name-start code point
// A letter, a non-ASCII code point, or U+005F LOW LINE (_).
function isNameStart$1(code) {
return isLetter$1(code) || isNonAscii$1(code) || code === 0x005F;
}
// name code point
// A name-start code point, a digit, or U+002D HYPHEN-MINUS (-).
function isName$1(code) {
return isNameStart$1(code) || isDigit$2(code) || code === 0x002D;
}
// non-printable code point
// A code point between U+0000 NULL and U+0008 BACKSPACE, or U+000B LINE TABULATION,
// or a code point between U+000E SHIFT OUT and U+001F INFORMATION SEPARATOR ONE, or U+007F DELETE.
function isNonPrintable$1(code) {
return (
(code >= 0x0000 && code <= 0x0008) ||
(code === 0x000B) ||
(code >= 0x000E && code <= 0x001F) ||
(code === 0x007F)
);
}
// newline
// U+000A LINE FEED. Note that U+000D CARRIAGE RETURN and U+000C FORM FEED are not included in this definition,
// as they are converted to U+000A LINE FEED during preprocessing.
// TODO: we doesn't do a preprocessing, so check a code point for U+000D CARRIAGE RETURN and U+000C FORM FEED
function isNewline$1(code) {
return code === 0x000A || code === 0x000D || code === 0x000C;
}
// whitespace
// A newline, U+0009 CHARACTER TABULATION, or U+0020 SPACE.
function isWhiteSpace$1(code) {
return isNewline$1(code) || code === 0x0020 || code === 0x0009;
}
// § 4.3.8. Check if two code points are a valid escape
function isValidEscape$1(first, second) {
// If the first code point is not U+005C REVERSE SOLIDUS (\), return false.
if (first !== 0x005C) {
return false;
}
// Otherwise, if the second code point is a newline or EOF, return false.
if (isNewline$1(second) || second === EOF$2) {
return false;
}
// Otherwise, return true.
return true;
}
// § 4.3.9. Check if three code points would start an identifier
function isIdentifierStart$1(first, second, third) {
// Look at the first code point:
// U+002D HYPHEN-MINUS
if (first === 0x002D) {
// If the second code point is a name-start code point or a U+002D HYPHEN-MINUS,
// or the second and third code points are a valid escape, return true. Otherwise, return false.
return (
isNameStart$1(second) ||
second === 0x002D ||
isValidEscape$1(second, third)
);
}
// name-start code point
if (isNameStart$1(first)) {
// Return true.
return true;
}
// U+005C REVERSE SOLIDUS (\)
if (first === 0x005C) {
// If the first and second code points are a valid escape, return true. Otherwise, return false.
return isValidEscape$1(first, second);
}
// anything else
// Return false.
return false;
}
// § 4.3.10. Check if three code points would start a number
function isNumberStart$1(first, second, third) {
// Look at the first code point:
// U+002B PLUS SIGN (+)
// U+002D HYPHEN-MINUS (-)
if (first === 0x002B || first === 0x002D) {
// If the second code point is a digit, return true.
if (isDigit$2(second)) {
return 2;
}
// Otherwise, if the second code point is a U+002E FULL STOP (.)
// and the third code point is a digit, return true.
// Otherwise, return false.
return second === 0x002E && isDigit$2(third) ? 3 : 0;
}
// U+002E FULL STOP (.)
if (first === 0x002E) {
// If the second code point is a digit, return true. Otherwise, return false.
return isDigit$2(second) ? 2 : 0;
}
// digit
if (isDigit$2(first)) {
// Return true.
return 1;
}
// anything else
// Return false.
return 0;
}
//
// Misc
//
// detect BOM (https://en.wikipedia.org/wiki/Byte_order_mark)
function isBOM$1(code) {
// UTF-16BE
if (code === 0xFEFF) {
return 1;
}
// UTF-16LE
if (code === 0xFFFE) {
return 1;
}
return 0;
}
// Fast code category
// Only ASCII code points has a special meaning, that's why we define a maps for 0..127 codes only
const CATEGORY$1 = new Array(0x80);
const EofCategory$1 = 0x80;
const WhiteSpaceCategory$1 = 0x82;
const DigitCategory$1 = 0x83;
const NameStartCategory$1 = 0x84;
const NonPrintableCategory$1 = 0x85;
for (let i = 0; i < CATEGORY$1.length; i++) {
CATEGORY$1[i] =
isWhiteSpace$1(i) && WhiteSpaceCategory$1 ||
isDigit$2(i) && DigitCategory$1 ||
isNameStart$1(i) && NameStartCategory$1 ||
isNonPrintable$1(i) && NonPrintableCategory$1 ||
i || EofCategory$1;
}
function charCodeCategory$1(code) {
return code < 0x80 ? CATEGORY$1[code] : NameStartCategory$1;
}
charCodeDefinitions$p.DigitCategory = DigitCategory$1;
charCodeDefinitions$p.EofCategory = EofCategory$1;
charCodeDefinitions$p.NameStartCategory = NameStartCategory$1;
charCodeDefinitions$p.NonPrintableCategory = NonPrintableCategory$1;
charCodeDefinitions$p.WhiteSpaceCategory = WhiteSpaceCategory$1;
charCodeDefinitions$p.charCodeCategory = charCodeCategory$1;
charCodeDefinitions$p.isBOM = isBOM$1;
charCodeDefinitions$p.isDigit = isDigit$2;
charCodeDefinitions$p.isHexDigit = isHexDigit$1;
charCodeDefinitions$p.isIdentifierStart = isIdentifierStart$1;
charCodeDefinitions$p.isLetter = isLetter$1;
charCodeDefinitions$p.isLowercaseLetter = isLowercaseLetter$1;
charCodeDefinitions$p.isName = isName$1;
charCodeDefinitions$p.isNameStart = isNameStart$1;
charCodeDefinitions$p.isNewline = isNewline$1;
charCodeDefinitions$p.isNonAscii = isNonAscii$1;
charCodeDefinitions$p.isNonPrintable = isNonPrintable$1;
charCodeDefinitions$p.isNumberStart = isNumberStart$1;
charCodeDefinitions$p.isUppercaseLetter = isUppercaseLetter$1;
charCodeDefinitions$p.isValidEscape = isValidEscape$1;
charCodeDefinitions$p.isWhiteSpace = isWhiteSpace$1;
var utils$u = {};
const charCodeDefinitions$o = charCodeDefinitions$p;
function getCharCode$1(source, offset) {
return offset < source.length ? source.charCodeAt(offset) : 0;
}
function getNewlineLength$1(source, offset, code) {
if (code === 13 /* \r */ && getCharCode$1(source, offset + 1) === 10 /* \n */) {
return 2;
}
return 1;
}
function cmpChar$1(testStr, offset, referenceCode) {
let code = testStr.charCodeAt(offset);
// code.toLowerCase() for A..Z
if (charCodeDefinitions$o.isUppercaseLetter(code)) {
code = code | 32;
}
return code === referenceCode;
}
function cmpStr$1(testStr, start, end, referenceStr) {
if (end - start !== referenceStr.length) {
return false;
}
if (start < 0 || end > testStr.length) {
return false;
}
for (let i = start; i < end; i++) {
const referenceCode = referenceStr.charCodeAt(i - start);
let testCode = testStr.charCodeAt(i);
// testCode.toLowerCase() for A..Z
if (charCodeDefinitions$o.isUppercaseLetter(testCode)) {
testCode = testCode | 32;
}
if (testCode !== referenceCode) {
return false;
}
}
return true;
}
function findWhiteSpaceStart$1(source, offset) {
for (; offset >= 0; offset--) {
if (!charCodeDefinitions$o.isWhiteSpace(source.charCodeAt(offset))) {
break;
}
}
return offset + 1;
}
function findWhiteSpaceEnd$1(source, offset) {
for (; offset < source.length; offset++) {
if (!charCodeDefinitions$o.isWhiteSpace(source.charCodeAt(offset))) {
break;
}
}
return offset;
}
function findDecimalNumberEnd$1(source, offset) {
for (; offset < source.length; offset++) {
if (!charCodeDefinitions$o.isDigit(source.charCodeAt(offset))) {
break;
}
}
return offset;
}
// § 4.3.7. Consume an escaped code point
function consumeEscaped$1(source, offset) {
// It assumes that the U+005C REVERSE SOLIDUS (\) has already been consumed and
// that the next input code point has already been verified to be part of a valid escape.
offset += 2;
// hex digit
if (charCodeDefinitions$o.isHexDigit(getCharCode$1(source, offset - 1))) {
// Consume as many hex digits as possible, but no more than 5.
// Note that this means 1-6 hex digits have been consumed in total.
for (const maxOffset = Math.min(source.length, offset + 5); offset < maxOffset; offset++) {
if (!charCodeDefinitions$o.isHexDigit(getCharCode$1(source, offset))) {
break;
}
}
// If the next input code point is whitespace, consume it as well.
const code = getCharCode$1(source, offset);
if (charCodeDefinitions$o.isWhiteSpace(code)) {
offset += getNewlineLength$1(source, offset, code);
}
}
return offset;
}
// §4.3.11. Consume a name
// Note: This algorithm does not do the verification of the first few code points that are necessary
// to ensure the returned code points would constitute an <ident-token>. If that is the intended use,
// ensure that the stream starts with an identifier before calling this algorithm.
function consumeName$1(source, offset) {
// Let result initially be an empty string.
// Repeatedly consume the next input code point from the stream:
for (; offset < source.length; offset++) {
const code = source.charCodeAt(offset);
// name code point
if (charCodeDefinitions$o.isName(code)) {
// Append the code point to result.
continue;
}
// the stream starts with a valid escape
if (charCodeDefinitions$o.isValidEscape(code, getCharCode$1(source, offset + 1))) {
// Consume an escaped code point. Append the returned code point to result.
offset = consumeEscaped$1(source, offset) - 1;
continue;
}
// anything else
// Reconsume the current input code point. Return result.
break;
}
return offset;
}
// §4.3.12. Consume a number
function consumeNumber$3(source, offset) {
let code = source.charCodeAt(offset);
// 2. If the next input code point is U+002B PLUS SIGN (+) or U+002D HYPHEN-MINUS (-),
// consume it and append it to repr.
if (code === 0x002B || code === 0x002D) {
code = source.charCodeAt(offset += 1);
}
// 3. While the next input code point is a digit, consume it and append it to repr.
if (charCodeDefinitions$o.isDigit(code)) {
offset = findDecimalNumberEnd$1(source, offset + 1);
code = source.charCodeAt(offset);
}
// 4. If the next 2 input code points are U+002E FULL STOP (.) followed by a digit, then:
if (code === 0x002E && charCodeDefinitions$o.isDigit(source.charCodeAt(offset + 1))) {
// 4.1 Consume them.
// 4.2 Append them to repr.
offset += 2;
// 4.3 Set type to "number".
// TODO
// 4.4 While the next input code point is a digit, consume it and append it to repr.
offset = findDecimalNumberEnd$1(source, offset);
}
// 5. If the next 2 or 3 input code points are U+0045 LATIN CAPITAL LETTER E (E)
// or U+0065 LATIN SMALL LETTER E (e), ... , followed by a digit, then:
if (cmpChar$1(source, offset, 101 /* e */)) {
let sign = 0;
code = source.charCodeAt(offset + 1);
// ... optionally followed by U+002D HYPHEN-MINUS (-) or U+002B PLUS SIGN (+) ...
if (code === 0x002D || code === 0x002B) {
sign = 1;
code = source.charCodeAt(offset + 2);
}
// ... followed by a digit
if (charCodeDefinitions$o.isDigit(code)) {
// 5.1 Consume them.
// 5.2 Append them to repr.
// 5.3 Set type to "number".
// TODO
// 5.4 While the next input code point is a digit, consume it and append it to repr.
offset = findDecimalNumberEnd$1(source, offset + 1 + sign + 1);
}
}
return offset;
}
// § 4.3.14. Consume the remnants of a bad url
// ... its sole use is to consume enough of the input stream to reach a recovery point
// where normal tokenizing can resume.
function consumeBadUrlRemnants$1(source, offset) {
// Repeatedly consume the next input code point from the stream:
for (; offset < source.length; offset++) {
const code = source.charCodeAt(offset);
// U+0029 RIGHT PARENTHESIS ())
// EOF
if (code === 0x0029) {
// Return.
offset++;
break;
}
if (charCodeDefinitions$o.isValidEscape(code, getCharCode$1(source, offset + 1))) {
// Consume an escaped code point.
// Note: This allows an escaped right parenthesis ("\)") to be encountered
// without ending the <bad-url-token>. This is otherwise identical to
// the "anything else" clause.
offset = consumeEscaped$1(source, offset);
}
}
return offset;
}
// § 4.3.7. Consume an escaped code point
// Note: This algorithm assumes that escaped is valid without leading U+005C REVERSE SOLIDUS (\)
function decodeEscaped$1(escaped) {
// Single char escaped that's not a hex digit
if (escaped.length === 1 && !charCodeDefinitions$o.isHexDigit(escaped.charCodeAt(0))) {
return escaped[0];
}
// Interpret the hex digits as a hexadecimal number.
let code = parseInt(escaped, 16);
if (
(code === 0) || // If this number is zero,
(code >= 0xD800 && code <= 0xDFFF) || // or is for a surrogate,
(code > 0x10FFFF) // or is greater than the maximum allowed code point
) {
// ... return U+FFFD REPLACEMENT CHARACTER
code = 0xFFFD;
}
// Otherwise, return the code point with that value.
return String.fromCodePoint(code);
}
utils$u.cmpChar = cmpChar$1;
utils$u.cmpStr = cmpStr$1;
utils$u.consumeBadUrlRemnants = consumeBadUrlRemnants$1;
utils$u.consumeEscaped = consumeEscaped$1;
utils$u.consumeName = consumeName$1;
utils$u.consumeNumber = consumeNumber$3;
utils$u.decodeEscaped = decodeEscaped$1;
utils$u.findDecimalNumberEnd = findDecimalNumberEnd$1;
utils$u.findWhiteSpaceEnd = findWhiteSpaceEnd$1;
utils$u.findWhiteSpaceStart = findWhiteSpaceStart$1;
utils$u.getNewlineLength = getNewlineLength$1;
const tokenNames$1 = [
'EOF-token',
'ident-token',
'function-token',
'at-keyword-token',
'hash-token',
'string-token',
'bad-string-token',
'url-token',
'bad-url-token',
'delim-token',
'number-token',
'percentage-token',
'dimension-token',
'whitespace-token',
'CDO-token',
'CDC-token',
'colon-token',
'semicolon-token',
'comma-token',
'[-token',
']-token',
'(-token',
')-token',
'{-token',
'}-token'
];
var names$g = tokenNames$1;
var OffsetToLocation$7 = {};
var adoptBuffer$7 = {};
const MIN_SIZE$1 = 16 * 1024;
function adoptBuffer$6(buffer = null, size) {
if (buffer === null || buffer.length < size) {
return new Uint32Array(Math.max(size + 1024, MIN_SIZE$1));
}
return buffer;
}
adoptBuffer$7.adoptBuffer = adoptBuffer$6;
const adoptBuffer$5 = adoptBuffer$7;
const charCodeDefinitions$n = charCodeDefinitions$p;
const N$9 = 10;
const F$5 = 12;
const R$5 = 13;
function computeLinesAndColumns$1(host) {
const source = host.source;
const sourceLength = source.length;
const startOffset = source.length > 0 ? charCodeDefinitions$n.isBOM(source.charCodeAt(0)) : 0;
const lines = adoptBuffer$5.adoptBuffer(host.lines, sourceLength);
const columns = adoptBuffer$5.adoptBuffer(host.columns, sourceLength);
let line = host.startLine;
let column = host.startColumn;
for (let i = startOffset; i < sourceLength; i++) {
const code = source.charCodeAt(i);
lines[i] = line;
columns[i] = column++;
if (code === N$9 || code === R$5 || code === F$5) {
if (code === R$5 && i + 1 < sourceLength && source.charCodeAt(i + 1) === N$9) {
i++;
lines[i] = line;
columns[i] = column;
}
line++;
column = 1;
}
}
lines[sourceLength] = line;
columns[sourceLength] = column;
host.lines = lines;
host.columns = columns;
host.computed = true;
}
let OffsetToLocation$6 = class OffsetToLocation {
constructor() {
this.lines = null;
this.columns = null;
this.computed = false;
}
setSource(source, startOffset = 0, startLine = 1, startColumn = 1) {
this.source = source;
this.startOffset = startOffset;
this.startLine = startLine;
this.startColumn = startColumn;
this.computed = false;
}
getLocation(offset, filename) {
if (!this.computed) {
computeLinesAndColumns$1(this);
}
return {
source: filename,
offset: this.startOffset + offset,
line: this.lines[offset],
column: this.columns[offset]
};
}
getLocationRange(start, end, filename) {
if (!this.computed) {
computeLinesAndColumns$1(this);
}
return {
source: filename,
start: {
offset: this.startOffset + start,
line: this.lines[start],
column: this.columns[start]
},
end: {
offset: this.startOffset + end,
line: this.lines[end],
column: this.columns[end]
}
};
}
};
OffsetToLocation$7.OffsetToLocation = OffsetToLocation$6;
var TokenStream$9 = {};
const adoptBuffer$4 = adoptBuffer$7;
const utils$t = utils$u;
const names$f = names$g;
const types$1J = types$1K;
const OFFSET_MASK$1 = 0x00FFFFFF;
const TYPE_SHIFT$1 = 24;
const balancePair$3 = new Map([
[types$1J.Function, types$1J.RightParenthesis],
[types$1J.LeftParenthesis, types$1J.RightParenthesis],
[types$1J.LeftSquareBracket, types$1J.RightSquareBracket],
[types$1J.LeftCurlyBracket, types$1J.RightCurlyBracket]
]);
let TokenStream$8 = class TokenStream {
constructor(source, tokenize) {
this.setSource(source, tokenize);
}
reset() {
this.eof = false;
this.tokenIndex = -1;
this.tokenType = 0;
this.tokenStart = this.firstCharOffset;
this.tokenEnd = this.firstCharOffset;
}
setSource(source = '', tokenize = () => {}) {
source = String(source || '');
const sourceLength = source.length;
const offsetAndType = adoptBuffer$4.adoptBuffer(this.offsetAndType, source.length + 1); // +1 because of eof-token
const balance = adoptBuffer$4.adoptBuffer(this.balance, source.length + 1);
let tokenCount = 0;
let balanceCloseType = 0;
let balanceStart = 0;
let firstCharOffset = -1;
// capture buffers
this.offsetAndType = null;
this.balance = null;
tokenize(source, (type, start, end) => {
switch (type) {
default:
balance[tokenCount] = sourceLength;
break;
case balanceCloseType: {
let balancePrev = balanceStart & OFFSET_MASK$1;
balanceStart = balance[balancePrev];
balanceCloseType = balanceStart >> TYPE_SHIFT$1;
balance[tokenCount] = balancePrev;
balance[balancePrev++] = tokenCount;
for (; balancePrev < tokenCount; balancePrev++) {
if (balance[balancePrev] === sourceLength) {
balance[balancePrev] = tokenCount;
}
}
break;
}
case types$1J.LeftParenthesis:
case types$1J.Function:
case types$1J.LeftSquareBracket:
case types$1J.LeftCurlyBracket:
balance[tokenCount] = balanceStart;
balanceCloseType = balancePair$3.get(type);
balanceStart = (balanceCloseType << TYPE_SHIFT$1) | tokenCount;
break;
}
offsetAndType[tokenCount++] = (type << TYPE_SHIFT$1) | end;
if (firstCharOffset === -1) {
firstCharOffset = start;
}
});
// finalize buffers
offsetAndType[tokenCount] = (types$1J.EOF << TYPE_SHIFT$1) | sourceLength; // <EOF-token>
balance[tokenCount] = sourceLength;
balance[sourceLength] = sourceLength; // prevents false positive balance match with any token
while (balanceStart !== 0) {
const balancePrev = balanceStart & OFFSET_MASK$1;
balanceStart = balance[balancePrev];
balance[balancePrev] = sourceLength;
}
this.source = source;
this.firstCharOffset = firstCharOffset === -1 ? 0 : firstCharOffset;
this.tokenCount = tokenCount;
this.offsetAndType = offsetAndType;
this.balance = balance;
this.reset();
this.next();
}
lookupType(offset) {
offset += this.tokenIndex;
if (offset < this.tokenCount) {
return this.offsetAndType[offset] >> TYPE_SHIFT$1;
}
return types$1J.EOF;
}
lookupOffset(offset) {
offset += this.tokenIndex;
if (offset < this.tokenCount) {
return this.offsetAndType[offset - 1] & OFFSET_MASK$1;
}
return this.source.length;
}
lookupValue(offset, referenceStr) {
offset += this.tokenIndex;
if (offset < this.tokenCount) {
return utils$t.cmpStr(
this.source,
this.offsetAndType[offset - 1] & OFFSET_MASK$1,
this.offsetAndType[offset] & OFFSET_MASK$1,
referenceStr
);
}
return false;
}
getTokenStart(tokenIndex) {
if (tokenIndex === this.tokenIndex) {
return this.tokenStart;
}
if (tokenIndex > 0) {
return tokenIndex < this.tokenCount
? this.offsetAndType[tokenIndex - 1] & OFFSET_MASK$1
: this.offsetAndType[this.tokenCount] & OFFSET_MASK$1;
}
return this.firstCharOffset;
}
substrToCursor(start) {
return this.source.substring(start, this.tokenStart);
}
isBalanceEdge(pos) {
return this.balance[this.tokenIndex] < pos;
}
isDelim(code, offset) {
if (offset) {
return (
this.lookupType(offset) === types$1J.Delim &&
this.source.charCodeAt(this.lookupOffset(offset)) === code
);
}
return (
this.tokenType === types$1J.Delim &&
this.source.charCodeAt(this.tokenStart) === code
);
}
skip(tokenCount) {
let next = this.tokenIndex + tokenCount;
if (next < this.tokenCount) {
this.tokenIndex = next;
this.tokenStart = this.offsetAndType[next - 1] & OFFSET_MASK$1;
next = this.offsetAndType[next];
this.tokenType = next >> TYPE_SHIFT$1;
this.tokenEnd = next & OFFSET_MASK$1;
} else {
this.tokenIndex = this.tokenCount;
this.next();
}
}
next() {
let next = this.tokenIndex + 1;
if (next < this.tokenCount) {
this.tokenIndex = next;
this.tokenStart = this.tokenEnd;
next = this.offsetAndType[next];
this.tokenType = next >> TYPE_SHIFT$1;
this.tokenEnd = next & OFFSET_MASK$1;
} else {
this.eof = true;
this.tokenIndex = this.tokenCount;
this.tokenType = types$1J.EOF;
this.tokenStart = this.tokenEnd = this.source.length;
}
}
skipSC() {
while (this.tokenType === types$1J.WhiteSpace || this.tokenType === types$1J.Comment) {
this.next();
}
}
skipUntilBalanced(startToken, stopConsume) {
let cursor = startToken;
let balanceEnd;
let offset;
loop:
for (; cursor < this.tokenCount; cursor++) {
balanceEnd = this.balance[cursor];
// stop scanning on balance edge that points to offset before start token
if (balanceEnd < startToken) {
break loop;
}
offset = cursor > 0 ? this.offsetAndType[cursor - 1] & OFFSET_MASK$1 : this.firstCharOffset;
// check stop condition
switch (stopConsume(this.source.charCodeAt(offset))) {
case 1: // just stop
break loop;
case 2: // stop & included
cursor++;
break loop;
default:
// fast forward to the end of balanced block
if (this.balance[balanceEnd] === cursor) {
cursor = balanceEnd;
}
}
}
this.skip(cursor - this.tokenIndex);
}
forEachToken(fn) {
for (let i = 0, offset = this.firstCharOffset; i < this.tokenCount; i++) {
const start = offset;
const item = this.offsetAndType[i];
const end = item & OFFSET_MASK$1;
const type = item >> TYPE_SHIFT$1;
offset = end;
fn(type, start, end, i);
}
}
dump() {
const tokens = new Array(this.tokenCount);
this.forEachToken((type, start, end, index) => {
tokens[index] = {
idx: index,
type: names$f[type],
chunk: this.source.substring(start, end),
balance: this.balance[index]
};
});
return tokens;
}
};
TokenStream$9.TokenStream = TokenStream$8;
const types$1I = types$1K;
const charCodeDefinitions$m = charCodeDefinitions$p;
const utils$s = utils$u;
const names$e = names$g;
const OffsetToLocation$5 = OffsetToLocation$7;
const TokenStream$7 = TokenStream$9;
function tokenize$4(source, onToken) {
function getCharCode(offset) {
return offset < sourceLength ? source.charCodeAt(offset) : 0;
}
// § 4.3.3. Consume a numeric token
function consumeNumericToken() {
// Consume a number and let number be the result.
offset = utils$s.consumeNumber(source, offset);
// If the next 3 input code points would start an identifier, then:
if (charCodeDefinitions$m.isIdentifierStart(getCharCode(offset), getCharCode(offset + 1), getCharCode(offset + 2))) {
// Create a <dimension-token> with the same value and type flag as number, and a unit set initially to the empty string.
// Consume a name. Set the <dimension-token>s unit to the returned value.
// Return the <dimension-token>.
type = types$1I.Dimension;
offset = utils$s.consumeName(source, offset);
return;
}
// Otherwise, if the next input code point is U+0025 PERCENTAGE SIGN (%), consume it.
if (getCharCode(offset) === 0x0025) {
// Create a <percentage-token> with the same value as number, and return it.
type = types$1I.Percentage;
offset++;
return;
}
// Otherwise, create a <number-token> with the same value and type flag as number, and return it.
type = types$1I.Number;
}
// § 4.3.4. Consume an ident-like token
function consumeIdentLikeToken() {
const nameStartOffset = offset;
// Consume a name, and let string be the result.
offset = utils$s.consumeName(source, offset);
// If strings value is an ASCII case-insensitive match for "url",
// and the next input code point is U+0028 LEFT PARENTHESIS ((), consume it.
if (utils$s.cmpStr(source, nameStartOffset, offset, 'url') && getCharCode(offset) === 0x0028) {
// While the next two input code points are whitespace, consume the next input code point.
offset = utils$s.findWhiteSpaceEnd(source, offset + 1);
// If the next one or two input code points are U+0022 QUOTATION MARK ("), U+0027 APOSTROPHE ('),
// or whitespace followed by U+0022 QUOTATION MARK (") or U+0027 APOSTROPHE ('),
// then create a <function-token> with its value set to string and return it.
if (getCharCode(offset) === 0x0022 ||
getCharCode(offset) === 0x0027) {
type = types$1I.Function;
offset = nameStartOffset + 4;
return;
}
// Otherwise, consume a url token, and return it.
consumeUrlToken();
return;
}
// Otherwise, if the next input code point is U+0028 LEFT PARENTHESIS ((), consume it.
// Create a <function-token> with its value set to string and return it.
if (getCharCode(offset) === 0x0028) {
type = types$1I.Function;
offset++;
return;
}
// Otherwise, create an <ident-token> with its value set to string and return it.
type = types$1I.Ident;
}
// § 4.3.5. Consume a string token
function consumeStringToken(endingCodePoint) {
// This algorithm may be called with an ending code point, which denotes the code point
// that ends the string. If an ending code point is not specified,
// the current input code point is used.
if (!endingCodePoint) {
endingCodePoint = getCharCode(offset++);
}
// Initially create a <string-token> with its value set to the empty string.
type = types$1I.String;
// Repeatedly consume the next input code point from the stream:
for (; offset < source.length; offset++) {
const code = source.charCodeAt(offset);
switch (charCodeDefinitions$m.charCodeCategory(code)) {
// ending code point
case endingCodePoint:
// Return the <string-token>.
offset++;
return;
// EOF
// case EofCategory:
// This is a parse error. Return the <string-token>.
// return;
// newline
case charCodeDefinitions$m.WhiteSpaceCategory:
if (charCodeDefinitions$m.isNewline(code)) {
// This is a parse error. Reconsume the current input code point,
// create a <bad-string-token>, and return it.
offset += utils$s.getNewlineLength(source, offset, code);
type = types$1I.BadString;
return;
}
break;
// U+005C REVERSE SOLIDUS (\)
case 0x005C:
// If the next input code point is EOF, do nothing.
if (offset === source.length - 1) {
break;
}
const nextCode = getCharCode(offset + 1);
// Otherwise, if the next input code point is a newline, consume it.
if (charCodeDefinitions$m.isNewline(nextCode)) {
offset += utils$s.getNewlineLength(source, offset + 1, nextCode);
} else if (charCodeDefinitions$m.isValidEscape(code, nextCode)) {
// Otherwise, (the stream starts with a valid escape) consume
// an escaped code point and append the returned code point to
// the <string-token>s value.
offset = utils$s.consumeEscaped(source, offset) - 1;
}
break;
// anything else
// Append the current input code point to the <string-token>s value.
}
}
}
// § 4.3.6. Consume a url token
// Note: This algorithm assumes that the initial "url(" has already been consumed.
// This algorithm also assumes that its being called to consume an "unquoted" value, like url(foo).
// A quoted value, like url("foo"), is parsed as a <function-token>. Consume an ident-like token
// automatically handles this distinction; this algorithm shouldnt be called directly otherwise.
function consumeUrlToken() {
// Initially create a <url-token> with its value set to the empty string.
type = types$1I.Url;
// Consume as much whitespace as possible.
offset = utils$s.findWhiteSpaceEnd(source, offset);
// Repeatedly consume the next input code point from the stream:
for (; offset < source.length; offset++) {
const code = source.charCodeAt(offset);
switch (charCodeDefinitions$m.charCodeCategory(code)) {
// U+0029 RIGHT PARENTHESIS ())
case 0x0029:
// Return the <url-token>.
offset++;
return;
// EOF
// case EofCategory:
// This is a parse error. Return the <url-token>.
// return;
// whitespace
case charCodeDefinitions$m.WhiteSpaceCategory:
// Consume as much whitespace as possible.
offset = utils$s.findWhiteSpaceEnd(source, offset);
// If the next input code point is U+0029 RIGHT PARENTHESIS ()) or EOF,
// consume it and return the <url-token>
// (if EOF was encountered, this is a parse error);
if (getCharCode(offset) === 0x0029 || offset >= source.length) {
if (offset < source.length) {
offset++;
}
return;
}
// otherwise, consume the remnants of a bad url, create a <bad-url-token>,
// and return it.
offset = utils$s.consumeBadUrlRemnants(source, offset);
type = types$1I.BadUrl;
return;
// U+0022 QUOTATION MARK (")
// U+0027 APOSTROPHE (')
// U+0028 LEFT PARENTHESIS (()
// non-printable code point
case 0x0022:
case 0x0027:
case 0x0028:
case charCodeDefinitions$m.NonPrintableCategory:
// This is a parse error. Consume the remnants of a bad url,
// create a <bad-url-token>, and return it.
offset = utils$s.consumeBadUrlRemnants(source, offset);
type = types$1I.BadUrl;
return;
// U+005C REVERSE SOLIDUS (\)
case 0x005C:
// If the stream starts with a valid escape, consume an escaped code point and
// append the returned code point to the <url-token>s value.
if (charCodeDefinitions$m.isValidEscape(code, getCharCode(offset + 1))) {
offset = utils$s.consumeEscaped(source, offset) - 1;
break;
}
// Otherwise, this is a parse error. Consume the remnants of a bad url,
// create a <bad-url-token>, and return it.
offset = utils$s.consumeBadUrlRemnants(source, offset);
type = types$1I.BadUrl;
return;
// anything else
// Append the current input code point to the <url-token>s value.
}
}
}
// ensure source is a string
source = String(source || '');
const sourceLength = source.length;
let start = charCodeDefinitions$m.isBOM(getCharCode(0));
let offset = start;
let type;
// https://drafts.csswg.org/css-syntax-3/#consume-token
// § 4.3.1. Consume a token
while (offset < sourceLength) {
const code = source.charCodeAt(offset);
switch (charCodeDefinitions$m.charCodeCategory(code)) {
// whitespace
case charCodeDefinitions$m.WhiteSpaceCategory:
// Consume as much whitespace as possible. Return a <whitespace-token>.
type = types$1I.WhiteSpace;
offset = utils$s.findWhiteSpaceEnd(source, offset + 1);
break;
// U+0022 QUOTATION MARK (")
case 0x0022:
// Consume a string token and return it.
consumeStringToken();
break;
// U+0023 NUMBER SIGN (#)
case 0x0023:
// If the next input code point is a name code point or the next two input code points are a valid escape, then:
if (charCodeDefinitions$m.isName(getCharCode(offset + 1)) || charCodeDefinitions$m.isValidEscape(getCharCode(offset + 1), getCharCode(offset + 2))) {
// Create a <hash-token>.
type = types$1I.Hash;
// If the next 3 input code points would start an identifier, set the <hash-token>s type flag to "id".
// if (isIdentifierStart(getCharCode(offset + 1), getCharCode(offset + 2), getCharCode(offset + 3))) {
// // TODO: set id flag
// }
// Consume a name, and set the <hash-token>s value to the returned string.
offset = utils$s.consumeName(source, offset + 1);
// Return the <hash-token>.
} else {
// Otherwise, return a <delim-token> with its value set to the current input code point.
type = types$1I.Delim;
offset++;
}
break;
// U+0027 APOSTROPHE (')
case 0x0027:
// Consume a string token and return it.
consumeStringToken();
break;
// U+0028 LEFT PARENTHESIS (()
case 0x0028:
// Return a <(-token>.
type = types$1I.LeftParenthesis;
offset++;
break;
// U+0029 RIGHT PARENTHESIS ())
case 0x0029:
// Return a <)-token>.
type = types$1I.RightParenthesis;
offset++;
break;
// U+002B PLUS SIGN (+)
case 0x002B:
// If the input stream starts with a number, ...
if (charCodeDefinitions$m.isNumberStart(code, getCharCode(offset + 1), getCharCode(offset + 2))) {
// ... reconsume the current input code point, consume a numeric token, and return it.
consumeNumericToken();
} else {
// Otherwise, return a <delim-token> with its value set to the current input code point.
type = types$1I.Delim;
offset++;
}
break;
// U+002C COMMA (,)
case 0x002C:
// Return a <comma-token>.
type = types$1I.Comma;
offset++;
break;
// U+002D HYPHEN-MINUS (-)
case 0x002D:
// If the input stream starts with a number, reconsume the current input code point, consume a numeric token, and return it.
if (charCodeDefinitions$m.isNumberStart(code, getCharCode(offset + 1), getCharCode(offset + 2))) {
consumeNumericToken();
} else {
// Otherwise, if the next 2 input code points are U+002D HYPHEN-MINUS U+003E GREATER-THAN SIGN (->), consume them and return a <CDC-token>.
if (getCharCode(offset + 1) === 0x002D &&
getCharCode(offset + 2) === 0x003E) {
type = types$1I.CDC;
offset = offset + 3;
} else {
// Otherwise, if the input stream starts with an identifier, ...
if (charCodeDefinitions$m.isIdentifierStart(code, getCharCode(offset + 1), getCharCode(offset + 2))) {
// ... reconsume the current input code point, consume an ident-like token, and return it.
consumeIdentLikeToken();
} else {
// Otherwise, return a <delim-token> with its value set to the current input code point.
type = types$1I.Delim;
offset++;
}
}
}
break;
// U+002E FULL STOP (.)
case 0x002E:
// If the input stream starts with a number, ...
if (charCodeDefinitions$m.isNumberStart(code, getCharCode(offset + 1), getCharCode(offset + 2))) {
// ... reconsume the current input code point, consume a numeric token, and return it.
consumeNumericToken();
} else {
// Otherwise, return a <delim-token> with its value set to the current input code point.
type = types$1I.Delim;
offset++;
}
break;
// U+002F SOLIDUS (/)
case 0x002F:
// If the next two input code point are U+002F SOLIDUS (/) followed by a U+002A ASTERISK (*),
if (getCharCode(offset + 1) === 0x002A) {
// ... consume them and all following code points up to and including the first U+002A ASTERISK (*)
// followed by a U+002F SOLIDUS (/), or up to an EOF code point.
type = types$1I.Comment;
offset = source.indexOf('*/', offset + 2);
offset = offset === -1 ? source.length : offset + 2;
} else {
type = types$1I.Delim;
offset++;
}
break;
// U+003A COLON (:)
case 0x003A:
// Return a <colon-token>.
type = types$1I.Colon;
offset++;
break;
// U+003B SEMICOLON (;)
case 0x003B:
// Return a <semicolon-token>.
type = types$1I.Semicolon;
offset++;
break;
// U+003C LESS-THAN SIGN (<)
case 0x003C:
// If the next 3 input code points are U+0021 EXCLAMATION MARK U+002D HYPHEN-MINUS U+002D HYPHEN-MINUS (!--), ...
if (getCharCode(offset + 1) === 0x0021 &&
getCharCode(offset + 2) === 0x002D &&
getCharCode(offset + 3) === 0x002D) {
// ... consume them and return a <CDO-token>.
type = types$1I.CDO;
offset = offset + 4;
} else {
// Otherwise, return a <delim-token> with its value set to the current input code point.
type = types$1I.Delim;
offset++;
}
break;
// U+0040 COMMERCIAL AT (@)
case 0x0040:
// If the next 3 input code points would start an identifier, ...
if (charCodeDefinitions$m.isIdentifierStart(getCharCode(offset + 1), getCharCode(offset + 2), getCharCode(offset + 3))) {
// ... consume a name, create an <at-keyword-token> with its value set to the returned value, and return it.
type = types$1I.AtKeyword;
offset = utils$s.consumeName(source, offset + 1);
} else {
// Otherwise, return a <delim-token> with its value set to the current input code point.
type = types$1I.Delim;
offset++;
}
break;
// U+005B LEFT SQUARE BRACKET ([)
case 0x005B:
// Return a <[-token>.
type = types$1I.LeftSquareBracket;
offset++;
break;
// U+005C REVERSE SOLIDUS (\)
case 0x005C:
// If the input stream starts with a valid escape, ...
if (charCodeDefinitions$m.isValidEscape(code, getCharCode(offset + 1))) {
// ... reconsume the current input code point, consume an ident-like token, and return it.
consumeIdentLikeToken();
} else {
// Otherwise, this is a parse error. Return a <delim-token> with its value set to the current input code point.
type = types$1I.Delim;
offset++;
}
break;
// U+005D RIGHT SQUARE BRACKET (])
case 0x005D:
// Return a <]-token>.
type = types$1I.RightSquareBracket;
offset++;
break;
// U+007B LEFT CURLY BRACKET ({)
case 0x007B:
// Return a <{-token>.
type = types$1I.LeftCurlyBracket;
offset++;
break;
// U+007D RIGHT CURLY BRACKET (})
case 0x007D:
// Return a <}-token>.
type = types$1I.RightCurlyBracket;
offset++;
break;
// digit
case charCodeDefinitions$m.DigitCategory:
// Reconsume the current input code point, consume a numeric token, and return it.
consumeNumericToken();
break;
// name-start code point
case charCodeDefinitions$m.NameStartCategory:
// Reconsume the current input code point, consume an ident-like token, and return it.
consumeIdentLikeToken();
break;
// EOF
// case EofCategory:
// Return an <EOF-token>.
// break;
// anything else
default:
// Return a <delim-token> with its value set to the current input code point.
type = types$1I.Delim;
offset++;
}
// put token to stream
onToken(type, start, start = offset);
}
}
tokenizer$5.AtKeyword = types$1I.AtKeyword;
tokenizer$5.BadString = types$1I.BadString;
tokenizer$5.BadUrl = types$1I.BadUrl;
tokenizer$5.CDC = types$1I.CDC;
tokenizer$5.CDO = types$1I.CDO;
tokenizer$5.Colon = types$1I.Colon;
tokenizer$5.Comma = types$1I.Comma;
tokenizer$5.Comment = types$1I.Comment;
tokenizer$5.Delim = types$1I.Delim;
tokenizer$5.Dimension = types$1I.Dimension;
tokenizer$5.EOF = types$1I.EOF;
tokenizer$5.Function = types$1I.Function;
tokenizer$5.Hash = types$1I.Hash;
tokenizer$5.Ident = types$1I.Ident;
tokenizer$5.LeftCurlyBracket = types$1I.LeftCurlyBracket;
tokenizer$5.LeftParenthesis = types$1I.LeftParenthesis;
tokenizer$5.LeftSquareBracket = types$1I.LeftSquareBracket;
tokenizer$5.Number = types$1I.Number;
tokenizer$5.Percentage = types$1I.Percentage;
tokenizer$5.RightCurlyBracket = types$1I.RightCurlyBracket;
tokenizer$5.RightParenthesis = types$1I.RightParenthesis;
tokenizer$5.RightSquareBracket = types$1I.RightSquareBracket;
tokenizer$5.Semicolon = types$1I.Semicolon;
tokenizer$5.String = types$1I.String;
tokenizer$5.Url = types$1I.Url;
tokenizer$5.WhiteSpace = types$1I.WhiteSpace;
tokenizer$5.tokenTypes = types$1I;
tokenizer$5.DigitCategory = charCodeDefinitions$m.DigitCategory;
tokenizer$5.EofCategory = charCodeDefinitions$m.EofCategory;
tokenizer$5.NameStartCategory = charCodeDefinitions$m.NameStartCategory;
tokenizer$5.NonPrintableCategory = charCodeDefinitions$m.NonPrintableCategory;
tokenizer$5.WhiteSpaceCategory = charCodeDefinitions$m.WhiteSpaceCategory;
tokenizer$5.charCodeCategory = charCodeDefinitions$m.charCodeCategory;
tokenizer$5.isBOM = charCodeDefinitions$m.isBOM;
tokenizer$5.isDigit = charCodeDefinitions$m.isDigit;
tokenizer$5.isHexDigit = charCodeDefinitions$m.isHexDigit;
tokenizer$5.isIdentifierStart = charCodeDefinitions$m.isIdentifierStart;
tokenizer$5.isLetter = charCodeDefinitions$m.isLetter;
tokenizer$5.isLowercaseLetter = charCodeDefinitions$m.isLowercaseLetter;
tokenizer$5.isName = charCodeDefinitions$m.isName;
tokenizer$5.isNameStart = charCodeDefinitions$m.isNameStart;
tokenizer$5.isNewline = charCodeDefinitions$m.isNewline;
tokenizer$5.isNonAscii = charCodeDefinitions$m.isNonAscii;
tokenizer$5.isNonPrintable = charCodeDefinitions$m.isNonPrintable;
tokenizer$5.isNumberStart = charCodeDefinitions$m.isNumberStart;
tokenizer$5.isUppercaseLetter = charCodeDefinitions$m.isUppercaseLetter;
tokenizer$5.isValidEscape = charCodeDefinitions$m.isValidEscape;
tokenizer$5.isWhiteSpace = charCodeDefinitions$m.isWhiteSpace;
tokenizer$5.cmpChar = utils$s.cmpChar;
tokenizer$5.cmpStr = utils$s.cmpStr;
tokenizer$5.consumeBadUrlRemnants = utils$s.consumeBadUrlRemnants;
tokenizer$5.consumeEscaped = utils$s.consumeEscaped;
tokenizer$5.consumeName = utils$s.consumeName;
tokenizer$5.consumeNumber = utils$s.consumeNumber;
tokenizer$5.decodeEscaped = utils$s.decodeEscaped;
tokenizer$5.findDecimalNumberEnd = utils$s.findDecimalNumberEnd;
tokenizer$5.findWhiteSpaceEnd = utils$s.findWhiteSpaceEnd;
tokenizer$5.findWhiteSpaceStart = utils$s.findWhiteSpaceStart;
tokenizer$5.getNewlineLength = utils$s.getNewlineLength;
tokenizer$5.tokenNames = names$e;
tokenizer$5.OffsetToLocation = OffsetToLocation$5.OffsetToLocation;
tokenizer$5.TokenStream = TokenStream$7.TokenStream;
tokenizer$5.tokenize = tokenize$4;
var create$e = {};
var List$f = {};
//
// list
// ┌──────┐
// ┌──────────────┼─head │
// │ │ tail─┼──────────────┐
// │ └──────┘ │
// ▼ ▼
// item item item item
// ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
// null ◀──┼─prev │◀───┼─prev │◀───┼─prev │◀───┼─prev │
// │ next─┼───▶│ next─┼───▶│ next─┼───▶│ next─┼──▶ null
// ├──────┤ ├──────┤ ├──────┤ ├──────┤
// │ data │ │ data │ │ data │ │ data │
// └──────┘ └──────┘ └──────┘ └──────┘
//
let releasedCursors$1 = null;
let List$e = class List {
static createItem(data) {
return {
prev: null,
next: null,
data
};
}
constructor() {
this.head = null;
this.tail = null;
this.cursor = null;
}
createItem(data) {
return List.createItem(data);
}
// cursor helpers
allocateCursor(prev, next) {
let cursor;
if (releasedCursors$1 !== null) {
cursor = releasedCursors$1;
releasedCursors$1 = releasedCursors$1.cursor;
cursor.prev = prev;
cursor.next = next;
cursor.cursor = this.cursor;
} else {
cursor = {
prev,
next,
cursor: this.cursor
};
}
this.cursor = cursor;
return cursor;
}
releaseCursor() {
const { cursor } = this;
this.cursor = cursor.cursor;
cursor.prev = null;
cursor.next = null;
cursor.cursor = releasedCursors$1;
releasedCursors$1 = cursor;
}
updateCursors(prevOld, prevNew, nextOld, nextNew) {
let { cursor } = this;
while (cursor !== null) {
if (cursor.prev === prevOld) {
cursor.prev = prevNew;
}
if (cursor.next === nextOld) {
cursor.next = nextNew;
}
cursor = cursor.cursor;
}
}
*[Symbol.iterator]() {
for (let cursor = this.head; cursor !== null; cursor = cursor.next) {
yield cursor.data;
}
}
// getters
get size() {
let size = 0;
for (let cursor = this.head; cursor !== null; cursor = cursor.next) {
size++;
}
return size;
}
get isEmpty() {
return this.head === null;
}
get first() {
return this.head && this.head.data;
}
get last() {
return this.tail && this.tail.data;
}
// convertors
fromArray(array) {
let cursor = null;
this.head = null;
for (let data of array) {
const item = List.createItem(data);
if (cursor !== null) {
cursor.next = item;
} else {
this.head = item;
}
item.prev = cursor;
cursor = item;
}
this.tail = cursor;
return this;
}
toArray() {
return [...this];
}
toJSON() {
return [...this];
}
// array-like methods
forEach(fn, thisArg = this) {
// push cursor
const cursor = this.allocateCursor(null, this.head);
while (cursor.next !== null) {
const item = cursor.next;
cursor.next = item.next;
fn.call(thisArg, item.data, item, this);
}
// pop cursor
this.releaseCursor();
}
forEachRight(fn, thisArg = this) {
// push cursor
const cursor = this.allocateCursor(this.tail, null);
while (cursor.prev !== null) {
const item = cursor.prev;
cursor.prev = item.prev;
fn.call(thisArg, item.data, item, this);
}
// pop cursor
this.releaseCursor();
}
reduce(fn, initialValue, thisArg = this) {
// push cursor
let cursor = this.allocateCursor(null, this.head);
let acc = initialValue;
let item;
while (cursor.next !== null) {
item = cursor.next;
cursor.next = item.next;
acc = fn.call(thisArg, acc, item.data, item, this);
}
// pop cursor
this.releaseCursor();
return acc;
}
reduceRight(fn, initialValue, thisArg = this) {
// push cursor
let cursor = this.allocateCursor(this.tail, null);
let acc = initialValue;
let item;
while (cursor.prev !== null) {
item = cursor.prev;
cursor.prev = item.prev;
acc = fn.call(thisArg, acc, item.data, item, this);
}
// pop cursor
this.releaseCursor();
return acc;
}
some(fn, thisArg = this) {
for (let cursor = this.head; cursor !== null; cursor = cursor.next) {
if (fn.call(thisArg, cursor.data, cursor, this)) {
return true;
}
}
return false;
}
map(fn, thisArg = this) {
const result = new List();
for (let cursor = this.head; cursor !== null; cursor = cursor.next) {
result.appendData(fn.call(thisArg, cursor.data, cursor, this));
}
return result;
}
filter(fn, thisArg = this) {
const result = new List();
for (let cursor = this.head; cursor !== null; cursor = cursor.next) {
if (fn.call(thisArg, cursor.data, cursor, this)) {
result.appendData(cursor.data);
}
}
return result;
}
nextUntil(start, fn, thisArg = this) {
if (start === null) {
return;
}
// push cursor
const cursor = this.allocateCursor(null, start);
while (cursor.next !== null) {
const item = cursor.next;
cursor.next = item.next;
if (fn.call(thisArg, item.data, item, this)) {
break;
}
}
// pop cursor
this.releaseCursor();
}
prevUntil(start, fn, thisArg = this) {
if (start === null) {
return;
}
// push cursor
const cursor = this.allocateCursor(start, null);
while (cursor.prev !== null) {
const item = cursor.prev;
cursor.prev = item.prev;
if (fn.call(thisArg, item.data, item, this)) {
break;
}
}
// pop cursor
this.releaseCursor();
}
// mutation
clear() {
this.head = null;
this.tail = null;
}
copy() {
const result = new List();
for (let data of this) {
result.appendData(data);
}
return result;
}
prepend(item) {
// head
// ^
// item
this.updateCursors(null, item, this.head, item);
// insert to the beginning of the list
if (this.head !== null) {
// new item <- first item
this.head.prev = item;
// new item -> first item
item.next = this.head;
} else {
// if list has no head, then it also has no tail
// in this case tail points to the new item
this.tail = item;
}
// head always points to new item
this.head = item;
return this;
}
prependData(data) {
return this.prepend(List.createItem(data));
}
append(item) {
return this.insert(item);
}
appendData(data) {
return this.insert(List.createItem(data));
}
insert(item, before = null) {
if (before !== null) {
// prev before
// ^
// item
this.updateCursors(before.prev, item, before, item);
if (before.prev === null) {
// insert to the beginning of list
if (this.head !== before) {
throw new Error('before doesn\'t belong to list');
}
// since head points to before therefore list doesn't empty
// no need to check tail
this.head = item;
before.prev = item;
item.next = before;
this.updateCursors(null, item);
} else {
// insert between two items
before.prev.next = item;
item.prev = before.prev;
before.prev = item;
item.next = before;
}
} else {
// tail
// ^
// item
this.updateCursors(this.tail, item, null, item);
// insert to the ending of the list
if (this.tail !== null) {
// last item -> new item
this.tail.next = item;
// last item <- new item
item.prev = this.tail;
} else {
// if list has no tail, then it also has no head
// in this case head points to new item
this.head = item;
}
// tail always points to new item
this.tail = item;
}
return this;
}
insertData(data, before) {
return this.insert(List.createItem(data), before);
}
remove(item) {
// item
// ^
// prev next
this.updateCursors(item, item.prev, item, item.next);
if (item.prev !== null) {
item.prev.next = item.next;
} else {
if (this.head !== item) {
throw new Error('item doesn\'t belong to list');
}
this.head = item.next;
}
if (item.next !== null) {
item.next.prev = item.prev;
} else {
if (this.tail !== item) {
throw new Error('item doesn\'t belong to list');
}
this.tail = item.prev;
}
item.prev = null;
item.next = null;
return item;
}
push(data) {
this.insert(List.createItem(data));
}
pop() {
return this.tail !== null ? this.remove(this.tail) : null;
}
unshift(data) {
this.prepend(List.createItem(data));
}
shift() {
return this.head !== null ? this.remove(this.head) : null;
}
prependList(list) {
return this.insertList(list, this.head);
}
appendList(list) {
return this.insertList(list);
}
insertList(list, before) {
// ignore empty lists
if (list.head === null) {
return this;
}
if (before !== undefined && before !== null) {
this.updateCursors(before.prev, list.tail, before, list.head);
// insert in the middle of dist list
if (before.prev !== null) {
// before.prev <-> list.head
before.prev.next = list.head;
list.head.prev = before.prev;
} else {
this.head = list.head;
}
before.prev = list.tail;
list.tail.next = before;
} else {
this.updateCursors(this.tail, list.tail, null, list.head);
// insert to end of the list
if (this.tail !== null) {
// if destination list has a tail, then it also has a head,
// but head doesn't change
// dest tail -> source head
this.tail.next = list.head;
// dest tail <- source head
list.head.prev = this.tail;
} else {
// if list has no a tail, then it also has no a head
// in this case points head to new item
this.head = list.head;
}
// tail always start point to new item
this.tail = list.tail;
}
list.head = null;
list.tail = null;
return this;
}
replace(oldItem, newItemOrList) {
if ('head' in newItemOrList) {
this.insertList(newItemOrList, oldItem);
} else {
this.insert(newItemOrList, oldItem);
}
this.remove(oldItem);
}
};
List$f.List = List$e;
var _SyntaxError$3 = {};
var createCustomError$9 = {};
function createCustomError$8(name, message) {
// use Object.create(), because some VMs prevent setting line/column otherwise
// (iOS Safari 10 even throws an exception)
const error = Object.create(SyntaxError.prototype);
const errorStack = new Error();
return Object.assign(error, {
name,
message,
get stack() {
return (errorStack.stack || '').replace(/^(.+\n){1,3}/, `${name}: ${message}\n`);
}
});
}
createCustomError$9.createCustomError = createCustomError$8;
const createCustomError$7 = createCustomError$9;
const MAX_LINE_LENGTH$1 = 100;
const OFFSET_CORRECTION$1 = 60;
const TAB_REPLACEMENT$1 = ' ';
function sourceFragment$1({ source, line, column }, extraLines) {
function processLines(start, end) {
return lines
.slice(start, end)
.map((line, idx) =>
String(start + idx + 1).padStart(maxNumLength) + ' |' + line
).join('\n');
}
const lines = source.split(/\r\n?|\n|\f/);
const startLine = Math.max(1, line - extraLines) - 1;
const endLine = Math.min(line + extraLines, lines.length + 1);
const maxNumLength = Math.max(4, String(endLine).length) + 1;
let cutLeft = 0;
// column correction according to replaced tab before column
column += (TAB_REPLACEMENT$1.length - 1) * (lines[line - 1].substr(0, column - 1).match(/\t/g) || []).length;
if (column > MAX_LINE_LENGTH$1) {
cutLeft = column - OFFSET_CORRECTION$1 + 3;
column = OFFSET_CORRECTION$1 - 2;
}
for (let i = startLine; i <= endLine; i++) {
if (i >= 0 && i < lines.length) {
lines[i] = lines[i].replace(/\t/g, TAB_REPLACEMENT$1);
lines[i] =
(cutLeft > 0 && lines[i].length > cutLeft ? '\u2026' : '') +
lines[i].substr(cutLeft, MAX_LINE_LENGTH$1 - 2) +
(lines[i].length > cutLeft + MAX_LINE_LENGTH$1 - 1 ? '\u2026' : '');
}
}
return [
processLines(startLine, line),
new Array(column + maxNumLength + 2).join('-') + '^',
processLines(line, endLine)
].filter(Boolean).join('\n');
}
function SyntaxError$a(message, source, offset, line, column) {
const error = Object.assign(createCustomError$7.createCustomError('SyntaxError', message), {
source,
offset,
line,
column,
sourceFragment(extraLines) {
return sourceFragment$1({ source, line, column }, isNaN(extraLines) ? 0 : extraLines);
},
get formattedMessage() {
return (
`Parse error: ${message}\n` +
sourceFragment$1({ source, line, column }, 2)
);
}
});
return error;
}
_SyntaxError$3.SyntaxError = SyntaxError$a;
var sequence$3 = {};
const types$1H = types$1K;
function readSequence$3(recognizer) {
const children = this.createList();
let space = false;
const context = {
recognizer
};
while (!this.eof) {
switch (this.tokenType) {
case types$1H.Comment:
this.next();
continue;
case types$1H.WhiteSpace:
space = true;
this.next();
continue;
}
let child = recognizer.getNode.call(this, context);
if (child === undefined) {
break;
}
if (space) {
if (recognizer.onWhiteSpace) {
recognizer.onWhiteSpace.call(this, child, children, context);
}
space = false;
}
children.push(child);
}
if (space && recognizer.onWhiteSpace) {
recognizer.onWhiteSpace.call(this, null, children, context);
}
return children;
}
sequence$3.readSequence = readSequence$3;
const List$d = List$f;
const SyntaxError$9 = _SyntaxError$3;
const index$j = tokenizer$5;
const sequence$2 = sequence$3;
const OffsetToLocation$4 = OffsetToLocation$7;
const TokenStream$6 = TokenStream$9;
const utils$r = utils$u;
const types$1G = types$1K;
const names$d = names$g;
const NOOP$1 = () => {};
const EXCLAMATIONMARK$7 = 0x0021; // U+0021 EXCLAMATION MARK (!)
const NUMBERSIGN$9 = 0x0023; // U+0023 NUMBER SIGN (#)
const SEMICOLON$1 = 0x003B; // U+003B SEMICOLON (;)
const LEFTCURLYBRACKET$3 = 0x007B; // U+007B LEFT CURLY BRACKET ({)
const NULL$1 = 0;
function createParseContext$1(name) {
return function() {
return this[name]();
};
}
function fetchParseValues$1(dict) {
const result = Object.create(null);
for (const name in dict) {
const item = dict[name];
const fn = item.parse || item;
if (fn) {
result[name] = fn;
}
}
return result;
}
function processConfig$1(config) {
const parseConfig = {
context: Object.create(null),
scope: Object.assign(Object.create(null), config.scope),
atrule: fetchParseValues$1(config.atrule),
pseudo: fetchParseValues$1(config.pseudo),
node: fetchParseValues$1(config.node)
};
for (const name in config.parseContext) {
switch (typeof config.parseContext[name]) {
case 'function':
parseConfig.context[name] = config.parseContext[name];
break;
case 'string':
parseConfig.context[name] = createParseContext$1(config.parseContext[name]);
break;
}
}
return {
config: parseConfig,
...parseConfig,
...parseConfig.node
};
}
function createParser$1(config) {
let source = '';
let filename = '<unknown>';
let needPositions = false;
let onParseError = NOOP$1;
let onParseErrorThrow = false;
const locationMap = new OffsetToLocation$4.OffsetToLocation();
const parser = Object.assign(new TokenStream$6.TokenStream(), processConfig$1(config || {}), {
parseAtrulePrelude: true,
parseRulePrelude: true,
parseValue: true,
parseCustomProperty: false,
readSequence: sequence$2.readSequence,
consumeUntilBalanceEnd: () => 0,
consumeUntilLeftCurlyBracket(code) {
return code === LEFTCURLYBRACKET$3 ? 1 : 0;
},
consumeUntilLeftCurlyBracketOrSemicolon(code) {
return code === LEFTCURLYBRACKET$3 || code === SEMICOLON$1 ? 1 : 0;
},
consumeUntilExclamationMarkOrSemicolon(code) {
return code === EXCLAMATIONMARK$7 || code === SEMICOLON$1 ? 1 : 0;
},
consumeUntilSemicolonIncluded(code) {
return code === SEMICOLON$1 ? 2 : 0;
},
createList() {
return new List$d.List();
},
createSingleNodeList(node) {
return new List$d.List().appendData(node);
},
getFirstListNode(list) {
return list && list.first;
},
getLastListNode(list) {
return list && list.last;
},
parseWithFallback(consumer, fallback) {
const startToken = this.tokenIndex;
try {
return consumer.call(this);
} catch (e) {
if (onParseErrorThrow) {
throw e;
}
const fallbackNode = fallback.call(this, startToken);
onParseErrorThrow = true;
onParseError(e, fallbackNode);
onParseErrorThrow = false;
return fallbackNode;
}
},
lookupNonWSType(offset) {
let type;
do {
type = this.lookupType(offset++);
if (type !== types$1G.WhiteSpace) {
return type;
}
} while (type !== NULL$1);
return NULL$1;
},
charCodeAt(offset) {
return offset >= 0 && offset < source.length ? source.charCodeAt(offset) : 0;
},
substring(offsetStart, offsetEnd) {
return source.substring(offsetStart, offsetEnd);
},
substrToCursor(start) {
return this.source.substring(start, this.tokenStart);
},
cmpChar(offset, charCode) {
return utils$r.cmpChar(source, offset, charCode);
},
cmpStr(offsetStart, offsetEnd, str) {
return utils$r.cmpStr(source, offsetStart, offsetEnd, str);
},
consume(tokenType) {
const start = this.tokenStart;
this.eat(tokenType);
return this.substrToCursor(start);
},
consumeFunctionName() {
const name = source.substring(this.tokenStart, this.tokenEnd - 1);
this.eat(types$1G.Function);
return name;
},
consumeNumber(type) {
const number = source.substring(this.tokenStart, utils$r.consumeNumber(source, this.tokenStart));
this.eat(type);
return number;
},
eat(tokenType) {
if (this.tokenType !== tokenType) {
const tokenName = names$d[tokenType].slice(0, -6).replace(/-/g, ' ').replace(/^./, m => m.toUpperCase());
let message = `${/[[\](){}]/.test(tokenName) ? `"${tokenName}"` : tokenName} is expected`;
let offset = this.tokenStart;
// tweak message and offset
switch (tokenType) {
case types$1G.Ident:
// when identifier is expected but there is a function or url
if (this.tokenType === types$1G.Function || this.tokenType === types$1G.Url) {
offset = this.tokenEnd - 1;
message = 'Identifier is expected but function found';
} else {
message = 'Identifier is expected';
}
break;
case types$1G.Hash:
if (this.isDelim(NUMBERSIGN$9)) {
this.next();
offset++;
message = 'Name is expected';
}
break;
case types$1G.Percentage:
if (this.tokenType === types$1G.Number) {
offset = this.tokenEnd;
message = 'Percent sign is expected';
}
break;
}
this.error(message, offset);
}
this.next();
},
eatIdent(name) {
if (this.tokenType !== types$1G.Ident || this.lookupValue(0, name) === false) {
this.error(`Identifier "${name}" is expected`);
}
this.next();
},
eatDelim(code) {
if (!this.isDelim(code)) {
this.error(`Delim "${String.fromCharCode(code)}" is expected`);
}
this.next();
},
getLocation(start, end) {
if (needPositions) {
return locationMap.getLocationRange(
start,
end,
filename
);
}
return null;
},
getLocationFromList(list) {
if (needPositions) {
const head = this.getFirstListNode(list);
const tail = this.getLastListNode(list);
return locationMap.getLocationRange(
head !== null ? head.loc.start.offset - locationMap.startOffset : this.tokenStart,
tail !== null ? tail.loc.end.offset - locationMap.startOffset : this.tokenStart,
filename
);
}
return null;
},
error(message, offset) {
const location = typeof offset !== 'undefined' && offset < source.length
? locationMap.getLocation(offset)
: this.eof
? locationMap.getLocation(utils$r.findWhiteSpaceStart(source, source.length - 1))
: locationMap.getLocation(this.tokenStart);
throw new SyntaxError$9.SyntaxError(
message || 'Unexpected input',
source,
location.offset,
location.line,
location.column
);
}
});
const parse = function(source_, options) {
source = source_;
options = options || {};
parser.setSource(source, index$j.tokenize);
locationMap.setSource(
source,
options.offset,
options.line,
options.column
);
filename = options.filename || '<unknown>';
needPositions = Boolean(options.positions);
onParseError = typeof options.onParseError === 'function' ? options.onParseError : NOOP$1;
onParseErrorThrow = false;
parser.parseAtrulePrelude = 'parseAtrulePrelude' in options ? Boolean(options.parseAtrulePrelude) : true;
parser.parseRulePrelude = 'parseRulePrelude' in options ? Boolean(options.parseRulePrelude) : true;
parser.parseValue = 'parseValue' in options ? Boolean(options.parseValue) : true;
parser.parseCustomProperty = 'parseCustomProperty' in options ? Boolean(options.parseCustomProperty) : false;
const { context = 'default', onComment } = options;
if (context in parser.context === false) {
throw new Error('Unknown context `' + context + '`');
}
if (typeof onComment === 'function') {
parser.forEachToken((type, start, end) => {
if (type === types$1G.Comment) {
const loc = parser.getLocation(start, end);
const value = utils$r.cmpStr(source, end - 2, end, '*/')
? source.slice(start + 2, end - 2)
: source.slice(start + 2, end);
onComment(value, loc);
}
});
}
const ast = parser.context[context].call(parser, options);
if (!parser.eof) {
parser.error();
}
return ast;
};
return Object.assign(parse, {
SyntaxError: SyntaxError$9.SyntaxError,
config: parser.config
});
}
create$e.createParser = createParser$1;
var create$d = {};
var sourceMap$3 = {};
const sourceMapGenerator_js$1 = require$$0$9;
const trackNodes$1 = new Set(['Atrule', 'Selector', 'Declaration']);
function generateSourceMap$1(handlers) {
const map = new sourceMapGenerator_js$1.SourceMapGenerator();
const generated = {
line: 1,
column: 0
};
const original = {
line: 0, // should be zero to add first mapping
column: 0
};
const activatedGenerated = {
line: 1,
column: 0
};
const activatedMapping = {
generated: activatedGenerated
};
let line = 1;
let column = 0;
let sourceMappingActive = false;
const origHandlersNode = handlers.node;
handlers.node = function(node) {
if (node.loc && node.loc.start && trackNodes$1.has(node.type)) {
const nodeLine = node.loc.start.line;
const nodeColumn = node.loc.start.column - 1;
if (original.line !== nodeLine ||
original.column !== nodeColumn) {
original.line = nodeLine;
original.column = nodeColumn;
generated.line = line;
generated.column = column;
if (sourceMappingActive) {
sourceMappingActive = false;
if (generated.line !== activatedGenerated.line ||
generated.column !== activatedGenerated.column) {
map.addMapping(activatedMapping);
}
}
sourceMappingActive = true;
map.addMapping({
source: node.loc.source,
original,
generated
});
}
}
origHandlersNode.call(this, node);
if (sourceMappingActive && trackNodes$1.has(node.type)) {
activatedGenerated.line = line;
activatedGenerated.column = column;
}
};
const origHandlersEmit = handlers.emit;
handlers.emit = function(value, type, auto) {
for (let i = 0; i < value.length; i++) {
if (value.charCodeAt(i) === 10) { // \n
line++;
column = 0;
} else {
column++;
}
}
origHandlersEmit(value, type, auto);
};
const origHandlersResult = handlers.result;
handlers.result = function() {
if (sourceMappingActive) {
map.addMapping(activatedMapping);
}
return {
css: origHandlersResult(),
map
};
};
return handlers;
}
sourceMap$3.generateSourceMap = generateSourceMap$1;
var tokenBefore$3 = {};
const types$1F = types$1K;
const PLUSSIGN$j = 0x002B; // U+002B PLUS SIGN (+)
const HYPHENMINUS$d = 0x002D; // U+002D HYPHEN-MINUS (-)
const code$1 = (type, value) => {
if (type === types$1F.Delim) {
type = value;
}
if (typeof type === 'string') {
const charCode = type.charCodeAt(0);
return charCode > 0x7F ? 0x8000 : charCode << 8;
}
return type;
};
// https://www.w3.org/TR/css-syntax-3/#serialization
// The only requirement for serialization is that it must "round-trip" with parsing,
// that is, parsing the stylesheet must produce the same data structures as parsing,
// serializing, and parsing again, except for consecutive <whitespace-token>s,
// which may be collapsed into a single token.
const specPairs$1 = [
[types$1F.Ident, types$1F.Ident],
[types$1F.Ident, types$1F.Function],
[types$1F.Ident, types$1F.Url],
[types$1F.Ident, types$1F.BadUrl],
[types$1F.Ident, '-'],
[types$1F.Ident, types$1F.Number],
[types$1F.Ident, types$1F.Percentage],
[types$1F.Ident, types$1F.Dimension],
[types$1F.Ident, types$1F.CDC],
[types$1F.Ident, types$1F.LeftParenthesis],
[types$1F.AtKeyword, types$1F.Ident],
[types$1F.AtKeyword, types$1F.Function],
[types$1F.AtKeyword, types$1F.Url],
[types$1F.AtKeyword, types$1F.BadUrl],
[types$1F.AtKeyword, '-'],
[types$1F.AtKeyword, types$1F.Number],
[types$1F.AtKeyword, types$1F.Percentage],
[types$1F.AtKeyword, types$1F.Dimension],
[types$1F.AtKeyword, types$1F.CDC],
[types$1F.Hash, types$1F.Ident],
[types$1F.Hash, types$1F.Function],
[types$1F.Hash, types$1F.Url],
[types$1F.Hash, types$1F.BadUrl],
[types$1F.Hash, '-'],
[types$1F.Hash, types$1F.Number],
[types$1F.Hash, types$1F.Percentage],
[types$1F.Hash, types$1F.Dimension],
[types$1F.Hash, types$1F.CDC],
[types$1F.Dimension, types$1F.Ident],
[types$1F.Dimension, types$1F.Function],
[types$1F.Dimension, types$1F.Url],
[types$1F.Dimension, types$1F.BadUrl],
[types$1F.Dimension, '-'],
[types$1F.Dimension, types$1F.Number],
[types$1F.Dimension, types$1F.Percentage],
[types$1F.Dimension, types$1F.Dimension],
[types$1F.Dimension, types$1F.CDC],
['#', types$1F.Ident],
['#', types$1F.Function],
['#', types$1F.Url],
['#', types$1F.BadUrl],
['#', '-'],
['#', types$1F.Number],
['#', types$1F.Percentage],
['#', types$1F.Dimension],
['#', types$1F.CDC], // https://github.com/w3c/csswg-drafts/pull/6874
['-', types$1F.Ident],
['-', types$1F.Function],
['-', types$1F.Url],
['-', types$1F.BadUrl],
['-', '-'],
['-', types$1F.Number],
['-', types$1F.Percentage],
['-', types$1F.Dimension],
['-', types$1F.CDC], // https://github.com/w3c/csswg-drafts/pull/6874
[types$1F.Number, types$1F.Ident],
[types$1F.Number, types$1F.Function],
[types$1F.Number, types$1F.Url],
[types$1F.Number, types$1F.BadUrl],
[types$1F.Number, types$1F.Number],
[types$1F.Number, types$1F.Percentage],
[types$1F.Number, types$1F.Dimension],
[types$1F.Number, '%'],
[types$1F.Number, types$1F.CDC], // https://github.com/w3c/csswg-drafts/pull/6874
['@', types$1F.Ident],
['@', types$1F.Function],
['@', types$1F.Url],
['@', types$1F.BadUrl],
['@', '-'],
['@', types$1F.CDC], // https://github.com/w3c/csswg-drafts/pull/6874
['.', types$1F.Number],
['.', types$1F.Percentage],
['.', types$1F.Dimension],
['+', types$1F.Number],
['+', types$1F.Percentage],
['+', types$1F.Dimension],
['/', '*']
];
// validate with scripts/generate-safe
const safePairs$1 = specPairs$1.concat([
[types$1F.Ident, types$1F.Hash],
[types$1F.Dimension, types$1F.Hash],
[types$1F.Hash, types$1F.Hash],
[types$1F.AtKeyword, types$1F.LeftParenthesis],
[types$1F.AtKeyword, types$1F.String],
[types$1F.AtKeyword, types$1F.Colon],
[types$1F.Percentage, types$1F.Percentage],
[types$1F.Percentage, types$1F.Dimension],
[types$1F.Percentage, types$1F.Function],
[types$1F.Percentage, '-'],
[types$1F.RightParenthesis, types$1F.Ident],
[types$1F.RightParenthesis, types$1F.Function],
[types$1F.RightParenthesis, types$1F.Percentage],
[types$1F.RightParenthesis, types$1F.Dimension],
[types$1F.RightParenthesis, types$1F.Hash],
[types$1F.RightParenthesis, '-']
]);
function createMap$1(pairs) {
const isWhiteSpaceRequired = new Set(
pairs.map(([prev, next]) => (code$1(prev) << 16 | code$1(next)))
);
return function(prevCode, type, value) {
const nextCode = code$1(type, value);
const nextCharCode = value.charCodeAt(0);
const emitWs =
(nextCharCode === HYPHENMINUS$d &&
type !== types$1F.Ident &&
type !== types$1F.Function &&
type !== types$1F.CDC) ||
(nextCharCode === PLUSSIGN$j)
? isWhiteSpaceRequired.has(prevCode << 16 | nextCharCode << 8)
: isWhiteSpaceRequired.has(prevCode << 16 | nextCode);
if (emitWs) {
this.emit(' ', types$1F.WhiteSpace, true);
}
return nextCode;
};
}
const spec$1 = createMap$1(specPairs$1);
const safe$1 = createMap$1(safePairs$1);
tokenBefore$3.safe = safe$1;
tokenBefore$3.spec = spec$1;
const index$i = tokenizer$5;
const sourceMap$2 = sourceMap$3;
const tokenBefore$2 = tokenBefore$3;
const types$1E = types$1K;
const REVERSESOLIDUS$1 = 0x005c; // U+005C REVERSE SOLIDUS (\)
function processChildren$1(node, delimeter) {
if (typeof delimeter === 'function') {
let prev = null;
node.children.forEach(node => {
if (prev !== null) {
delimeter.call(this, prev);
}
this.node(node);
prev = node;
});
return;
}
node.children.forEach(this.node, this);
}
function processChunk$1(chunk) {
index$i.tokenize(chunk, (type, start, end) => {
this.token(type, chunk.slice(start, end));
});
}
function createGenerator$1(config) {
const types$1 = new Map();
for (let name in config.node) {
const item = config.node[name];
const fn = item.generate || item;
if (typeof fn === 'function') {
types$1.set(name, item.generate || item);
}
}
return function(node, options) {
let buffer = '';
let prevCode = 0;
let handlers = {
node(node) {
if (types$1.has(node.type)) {
types$1.get(node.type).call(publicApi, node);
} else {
throw new Error('Unknown node type: ' + node.type);
}
},
tokenBefore: tokenBefore$2.safe,
token(type, value) {
prevCode = this.tokenBefore(prevCode, type, value);
this.emit(value, type, false);
if (type === types$1E.Delim && value.charCodeAt(0) === REVERSESOLIDUS$1) {
this.emit('\n', types$1E.WhiteSpace, true);
}
},
emit(value) {
buffer += value;
},
result() {
return buffer;
}
};
if (options) {
if (typeof options.decorator === 'function') {
handlers = options.decorator(handlers);
}
if (options.sourceMap) {
handlers = sourceMap$2.generateSourceMap(handlers);
}
if (options.mode in tokenBefore$2) {
handlers.tokenBefore = tokenBefore$2[options.mode];
}
}
const publicApi = {
node: (node) => handlers.node(node),
children: processChildren$1,
token: (type, value) => handlers.token(type, value),
tokenize: processChunk$1
};
handlers.node(node);
return handlers.result();
};
}
create$d.createGenerator = createGenerator$1;
var create$c = {};
const List$c = List$f;
function createConvertor$1(walk) {
return {
fromPlainObject(ast) {
walk(ast, {
enter(node) {
if (node.children && node.children instanceof List$c.List === false) {
node.children = new List$c.List().fromArray(node.children);
}
}
});
return ast;
},
toPlainObject(ast) {
walk(ast, {
leave(node) {
if (node.children && node.children instanceof List$c.List) {
node.children = node.children.toArray();
}
}
});
return ast;
}
};
}
create$c.createConvertor = createConvertor$1;
var create$b = {};
const { hasOwnProperty: hasOwnProperty$b } = Object.prototype;
const noop$5 = function() {};
function ensureFunction$3(value) {
return typeof value === 'function' ? value : noop$5;
}
function invokeForType$1(fn, type) {
return function(node, item, list) {
if (node.type === type) {
fn.call(this, node, item, list);
}
};
}
function getWalkersFromStructure$1(name, nodeType) {
const structure = nodeType.structure;
const walkers = [];
for (const key in structure) {
if (hasOwnProperty$b.call(structure, key) === false) {
continue;
}
let fieldTypes = structure[key];
const walker = {
name: key,
type: false,
nullable: false
};
if (!Array.isArray(fieldTypes)) {
fieldTypes = [fieldTypes];
}
for (const fieldType of fieldTypes) {
if (fieldType === null) {
walker.nullable = true;
} else if (typeof fieldType === 'string') {
walker.type = 'node';
} else if (Array.isArray(fieldType)) {
walker.type = 'list';
}
}
if (walker.type) {
walkers.push(walker);
}
}
if (walkers.length) {
return {
context: nodeType.walkContext,
fields: walkers
};
}
return null;
}
function getTypesFromConfig$1(config) {
const types = {};
for (const name in config.node) {
if (hasOwnProperty$b.call(config.node, name)) {
const nodeType = config.node[name];
if (!nodeType.structure) {
throw new Error('Missed `structure` field in `' + name + '` node type definition');
}
types[name] = getWalkersFromStructure$1(name, nodeType);
}
}
return types;
}
function createTypeIterator$1(config, reverse) {
const fields = config.fields.slice();
const contextName = config.context;
const useContext = typeof contextName === 'string';
if (reverse) {
fields.reverse();
}
return function(node, context, walk, walkReducer) {
let prevContextValue;
if (useContext) {
prevContextValue = context[contextName];
context[contextName] = node;
}
for (const field of fields) {
const ref = node[field.name];
if (!field.nullable || ref) {
if (field.type === 'list') {
const breakWalk = reverse
? ref.reduceRight(walkReducer, false)
: ref.reduce(walkReducer, false);
if (breakWalk) {
return true;
}
} else if (walk(ref)) {
return true;
}
}
}
if (useContext) {
context[contextName] = prevContextValue;
}
};
}
function createFastTraveralMap$1({
StyleSheet,
Atrule,
Rule,
Block,
DeclarationList
}) {
return {
Atrule: {
StyleSheet,
Atrule,
Rule,
Block
},
Rule: {
StyleSheet,
Atrule,
Rule,
Block
},
Declaration: {
StyleSheet,
Atrule,
Rule,
Block,
DeclarationList
}
};
}
function createWalker$1(config) {
const types = getTypesFromConfig$1(config);
const iteratorsNatural = {};
const iteratorsReverse = {};
const breakWalk = Symbol('break-walk');
const skipNode = Symbol('skip-node');
for (const name in types) {
if (hasOwnProperty$b.call(types, name) && types[name] !== null) {
iteratorsNatural[name] = createTypeIterator$1(types[name], false);
iteratorsReverse[name] = createTypeIterator$1(types[name], true);
}
}
const fastTraversalIteratorsNatural = createFastTraveralMap$1(iteratorsNatural);
const fastTraversalIteratorsReverse = createFastTraveralMap$1(iteratorsReverse);
const walk = function(root, options) {
function walkNode(node, item, list) {
const enterRet = enter.call(context, node, item, list);
if (enterRet === breakWalk) {
return true;
}
if (enterRet === skipNode) {
return false;
}
if (iterators.hasOwnProperty(node.type)) {
if (iterators[node.type](node, context, walkNode, walkReducer)) {
return true;
}
}
if (leave.call(context, node, item, list) === breakWalk) {
return true;
}
return false;
}
let enter = noop$5;
let leave = noop$5;
let iterators = iteratorsNatural;
let walkReducer = (ret, data, item, list) => ret || walkNode(data, item, list);
const context = {
break: breakWalk,
skip: skipNode,
root,
stylesheet: null,
atrule: null,
atrulePrelude: null,
rule: null,
selector: null,
block: null,
declaration: null,
function: null
};
if (typeof options === 'function') {
enter = options;
} else if (options) {
enter = ensureFunction$3(options.enter);
leave = ensureFunction$3(options.leave);
if (options.reverse) {
iterators = iteratorsReverse;
}
if (options.visit) {
if (fastTraversalIteratorsNatural.hasOwnProperty(options.visit)) {
iterators = options.reverse
? fastTraversalIteratorsReverse[options.visit]
: fastTraversalIteratorsNatural[options.visit];
} else if (!types.hasOwnProperty(options.visit)) {
throw new Error('Bad value `' + options.visit + '` for `visit` option (should be: ' + Object.keys(types).sort().join(', ') + ')');
}
enter = invokeForType$1(enter, options.visit);
leave = invokeForType$1(leave, options.visit);
}
}
if (enter === noop$5 && leave === noop$5) {
throw new Error('Neither `enter` nor `leave` walker handler is set or both aren\'t a function');
}
walkNode(root);
};
walk.break = breakWalk;
walk.skip = skipNode;
walk.find = function(ast, fn) {
let found = null;
walk(ast, function(node, item, list) {
if (fn.call(this, node, item, list)) {
found = node;
return breakWalk;
}
});
return found;
};
walk.findLast = function(ast, fn) {
let found = null;
walk(ast, {
reverse: true,
enter(node, item, list) {
if (fn.call(this, node, item, list)) {
found = node;
return breakWalk;
}
}
});
return found;
};
walk.findAll = function(ast, fn) {
const found = [];
walk(ast, function(node, item, list) {
if (fn.call(this, node, item, list)) {
found.push(node);
}
});
return found;
};
return walk;
}
create$b.createWalker = createWalker$1;
var Lexer$7 = {};
var error$4 = {};
var generate$1u = {};
function noop$4(value) {
return value;
}
function generateMultiplier$1(multiplier) {
const { min, max, comma } = multiplier;
if (min === 0 && max === 0) {
return comma ? '#?' : '*';
}
if (min === 0 && max === 1) {
return '?';
}
if (min === 1 && max === 0) {
return comma ? '#' : '+';
}
if (min === 1 && max === 1) {
return '';
}
return (
(comma ? '#' : '') +
(min === max
? '{' + min + '}'
: '{' + min + ',' + (max !== 0 ? max : '') + '}'
)
);
}
function generateTypeOpts$1(node) {
switch (node.type) {
case 'Range':
return (
' [' +
(node.min === null ? '-∞' : node.min) +
',' +
(node.max === null ? '∞' : node.max) +
']'
);
default:
throw new Error('Unknown node type `' + node.type + '`');
}
}
function generateSequence$1(node, decorate, forceBraces, compact) {
const combinator = node.combinator === ' ' || compact ? node.combinator : ' ' + node.combinator + ' ';
const result = node.terms
.map(term => internalGenerate$1(term, decorate, forceBraces, compact))
.join(combinator);
if (node.explicit || forceBraces) {
return (compact || result[0] === ',' ? '[' : '[ ') + result + (compact ? ']' : ' ]');
}
return result;
}
function internalGenerate$1(node, decorate, forceBraces, compact) {
let result;
switch (node.type) {
case 'Group':
result =
generateSequence$1(node, decorate, forceBraces, compact) +
(node.disallowEmpty ? '!' : '');
break;
case 'Multiplier':
// return since node is a composition
return (
internalGenerate$1(node.term, decorate, forceBraces, compact) +
decorate(generateMultiplier$1(node), node)
);
case 'Type':
result = '<' + node.name + (node.opts ? decorate(generateTypeOpts$1(node.opts), node.opts) : '') + '>';
break;
case 'Property':
result = '<\'' + node.name + '\'>';
break;
case 'Keyword':
result = node.name;
break;
case 'AtKeyword':
result = '@' + node.name;
break;
case 'Function':
result = node.name + '(';
break;
case 'String':
case 'Token':
result = node.value;
break;
case 'Comma':
result = ',';
break;
default:
throw new Error('Unknown node type `' + node.type + '`');
}
return decorate(result, node);
}
function generate$1t(node, options) {
let decorate = noop$4;
let forceBraces = false;
let compact = false;
if (typeof options === 'function') {
decorate = options;
} else if (options) {
forceBraces = Boolean(options.forceBraces);
compact = Boolean(options.compact);
if (typeof options.decorate === 'function') {
decorate = options.decorate;
}
}
return internalGenerate$1(node, decorate, forceBraces, compact);
}
generate$1u.generate = generate$1t;
const createCustomError$6 = createCustomError$9;
const generate$1s = generate$1u;
const defaultLoc$1 = { offset: 0, line: 1, column: 1 };
function locateMismatch$1(matchResult, node) {
const tokens = matchResult.tokens;
const longestMatch = matchResult.longestMatch;
const mismatchNode = longestMatch < tokens.length ? tokens[longestMatch].node || null : null;
const badNode = mismatchNode !== node ? mismatchNode : null;
let mismatchOffset = 0;
let mismatchLength = 0;
let entries = 0;
let css = '';
let start;
let end;
for (let i = 0; i < tokens.length; i++) {
const token = tokens[i].value;
if (i === longestMatch) {
mismatchLength = token.length;
mismatchOffset = css.length;
}
if (badNode !== null && tokens[i].node === badNode) {
if (i <= longestMatch) {
entries++;
} else {
entries = 0;
}
}
css += token;
}
if (longestMatch === tokens.length || entries > 1) { // last
start = fromLoc$1(badNode || node, 'end') || buildLoc$1(defaultLoc$1, css);
end = buildLoc$1(start);
} else {
start = fromLoc$1(badNode, 'start') ||
buildLoc$1(fromLoc$1(node, 'start') || defaultLoc$1, css.slice(0, mismatchOffset));
end = fromLoc$1(badNode, 'end') ||
buildLoc$1(start, css.substr(mismatchOffset, mismatchLength));
}
return {
css,
mismatchOffset,
mismatchLength,
start,
end
};
}
function fromLoc$1(node, point) {
const value = node && node.loc && node.loc[point];
if (value) {
return 'line' in value ? buildLoc$1(value) : value;
}
return null;
}
function buildLoc$1({ offset, line, column }, extra) {
const loc = {
offset,
line,
column
};
if (extra) {
const lines = extra.split(/\n|\r\n?|\f/);
loc.offset += extra.length;
loc.line += lines.length - 1;
loc.column = lines.length === 1 ? loc.column + extra.length : lines.pop().length + 1;
}
return loc;
}
const SyntaxReferenceError$1 = function(type, referenceName) {
const error = createCustomError$6.createCustomError(
'SyntaxReferenceError',
type + (referenceName ? ' `' + referenceName + '`' : '')
);
error.reference = referenceName;
return error;
};
const SyntaxMatchError$1 = function(message, syntax, node, matchResult) {
const error = createCustomError$6.createCustomError('SyntaxMatchError', message);
const {
css,
mismatchOffset,
mismatchLength,
start,
end
} = locateMismatch$1(matchResult, node);
error.rawMessage = message;
error.syntax = syntax ? generate$1s.generate(syntax) : '<generic>';
error.css = css;
error.mismatchOffset = mismatchOffset;
error.mismatchLength = mismatchLength;
error.message = message + '\n' +
' syntax: ' + error.syntax + '\n' +
' value: ' + (css || '<empty string>') + '\n' +
' --------' + new Array(error.mismatchOffset + 1).join('-') + '^';
Object.assign(error, start);
error.loc = {
source: (node && node.loc && node.loc.source) || '<unknown>',
start,
end
};
return error;
};
error$4.SyntaxMatchError = SyntaxMatchError$1;
error$4.SyntaxReferenceError = SyntaxReferenceError$1;
var names$c = {};
const keywords$4 = new Map();
const properties$3 = new Map();
const HYPHENMINUS$c = 45; // '-'.charCodeAt()
const keyword$1 = getKeywordDescriptor$1;
const property$1 = getPropertyDescriptor$1;
const vendorPrefix$1 = getVendorPrefix$1;
function isCustomProperty$1(str, offset) {
offset = offset || 0;
return str.length - offset >= 2 &&
str.charCodeAt(offset) === HYPHENMINUS$c &&
str.charCodeAt(offset + 1) === HYPHENMINUS$c;
}
function getVendorPrefix$1(str, offset) {
offset = offset || 0;
// verdor prefix should be at least 3 chars length
if (str.length - offset >= 3) {
// vendor prefix starts with hyper minus following non-hyper minus
if (str.charCodeAt(offset) === HYPHENMINUS$c &&
str.charCodeAt(offset + 1) !== HYPHENMINUS$c) {
// vendor prefix should contain a hyper minus at the ending
const secondDashIndex = str.indexOf('-', offset + 2);
if (secondDashIndex !== -1) {
return str.substring(offset, secondDashIndex + 1);
}
}
}
return '';
}
function getKeywordDescriptor$1(keyword) {
if (keywords$4.has(keyword)) {
return keywords$4.get(keyword);
}
const name = keyword.toLowerCase();
let descriptor = keywords$4.get(name);
if (descriptor === undefined) {
const custom = isCustomProperty$1(name, 0);
const vendor = !custom ? getVendorPrefix$1(name, 0) : '';
descriptor = Object.freeze({
basename: name.substr(vendor.length),
name,
prefix: vendor,
vendor,
custom
});
}
keywords$4.set(keyword, descriptor);
return descriptor;
}
function getPropertyDescriptor$1(property) {
if (properties$3.has(property)) {
return properties$3.get(property);
}
let name = property;
let hack = property[0];
if (hack === '/') {
hack = property[1] === '/' ? '//' : '/';
} else if (hack !== '_' &&
hack !== '*' &&
hack !== '$' &&
hack !== '#' &&
hack !== '+' &&
hack !== '&') {
hack = '';
}
const custom = isCustomProperty$1(name, hack.length);
// re-use result when possible (the same as for lower case)
if (!custom) {
name = name.toLowerCase();
if (properties$3.has(name)) {
const descriptor = properties$3.get(name);
properties$3.set(property, descriptor);
return descriptor;
}
}
const vendor = !custom ? getVendorPrefix$1(name, hack.length) : '';
const prefix = name.substr(0, hack.length + vendor.length);
const descriptor = Object.freeze({
basename: name.substr(prefix.length),
name: name.substr(hack.length),
hack,
vendor,
prefix,
custom
});
properties$3.set(property, descriptor);
return descriptor;
}
names$c.isCustomProperty = isCustomProperty$1;
names$c.keyword = keyword$1;
names$c.property = property$1;
names$c.vendorPrefix = vendorPrefix$1;
var genericConst$5 = {};
// https://drafts.csswg.org/css-cascade-5/
const cssWideKeywords$1 = [
'initial',
'inherit',
'unset',
'revert',
'revert-layer'
];
genericConst$5.cssWideKeywords = cssWideKeywords$1;
var generic$3 = {};
const charCodeDefinitions$l = charCodeDefinitions$p;
const types$1D = types$1K;
const utils$q = utils$u;
const PLUSSIGN$i = 0x002B; // U+002B PLUS SIGN (+)
const HYPHENMINUS$b = 0x002D; // U+002D HYPHEN-MINUS (-)
const N$8 = 0x006E; // U+006E LATIN SMALL LETTER N (n)
const DISALLOW_SIGN$3 = true;
const ALLOW_SIGN$3 = false;
function isDelim$3(token, code) {
return token !== null && token.type === types$1D.Delim && token.value.charCodeAt(0) === code;
}
function skipSC$1(token, offset, getNextToken) {
while (token !== null && (token.type === types$1D.WhiteSpace || token.type === types$1D.Comment)) {
token = getNextToken(++offset);
}
return offset;
}
function checkInteger$3(token, valueOffset, disallowSign, offset) {
if (!token) {
return 0;
}
const code = token.value.charCodeAt(valueOffset);
if (code === PLUSSIGN$i || code === HYPHENMINUS$b) {
if (disallowSign) {
// Number sign is not allowed
return 0;
}
valueOffset++;
}
for (; valueOffset < token.value.length; valueOffset++) {
if (!charCodeDefinitions$l.isDigit(token.value.charCodeAt(valueOffset))) {
// Integer is expected
return 0;
}
}
return offset + 1;
}
// ... <signed-integer>
// ... ['+' | '-'] <signless-integer>
function consumeB$3(token, offset_, getNextToken) {
let sign = false;
let offset = skipSC$1(token, offset_, getNextToken);
token = getNextToken(offset);
if (token === null) {
return offset_;
}
if (token.type !== types$1D.Number) {
if (isDelim$3(token, PLUSSIGN$i) || isDelim$3(token, HYPHENMINUS$b)) {
sign = true;
offset = skipSC$1(getNextToken(++offset), offset, getNextToken);
token = getNextToken(offset);
if (token === null || token.type !== types$1D.Number) {
return 0;
}
} else {
return offset_;
}
}
if (!sign) {
const code = token.value.charCodeAt(0);
if (code !== PLUSSIGN$i && code !== HYPHENMINUS$b) {
// Number sign is expected
return 0;
}
}
return checkInteger$3(token, sign ? 0 : 1, sign, offset);
}
// An+B microsyntax https://www.w3.org/TR/css-syntax-3/#anb
function anPlusB$1(token, getNextToken) {
/* eslint-disable brace-style*/
let offset = 0;
if (!token) {
return 0;
}
// <integer>
if (token.type === types$1D.Number) {
return checkInteger$3(token, 0, ALLOW_SIGN$3, offset); // b
}
// -n
// -n <signed-integer>
// -n ['+' | '-'] <signless-integer>
// -n- <signless-integer>
// <dashndashdigit-ident>
else if (token.type === types$1D.Ident && token.value.charCodeAt(0) === HYPHENMINUS$b) {
// expect 1st char is N
if (!utils$q.cmpChar(token.value, 1, N$8)) {
return 0;
}
switch (token.value.length) {
// -n
// -n <signed-integer>
// -n ['+' | '-'] <signless-integer>
case 2:
return consumeB$3(getNextToken(++offset), offset, getNextToken);
// -n- <signless-integer>
case 3:
if (token.value.charCodeAt(2) !== HYPHENMINUS$b) {
return 0;
}
offset = skipSC$1(getNextToken(++offset), offset, getNextToken);
token = getNextToken(offset);
return checkInteger$3(token, 0, DISALLOW_SIGN$3, offset);
// <dashndashdigit-ident>
default:
if (token.value.charCodeAt(2) !== HYPHENMINUS$b) {
return 0;
}
return checkInteger$3(token, 3, DISALLOW_SIGN$3, offset);
}
}
// '+'? n
// '+'? n <signed-integer>
// '+'? n ['+' | '-'] <signless-integer>
// '+'? n- <signless-integer>
// '+'? <ndashdigit-ident>
else if (token.type === types$1D.Ident || (isDelim$3(token, PLUSSIGN$i) && getNextToken(offset + 1).type === types$1D.Ident)) {
// just ignore a plus
if (token.type !== types$1D.Ident) {
token = getNextToken(++offset);
}
if (token === null || !utils$q.cmpChar(token.value, 0, N$8)) {
return 0;
}
switch (token.value.length) {
// '+'? n
// '+'? n <signed-integer>
// '+'? n ['+' | '-'] <signless-integer>
case 1:
return consumeB$3(getNextToken(++offset), offset, getNextToken);
// '+'? n- <signless-integer>
case 2:
if (token.value.charCodeAt(1) !== HYPHENMINUS$b) {
return 0;
}
offset = skipSC$1(getNextToken(++offset), offset, getNextToken);
token = getNextToken(offset);
return checkInteger$3(token, 0, DISALLOW_SIGN$3, offset);
// '+'? <ndashdigit-ident>
default:
if (token.value.charCodeAt(1) !== HYPHENMINUS$b) {
return 0;
}
return checkInteger$3(token, 2, DISALLOW_SIGN$3, offset);
}
}
// <ndashdigit-dimension>
// <ndash-dimension> <signless-integer>
// <n-dimension>
// <n-dimension> <signed-integer>
// <n-dimension> ['+' | '-'] <signless-integer>
else if (token.type === types$1D.Dimension) {
let code = token.value.charCodeAt(0);
let sign = code === PLUSSIGN$i || code === HYPHENMINUS$b ? 1 : 0;
let i = sign;
for (; i < token.value.length; i++) {
if (!charCodeDefinitions$l.isDigit(token.value.charCodeAt(i))) {
break;
}
}
if (i === sign) {
// Integer is expected
return 0;
}
if (!utils$q.cmpChar(token.value, i, N$8)) {
return 0;
}
// <n-dimension>
// <n-dimension> <signed-integer>
// <n-dimension> ['+' | '-'] <signless-integer>
if (i + 1 === token.value.length) {
return consumeB$3(getNextToken(++offset), offset, getNextToken);
} else {
if (token.value.charCodeAt(i + 1) !== HYPHENMINUS$b) {
return 0;
}
// <ndash-dimension> <signless-integer>
if (i + 2 === token.value.length) {
offset = skipSC$1(getNextToken(++offset), offset, getNextToken);
token = getNextToken(offset);
return checkInteger$3(token, 0, DISALLOW_SIGN$3, offset);
}
// <ndashdigit-dimension>
else {
return checkInteger$3(token, i + 2, DISALLOW_SIGN$3, offset);
}
}
}
return 0;
}
var genericAnPlusB$3 = anPlusB$1;
const charCodeDefinitions$k = charCodeDefinitions$p;
const types$1C = types$1K;
const utils$p = utils$u;
const PLUSSIGN$h = 0x002B; // U+002B PLUS SIGN (+)
const HYPHENMINUS$a = 0x002D; // U+002D HYPHEN-MINUS (-)
const QUESTIONMARK$5 = 0x003F; // U+003F QUESTION MARK (?)
const U$3 = 0x0075; // U+0075 LATIN SMALL LETTER U (u)
function isDelim$2(token, code) {
return token !== null && token.type === types$1C.Delim && token.value.charCodeAt(0) === code;
}
function startsWith$3(token, code) {
return token.value.charCodeAt(0) === code;
}
function hexSequence$1(token, offset, allowDash) {
let hexlen = 0;
for (let pos = offset; pos < token.value.length; pos++) {
const code = token.value.charCodeAt(pos);
if (code === HYPHENMINUS$a && allowDash && hexlen !== 0) {
hexSequence$1(token, offset + hexlen + 1, false);
return 6; // dissallow following question marks
}
if (!charCodeDefinitions$k.isHexDigit(code)) {
return 0; // not a hex digit
}
if (++hexlen > 6) {
return 0; // too many hex digits
} }
return hexlen;
}
function withQuestionMarkSequence$1(consumed, length, getNextToken) {
if (!consumed) {
return 0; // nothing consumed
}
while (isDelim$2(getNextToken(length), QUESTIONMARK$5)) {
if (++consumed > 6) {
return 0; // too many question marks
}
length++;
}
return length;
}
// https://drafts.csswg.org/css-syntax/#urange
// Informally, the <urange> production has three forms:
// U+0001
// Defines a range consisting of a single code point, in this case the code point "1".
// U+0001-00ff
// Defines a range of codepoints between the first and the second value, in this case
// the range between "1" and "ff" (255 in decimal) inclusive.
// U+00??
// Defines a range of codepoints where the "?" characters range over all hex digits,
// in this case defining the same as the value U+0000-00ff.
// In each form, a maximum of 6 digits is allowed for each hexadecimal number (if you treat "?" as a hexadecimal digit).
//
// <urange> =
// u '+' <ident-token> '?'* |
// u <dimension-token> '?'* |
// u <number-token> '?'* |
// u <number-token> <dimension-token> |
// u <number-token> <number-token> |
// u '+' '?'+
function urange$1(token, getNextToken) {
let length = 0;
// should start with `u` or `U`
if (token === null || token.type !== types$1C.Ident || !utils$p.cmpChar(token.value, 0, U$3)) {
return 0;
}
token = getNextToken(++length);
if (token === null) {
return 0;
}
// u '+' <ident-token> '?'*
// u '+' '?'+
if (isDelim$2(token, PLUSSIGN$h)) {
token = getNextToken(++length);
if (token === null) {
return 0;
}
if (token.type === types$1C.Ident) {
// u '+' <ident-token> '?'*
return withQuestionMarkSequence$1(hexSequence$1(token, 0, true), ++length, getNextToken);
}
if (isDelim$2(token, QUESTIONMARK$5)) {
// u '+' '?'+
return withQuestionMarkSequence$1(1, ++length, getNextToken);
}
// Hex digit or question mark is expected
return 0;
}
// u <number-token> '?'*
// u <number-token> <dimension-token>
// u <number-token> <number-token>
if (token.type === types$1C.Number) {
const consumedHexLength = hexSequence$1(token, 1, true);
if (consumedHexLength === 0) {
return 0;
}
token = getNextToken(++length);
if (token === null) {
// u <number-token> <eof>
return length;
}
if (token.type === types$1C.Dimension || token.type === types$1C.Number) {
// u <number-token> <dimension-token>
// u <number-token> <number-token>
if (!startsWith$3(token, HYPHENMINUS$a) || !hexSequence$1(token, 1, false)) {
return 0;
}
return length + 1;
}
// u <number-token> '?'*
return withQuestionMarkSequence$1(consumedHexLength, length, getNextToken);
}
// u <dimension-token> '?'*
if (token.type === types$1C.Dimension) {
return withQuestionMarkSequence$1(hexSequence$1(token, 1, true), ++length, getNextToken);
}
return 0;
}
var genericUrange$3 = urange$1;
const genericConst$4 = genericConst$5;
const genericAnPlusB$2 = genericAnPlusB$3;
const genericUrange$2 = genericUrange$3;
const types$1B = types$1K;
const charCodeDefinitions$j = charCodeDefinitions$p;
const utils$o = utils$u;
const calcFunctionNames$1 = ['calc(', '-moz-calc(', '-webkit-calc('];
const balancePair$2 = new Map([
[types$1B.Function, types$1B.RightParenthesis],
[types$1B.LeftParenthesis, types$1B.RightParenthesis],
[types$1B.LeftSquareBracket, types$1B.RightSquareBracket],
[types$1B.LeftCurlyBracket, types$1B.RightCurlyBracket]
]);
// safe char code getter
function charCodeAt$1(str, index) {
return index < str.length ? str.charCodeAt(index) : 0;
}
function eqStr$1(actual, expected) {
return utils$o.cmpStr(actual, 0, actual.length, expected);
}
function eqStrAny$1(actual, expected) {
for (let i = 0; i < expected.length; i++) {
if (eqStr$1(actual, expected[i])) {
return true;
}
}
return false;
}
// IE postfix hack, i.e. 123\0 or 123px\9
function isPostfixIeHack$1(str, offset) {
if (offset !== str.length - 2) {
return false;
}
return (
charCodeAt$1(str, offset) === 0x005C && // U+005C REVERSE SOLIDUS (\)
charCodeDefinitions$j.isDigit(charCodeAt$1(str, offset + 1))
);
}
function outOfRange$1(opts, value, numEnd) {
if (opts && opts.type === 'Range') {
const num = Number(
numEnd !== undefined && numEnd !== value.length
? value.substr(0, numEnd)
: value
);
if (isNaN(num)) {
return true;
}
// FIXME: when opts.min is a string it's a dimension, skip a range validation
// for now since it requires a type covertation which is not implmented yet
if (opts.min !== null && num < opts.min && typeof opts.min !== 'string') {
return true;
}
// FIXME: when opts.max is a string it's a dimension, skip a range validation
// for now since it requires a type covertation which is not implmented yet
if (opts.max !== null && num > opts.max && typeof opts.max !== 'string') {
return true;
}
}
return false;
}
function consumeFunction$1(token, getNextToken) {
let balanceCloseType = 0;
let balanceStash = [];
let length = 0;
// balanced token consuming
scan:
do {
switch (token.type) {
case types$1B.RightCurlyBracket:
case types$1B.RightParenthesis:
case types$1B.RightSquareBracket:
if (token.type !== balanceCloseType) {
break scan;
}
balanceCloseType = balanceStash.pop();
if (balanceStash.length === 0) {
length++;
break scan;
}
break;
case types$1B.Function:
case types$1B.LeftParenthesis:
case types$1B.LeftSquareBracket:
case types$1B.LeftCurlyBracket:
balanceStash.push(balanceCloseType);
balanceCloseType = balancePair$2.get(token.type);
break;
}
length++;
} while (token = getNextToken(length));
return length;
}
// TODO: implement
// can be used wherever <length>, <frequency>, <angle>, <time>, <percentage>, <number>, or <integer> values are allowed
// https://drafts.csswg.org/css-values/#calc-notation
function calc$1(next) {
return function(token, getNextToken, opts) {
if (token === null) {
return 0;
}
if (token.type === types$1B.Function && eqStrAny$1(token.value, calcFunctionNames$1)) {
return consumeFunction$1(token, getNextToken);
}
return next(token, getNextToken, opts);
};
}
function tokenType$1(expectedTokenType) {
return function(token) {
if (token === null || token.type !== expectedTokenType) {
return 0;
}
return 1;
};
}
// =========================
// Complex types
//
// https://drafts.csswg.org/css-values-4/#custom-idents
// 4.2. Author-defined Identifiers: the <custom-ident> type
// Some properties accept arbitrary author-defined identifiers as a component value.
// This generic data type is denoted by <custom-ident>, and represents any valid CSS identifier
// that would not be misinterpreted as a pre-defined keyword in that propertys value definition.
//
// See also: https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident
function customIdent$1(token) {
if (token === null || token.type !== types$1B.Ident) {
return 0;
}
const name = token.value.toLowerCase();
// The CSS-wide keywords are not valid <custom-ident>s
if (eqStrAny$1(name, genericConst$4.cssWideKeywords)) {
return 0;
}
// The default keyword is reserved and is also not a valid <custom-ident>
if (eqStr$1(name, 'default')) {
return 0;
}
// TODO: ignore property specific keywords (as described https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident)
// Specifications using <custom-ident> must specify clearly what other keywords
// are excluded from <custom-ident>, if any—for example by saying that any pre-defined keywords
// in that propertys value definition are excluded. Excluded keywords are excluded
// in all ASCII case permutations.
return 1;
}
// https://drafts.csswg.org/css-variables/#typedef-custom-property-name
// A custom property is any property whose name starts with two dashes (U+002D HYPHEN-MINUS), like --foo.
// The <custom-property-name> production corresponds to this: its defined as any valid identifier
// that starts with two dashes, except -- itself, which is reserved for future use by CSS.
// NOTE: Current implementation treat `--` as a valid name since most (all?) major browsers treat it as valid.
function customPropertyName$1(token) {
// ... defined as any valid identifier
if (token === null || token.type !== types$1B.Ident) {
return 0;
}
// ... that starts with two dashes (U+002D HYPHEN-MINUS)
if (charCodeAt$1(token.value, 0) !== 0x002D || charCodeAt$1(token.value, 1) !== 0x002D) {
return 0;
}
return 1;
}
// https://drafts.csswg.org/css-color-4/#hex-notation
// The syntax of a <hex-color> is a <hash-token> token whose value consists of 3, 4, 6, or 8 hexadecimal digits.
// In other words, a hex color is written as a hash character, "#", followed by some number of digits 0-9 or
// letters a-f (the case of the letters doesnt matter - #00ff00 is identical to #00FF00).
function hexColor$1(token) {
if (token === null || token.type !== types$1B.Hash) {
return 0;
}
const length = token.value.length;
// valid values (length): #rgb (4), #rgba (5), #rrggbb (7), #rrggbbaa (9)
if (length !== 4 && length !== 5 && length !== 7 && length !== 9) {
return 0;
}
for (let i = 1; i < length; i++) {
if (!charCodeDefinitions$j.isHexDigit(charCodeAt$1(token.value, i))) {
return 0;
}
}
return 1;
}
function idSelector$1(token) {
if (token === null || token.type !== types$1B.Hash) {
return 0;
}
if (!charCodeDefinitions$j.isIdentifierStart(charCodeAt$1(token.value, 1), charCodeAt$1(token.value, 2), charCodeAt$1(token.value, 3))) {
return 0;
}
return 1;
}
// https://drafts.csswg.org/css-syntax/#any-value
// It represents the entirety of what a valid declaration can have as its value.
function declarationValue$1(token, getNextToken) {
if (!token) {
return 0;
}
let balanceCloseType = 0;
let balanceStash = [];
let length = 0;
// The <declaration-value> production matches any sequence of one or more tokens,
// so long as the sequence does not contain ...
scan:
do {
switch (token.type) {
// ... <bad-string-token>, <bad-url-token>,
case types$1B.BadString:
case types$1B.BadUrl:
break scan;
// ... unmatched <)-token>, <]-token>, or <}-token>,
case types$1B.RightCurlyBracket:
case types$1B.RightParenthesis:
case types$1B.RightSquareBracket:
if (token.type !== balanceCloseType) {
break scan;
}
balanceCloseType = balanceStash.pop();
break;
// ... or top-level <semicolon-token> tokens
case types$1B.Semicolon:
if (balanceCloseType === 0) {
break scan;
}
break;
// ... or <delim-token> tokens with a value of "!"
case types$1B.Delim:
if (balanceCloseType === 0 && token.value === '!') {
break scan;
}
break;
case types$1B.Function:
case types$1B.LeftParenthesis:
case types$1B.LeftSquareBracket:
case types$1B.LeftCurlyBracket:
balanceStash.push(balanceCloseType);
balanceCloseType = balancePair$2.get(token.type);
break;
}
length++;
} while (token = getNextToken(length));
return length;
}
// https://drafts.csswg.org/css-syntax/#any-value
// The <any-value> production is identical to <declaration-value>, but also
// allows top-level <semicolon-token> tokens and <delim-token> tokens
// with a value of "!". It represents the entirety of what valid CSS can be in any context.
function anyValue$1(token, getNextToken) {
if (!token) {
return 0;
}
let balanceCloseType = 0;
let balanceStash = [];
let length = 0;
// The <any-value> production matches any sequence of one or more tokens,
// so long as the sequence ...
scan:
do {
switch (token.type) {
// ... does not contain <bad-string-token>, <bad-url-token>,
case types$1B.BadString:
case types$1B.BadUrl:
break scan;
// ... unmatched <)-token>, <]-token>, or <}-token>,
case types$1B.RightCurlyBracket:
case types$1B.RightParenthesis:
case types$1B.RightSquareBracket:
if (token.type !== balanceCloseType) {
break scan;
}
balanceCloseType = balanceStash.pop();
break;
case types$1B.Function:
case types$1B.LeftParenthesis:
case types$1B.LeftSquareBracket:
case types$1B.LeftCurlyBracket:
balanceStash.push(balanceCloseType);
balanceCloseType = balancePair$2.get(token.type);
break;
}
length++;
} while (token = getNextToken(length));
return length;
}
// =========================
// Dimensions
//
function dimension$1(type) {
if (type) {
type = new Set(type);
}
return function(token, getNextToken, opts) {
if (token === null || token.type !== types$1B.Dimension) {
return 0;
}
const numberEnd = utils$o.consumeNumber(token.value, 0);
// check unit
if (type !== null) {
// check for IE postfix hack, i.e. 123px\0 or 123px\9
const reverseSolidusOffset = token.value.indexOf('\\', numberEnd);
const unit = reverseSolidusOffset === -1 || !isPostfixIeHack$1(token.value, reverseSolidusOffset)
? token.value.substr(numberEnd)
: token.value.substring(numberEnd, reverseSolidusOffset);
if (type.has(unit.toLowerCase()) === false) {
return 0;
}
}
// check range if specified
if (outOfRange$1(opts, token.value, numberEnd)) {
return 0;
}
return 1;
};
}
// =========================
// Percentage
//
// §5.5. Percentages: the <percentage> type
// https://drafts.csswg.org/css-values-4/#percentages
function percentage$1(token, getNextToken, opts) {
// ... corresponds to the <percentage-token> production
if (token === null || token.type !== types$1B.Percentage) {
return 0;
}
// check range if specified
if (outOfRange$1(opts, token.value, token.value.length - 1)) {
return 0;
}
return 1;
}
// =========================
// Numeric
//
// https://drafts.csswg.org/css-values-4/#numbers
// The value <zero> represents a literal number with the value 0. Expressions that merely
// evaluate to a <number> with the value 0 (for example, calc(0)) do not match <zero>;
// only literal <number-token>s do.
function zero$1(next) {
if (typeof next !== 'function') {
next = function() {
return 0;
};
}
return function(token, getNextToken, opts) {
if (token !== null && token.type === types$1B.Number) {
if (Number(token.value) === 0) {
return 1;
}
}
return next(token, getNextToken, opts);
};
}
// § 5.3. Real Numbers: the <number> type
// https://drafts.csswg.org/css-values-4/#numbers
// Number values are denoted by <number>, and represent real numbers, possibly with a fractional component.
// ... It corresponds to the <number-token> production
function number$1(token, getNextToken, opts) {
if (token === null) {
return 0;
}
const numberEnd = utils$o.consumeNumber(token.value, 0);
const isNumber = numberEnd === token.value.length;
if (!isNumber && !isPostfixIeHack$1(token.value, numberEnd)) {
return 0;
}
// check range if specified
if (outOfRange$1(opts, token.value, numberEnd)) {
return 0;
}
return 1;
}
// §5.2. Integers: the <integer> type
// https://drafts.csswg.org/css-values-4/#integers
function integer$1(token, getNextToken, opts) {
// ... corresponds to a subset of the <number-token> production
if (token === null || token.type !== types$1B.Number) {
return 0;
}
// The first digit of an integer may be immediately preceded by `-` or `+` to indicate the integers sign.
let i = charCodeAt$1(token.value, 0) === 0x002B || // U+002B PLUS SIGN (+)
charCodeAt$1(token.value, 0) === 0x002D ? 1 : 0; // U+002D HYPHEN-MINUS (-)
// When written literally, an integer is one or more decimal digits 0 through 9 ...
for (; i < token.value.length; i++) {
if (!charCodeDefinitions$j.isDigit(charCodeAt$1(token.value, i))) {
return 0;
}
}
// check range if specified
if (outOfRange$1(opts, token.value, i)) {
return 0;
}
return 1;
}
// token types
const tokenTypes = {
'ident-token': tokenType$1(types$1B.Ident),
'function-token': tokenType$1(types$1B.Function),
'at-keyword-token': tokenType$1(types$1B.AtKeyword),
'hash-token': tokenType$1(types$1B.Hash),
'string-token': tokenType$1(types$1B.String),
'bad-string-token': tokenType$1(types$1B.BadString),
'url-token': tokenType$1(types$1B.Url),
'bad-url-token': tokenType$1(types$1B.BadUrl),
'delim-token': tokenType$1(types$1B.Delim),
'number-token': tokenType$1(types$1B.Number),
'percentage-token': tokenType$1(types$1B.Percentage),
'dimension-token': tokenType$1(types$1B.Dimension),
'whitespace-token': tokenType$1(types$1B.WhiteSpace),
'CDO-token': tokenType$1(types$1B.CDO),
'CDC-token': tokenType$1(types$1B.CDC),
'colon-token': tokenType$1(types$1B.Colon),
'semicolon-token': tokenType$1(types$1B.Semicolon),
'comma-token': tokenType$1(types$1B.Comma),
'[-token': tokenType$1(types$1B.LeftSquareBracket),
']-token': tokenType$1(types$1B.RightSquareBracket),
'(-token': tokenType$1(types$1B.LeftParenthesis),
')-token': tokenType$1(types$1B.RightParenthesis),
'{-token': tokenType$1(types$1B.LeftCurlyBracket),
'}-token': tokenType$1(types$1B.RightCurlyBracket)
};
// token production types
const productionTypes = {
// token type aliases
'string': tokenType$1(types$1B.String),
'ident': tokenType$1(types$1B.Ident),
// percentage
'percentage': calc$1(percentage$1),
// numeric
'zero': zero$1(),
'number': calc$1(number$1),
'integer': calc$1(integer$1),
// complex types
'custom-ident': customIdent$1,
'custom-property-name': customPropertyName$1,
'hex-color': hexColor$1,
'id-selector': idSelector$1, // element( <id-selector> )
'an-plus-b': genericAnPlusB$2,
'urange': genericUrange$2,
'declaration-value': declarationValue$1,
'any-value': anyValue$1
};
// dimensions types depend on units set
function createDemensionTypes(units) {
const {
angle,
decibel,
frequency,
flex,
length,
resolution,
semitones,
time
} = units || {};
return {
'dimension': calc$1(dimension$1(null)),
'angle': calc$1(dimension$1(angle)),
'decibel': calc$1(dimension$1(decibel)),
'frequency': calc$1(dimension$1(frequency)),
'flex': calc$1(dimension$1(flex)),
'length': calc$1(zero$1(dimension$1(length))),
'resolution': calc$1(dimension$1(resolution)),
'semitones': calc$1(dimension$1(semitones)),
'time': calc$1(dimension$1(time))
};
}
function createGenericTypes(units) {
return {
...tokenTypes,
...productionTypes,
...createDemensionTypes(units)
};
}
generic$3.createDemensionTypes = createDemensionTypes;
generic$3.createGenericTypes = createGenericTypes;
generic$3.productionTypes = productionTypes;
generic$3.tokenTypes = tokenTypes;
var units$1 = {};
const length = [
// absolute length units https://www.w3.org/TR/css-values-3/#lengths
'cm', 'mm', 'q', 'in', 'pt', 'pc', 'px',
// font-relative length units https://drafts.csswg.org/css-values-4/#font-relative-lengths
'em', 'rem',
'ex', 'rex',
'cap', 'rcap',
'ch', 'rch',
'ic', 'ric',
'lh', 'rlh',
// viewport-percentage lengths https://drafts.csswg.org/css-values-4/#viewport-relative-lengths
'vw', 'svw', 'lvw', 'dvw',
'vh', 'svh', 'lvh', 'dvh',
'vi', 'svi', 'lvi', 'dvi',
'vb', 'svb', 'lvb', 'dvb',
'vmin', 'svmin', 'lvmin', 'dvmin',
'vmax', 'svmax', 'lvmax', 'dvmax',
// container relative lengths https://drafts.csswg.org/css-contain-3/#container-lengths
'cqw', 'cqh', 'cqi', 'cqb', 'cqmin', 'cqmax'
];
const angle = ['deg', 'grad', 'rad', 'turn']; // https://www.w3.org/TR/css-values-3/#angles
const time = ['s', 'ms']; // https://www.w3.org/TR/css-values-3/#time
const frequency = ['hz', 'khz']; // https://www.w3.org/TR/css-values-3/#frequency
const resolution = ['dpi', 'dpcm', 'dppx', 'x']; // https://www.w3.org/TR/css-values-3/#resolution
const flex$2 = ['fr']; // https://drafts.csswg.org/css-grid/#fr-unit
const decibel = ['db']; // https://www.w3.org/TR/css3-speech/#mixing-props-voice-volume
const semitones = ['st']; // https://www.w3.org/TR/css3-speech/#voice-props-voice-pitch
units$1.angle = angle;
units$1.decibel = decibel;
units$1.flex = flex$2;
units$1.frequency = frequency;
units$1.length = length;
units$1.resolution = resolution;
units$1.semitones = semitones;
units$1.time = time;
const index$h = tokenizer$5;
const astToTokens$1 = {
decorator(handlers) {
const tokens = [];
let curNode = null;
return {
...handlers,
node(node) {
const tmp = curNode;
curNode = node;
handlers.node.call(this, node);
curNode = tmp;
},
emit(value, type, auto) {
tokens.push({
type,
value,
node: auto ? null : curNode
});
},
result() {
return tokens;
}
};
}
};
function stringToTokens$1(str) {
const tokens = [];
index$h.tokenize(str, (type, start, end) =>
tokens.push({
type,
value: str.slice(start, end),
node: null
})
);
return tokens;
}
function prepareTokens$3(value, syntax) {
if (typeof value === 'string') {
return stringToTokens$1(value);
}
return syntax.generate(value, astToTokens$1);
}
var prepareTokens_1$1 = prepareTokens$3;
var matchGraph$5 = {};
var parse$1u = {};
var tokenizer$4 = {};
var _SyntaxError$2 = {};
const createCustomError$5 = createCustomError$9;
function SyntaxError$8(message, input, offset) {
return Object.assign(createCustomError$5.createCustomError('SyntaxError', message), {
input,
offset,
rawMessage: message,
message: message + '\n' +
' ' + input + '\n' +
'--' + new Array((offset || input.length) + 1).join('-') + '^'
});
}
_SyntaxError$2.SyntaxError = SyntaxError$8;
const SyntaxError$7 = _SyntaxError$2;
const TAB$3 = 9;
const N$7 = 10;
const F$4 = 12;
const R$4 = 13;
const SPACE$7 = 32;
let Tokenizer$1 = class Tokenizer {
constructor(str) {
this.str = str;
this.pos = 0;
}
charCodeAt(pos) {
return pos < this.str.length ? this.str.charCodeAt(pos) : 0;
}
charCode() {
return this.charCodeAt(this.pos);
}
nextCharCode() {
return this.charCodeAt(this.pos + 1);
}
nextNonWsCode(pos) {
return this.charCodeAt(this.findWsEnd(pos));
}
findWsEnd(pos) {
for (; pos < this.str.length; pos++) {
const code = this.str.charCodeAt(pos);
if (code !== R$4 && code !== N$7 && code !== F$4 && code !== SPACE$7 && code !== TAB$3) {
break;
}
}
return pos;
}
substringToPos(end) {
return this.str.substring(this.pos, this.pos = end);
}
eat(code) {
if (this.charCode() !== code) {
this.error('Expect `' + String.fromCharCode(code) + '`');
}
this.pos++;
}
peek() {
return this.pos < this.str.length ? this.str.charAt(this.pos++) : '';
}
error(message) {
throw new SyntaxError$7.SyntaxError(message, this.str, this.pos);
}
};
tokenizer$4.Tokenizer = Tokenizer$1;
const tokenizer$3 = tokenizer$4;
const TAB$2 = 9;
const N$6 = 10;
const F$3 = 12;
const R$3 = 13;
const SPACE$6 = 32;
const EXCLAMATIONMARK$6 = 33; // !
const NUMBERSIGN$8 = 35; // #
const AMPERSAND$7 = 38; // &
const APOSTROPHE$5 = 39; // '
const LEFTPARENTHESIS$5 = 40; // (
const RIGHTPARENTHESIS$5 = 41; // )
const ASTERISK$d = 42; // *
const PLUSSIGN$g = 43; // +
const COMMA$1 = 44; // ,
const HYPERMINUS$1 = 45; // -
const LESSTHANSIGN$1 = 60; // <
const GREATERTHANSIGN$5 = 62; // >
const QUESTIONMARK$4 = 63; // ?
const COMMERCIALAT$1 = 64; // @
const LEFTSQUAREBRACKET$1 = 91; // [
const RIGHTSQUAREBRACKET$1 = 93; // ]
const LEFTCURLYBRACKET$2 = 123; // {
const VERTICALLINE$7 = 124; // |
const RIGHTCURLYBRACKET$1 = 125; // }
const INFINITY$1 = 8734; // ∞
const NAME_CHAR$1 = new Uint8Array(128).map((_, idx) =>
/[a-zA-Z0-9\-]/.test(String.fromCharCode(idx)) ? 1 : 0
);
const COMBINATOR_PRECEDENCE$1 = {
' ': 1,
'&&': 2,
'||': 3,
'|': 4
};
function scanSpaces$1(tokenizer) {
return tokenizer.substringToPos(
tokenizer.findWsEnd(tokenizer.pos)
);
}
function scanWord$1(tokenizer) {
let end = tokenizer.pos;
for (; end < tokenizer.str.length; end++) {
const code = tokenizer.str.charCodeAt(end);
if (code >= 128 || NAME_CHAR$1[code] === 0) {
break;
}
}
if (tokenizer.pos === end) {
tokenizer.error('Expect a keyword');
}
return tokenizer.substringToPos(end);
}
function scanNumber$1(tokenizer) {
let end = tokenizer.pos;
for (; end < tokenizer.str.length; end++) {
const code = tokenizer.str.charCodeAt(end);
if (code < 48 || code > 57) {
break;
}
}
if (tokenizer.pos === end) {
tokenizer.error('Expect a number');
}
return tokenizer.substringToPos(end);
}
function scanString$1(tokenizer) {
const end = tokenizer.str.indexOf('\'', tokenizer.pos + 1);
if (end === -1) {
tokenizer.pos = tokenizer.str.length;
tokenizer.error('Expect an apostrophe');
}
return tokenizer.substringToPos(end + 1);
}
function readMultiplierRange$1(tokenizer) {
let min = null;
let max = null;
tokenizer.eat(LEFTCURLYBRACKET$2);
min = scanNumber$1(tokenizer);
if (tokenizer.charCode() === COMMA$1) {
tokenizer.pos++;
if (tokenizer.charCode() !== RIGHTCURLYBRACKET$1) {
max = scanNumber$1(tokenizer);
}
} else {
max = min;
}
tokenizer.eat(RIGHTCURLYBRACKET$1);
return {
min: Number(min),
max: max ? Number(max) : 0
};
}
function readMultiplier$1(tokenizer) {
let range = null;
let comma = false;
switch (tokenizer.charCode()) {
case ASTERISK$d:
tokenizer.pos++;
range = {
min: 0,
max: 0
};
break;
case PLUSSIGN$g:
tokenizer.pos++;
range = {
min: 1,
max: 0
};
break;
case QUESTIONMARK$4:
tokenizer.pos++;
range = {
min: 0,
max: 1
};
break;
case NUMBERSIGN$8:
tokenizer.pos++;
comma = true;
if (tokenizer.charCode() === LEFTCURLYBRACKET$2) {
range = readMultiplierRange$1(tokenizer);
} else if (tokenizer.charCode() === QUESTIONMARK$4) {
// https://www.w3.org/TR/css-values-4/#component-multipliers
// > the # and ? multipliers may be stacked as #?
// In this case just treat "#?" as a single multiplier
// { min: 0, max: 0, comma: true }
tokenizer.pos++;
range = {
min: 0,
max: 0
};
} else {
range = {
min: 1,
max: 0
};
}
break;
case LEFTCURLYBRACKET$2:
range = readMultiplierRange$1(tokenizer);
break;
default:
return null;
}
return {
type: 'Multiplier',
comma,
min: range.min,
max: range.max,
term: null
};
}
function maybeMultiplied$1(tokenizer, node) {
const multiplier = readMultiplier$1(tokenizer);
if (multiplier !== null) {
multiplier.term = node;
// https://www.w3.org/TR/css-values-4/#component-multipliers
// > The + and # multipliers may be stacked as +#;
// Represent "+#" as nested multipliers:
// { ...<multiplier #>,
// term: {
// ...<multipler +>,
// term: node
// }
// }
if (tokenizer.charCode() === NUMBERSIGN$8 &&
tokenizer.charCodeAt(tokenizer.pos - 1) === PLUSSIGN$g) {
return maybeMultiplied$1(tokenizer, multiplier);
}
return multiplier;
}
return node;
}
function maybeToken$1(tokenizer) {
const ch = tokenizer.peek();
if (ch === '') {
return null;
}
return {
type: 'Token',
value: ch
};
}
function readProperty$3(tokenizer) {
let name;
tokenizer.eat(LESSTHANSIGN$1);
tokenizer.eat(APOSTROPHE$5);
name = scanWord$1(tokenizer);
tokenizer.eat(APOSTROPHE$5);
tokenizer.eat(GREATERTHANSIGN$5);
return maybeMultiplied$1(tokenizer, {
type: 'Property',
name
});
}
// https://drafts.csswg.org/css-values-3/#numeric-ranges
// 4.1. Range Restrictions and Range Definition Notation
//
// Range restrictions can be annotated in the numeric type notation using CSS bracketed
// range notation—[min,max]—within the angle brackets, after the identifying keyword,
// indicating a closed range between (and including) min and max.
// For example, <integer [0, 10]> indicates an integer between 0 and 10, inclusive.
function readTypeRange$1(tokenizer) {
// use null for Infinity to make AST format JSON serializable/deserializable
let min = null; // -Infinity
let max = null; // Infinity
let sign = 1;
tokenizer.eat(LEFTSQUAREBRACKET$1);
if (tokenizer.charCode() === HYPERMINUS$1) {
tokenizer.peek();
sign = -1;
}
if (sign == -1 && tokenizer.charCode() === INFINITY$1) {
tokenizer.peek();
} else {
min = sign * Number(scanNumber$1(tokenizer));
if (NAME_CHAR$1[tokenizer.charCode()] !== 0) {
min += scanWord$1(tokenizer);
}
}
scanSpaces$1(tokenizer);
tokenizer.eat(COMMA$1);
scanSpaces$1(tokenizer);
if (tokenizer.charCode() === INFINITY$1) {
tokenizer.peek();
} else {
sign = 1;
if (tokenizer.charCode() === HYPERMINUS$1) {
tokenizer.peek();
sign = -1;
}
max = sign * Number(scanNumber$1(tokenizer));
if (NAME_CHAR$1[tokenizer.charCode()] !== 0) {
max += scanWord$1(tokenizer);
}
}
tokenizer.eat(RIGHTSQUAREBRACKET$1);
return {
type: 'Range',
min,
max
};
}
function readType$1(tokenizer) {
let name;
let opts = null;
tokenizer.eat(LESSTHANSIGN$1);
name = scanWord$1(tokenizer);
if (tokenizer.charCode() === LEFTPARENTHESIS$5 &&
tokenizer.nextCharCode() === RIGHTPARENTHESIS$5) {
tokenizer.pos += 2;
name += '()';
}
if (tokenizer.charCodeAt(tokenizer.findWsEnd(tokenizer.pos)) === LEFTSQUAREBRACKET$1) {
scanSpaces$1(tokenizer);
opts = readTypeRange$1(tokenizer);
}
tokenizer.eat(GREATERTHANSIGN$5);
return maybeMultiplied$1(tokenizer, {
type: 'Type',
name,
opts
});
}
function readKeywordOrFunction$1(tokenizer) {
const name = scanWord$1(tokenizer);
if (tokenizer.charCode() === LEFTPARENTHESIS$5) {
tokenizer.pos++;
return {
type: 'Function',
name
};
}
return maybeMultiplied$1(tokenizer, {
type: 'Keyword',
name
});
}
function regroupTerms$1(terms, combinators) {
function createGroup(terms, combinator) {
return {
type: 'Group',
terms,
combinator,
disallowEmpty: false,
explicit: false
};
}
let combinator;
combinators = Object.keys(combinators)
.sort((a, b) => COMBINATOR_PRECEDENCE$1[a] - COMBINATOR_PRECEDENCE$1[b]);
while (combinators.length > 0) {
combinator = combinators.shift();
let i = 0;
let subgroupStart = 0;
for (; i < terms.length; i++) {
const term = terms[i];
if (term.type === 'Combinator') {
if (term.value === combinator) {
if (subgroupStart === -1) {
subgroupStart = i - 1;
}
terms.splice(i, 1);
i--;
} else {
if (subgroupStart !== -1 && i - subgroupStart > 1) {
terms.splice(
subgroupStart,
i - subgroupStart,
createGroup(terms.slice(subgroupStart, i), combinator)
);
i = subgroupStart + 1;
}
subgroupStart = -1;
}
}
}
if (subgroupStart !== -1 && combinators.length) {
terms.splice(
subgroupStart,
i - subgroupStart,
createGroup(terms.slice(subgroupStart, i), combinator)
);
}
}
return combinator;
}
function readImplicitGroup$1(tokenizer) {
const terms = [];
const combinators = {};
let token;
let prevToken = null;
let prevTokenPos = tokenizer.pos;
while (token = peek$1(tokenizer)) {
if (token.type !== 'Spaces') {
if (token.type === 'Combinator') {
// check for combinator in group beginning and double combinator sequence
if (prevToken === null || prevToken.type === 'Combinator') {
tokenizer.pos = prevTokenPos;
tokenizer.error('Unexpected combinator');
}
combinators[token.value] = true;
} else if (prevToken !== null && prevToken.type !== 'Combinator') {
combinators[' '] = true; // a b
terms.push({
type: 'Combinator',
value: ' '
});
}
terms.push(token);
prevToken = token;
prevTokenPos = tokenizer.pos;
}
}
// check for combinator in group ending
if (prevToken !== null && prevToken.type === 'Combinator') {
tokenizer.pos -= prevTokenPos;
tokenizer.error('Unexpected combinator');
}
return {
type: 'Group',
terms,
combinator: regroupTerms$1(terms, combinators) || ' ',
disallowEmpty: false,
explicit: false
};
}
function readGroup$1(tokenizer) {
let result;
tokenizer.eat(LEFTSQUAREBRACKET$1);
result = readImplicitGroup$1(tokenizer);
tokenizer.eat(RIGHTSQUAREBRACKET$1);
result.explicit = true;
if (tokenizer.charCode() === EXCLAMATIONMARK$6) {
tokenizer.pos++;
result.disallowEmpty = true;
}
return result;
}
function peek$1(tokenizer) {
let code = tokenizer.charCode();
if (code < 128 && NAME_CHAR$1[code] === 1) {
return readKeywordOrFunction$1(tokenizer);
}
switch (code) {
case RIGHTSQUAREBRACKET$1:
// don't eat, stop scan a group
break;
case LEFTSQUAREBRACKET$1:
return maybeMultiplied$1(tokenizer, readGroup$1(tokenizer));
case LESSTHANSIGN$1:
return tokenizer.nextCharCode() === APOSTROPHE$5
? readProperty$3(tokenizer)
: readType$1(tokenizer);
case VERTICALLINE$7:
return {
type: 'Combinator',
value: tokenizer.substringToPos(
tokenizer.pos + (tokenizer.nextCharCode() === VERTICALLINE$7 ? 2 : 1)
)
};
case AMPERSAND$7:
tokenizer.pos++;
tokenizer.eat(AMPERSAND$7);
return {
type: 'Combinator',
value: '&&'
};
case COMMA$1:
tokenizer.pos++;
return {
type: 'Comma'
};
case APOSTROPHE$5:
return maybeMultiplied$1(tokenizer, {
type: 'String',
value: scanString$1(tokenizer)
});
case SPACE$6:
case TAB$2:
case N$6:
case R$3:
case F$3:
return {
type: 'Spaces',
value: scanSpaces$1(tokenizer)
};
case COMMERCIALAT$1:
code = tokenizer.nextCharCode();
if (code < 128 && NAME_CHAR$1[code] === 1) {
tokenizer.pos++;
return {
type: 'AtKeyword',
name: scanWord$1(tokenizer)
};
}
return maybeToken$1(tokenizer);
case ASTERISK$d:
case PLUSSIGN$g:
case QUESTIONMARK$4:
case NUMBERSIGN$8:
case EXCLAMATIONMARK$6:
// prohibited tokens (used as a multiplier start)
break;
case LEFTCURLYBRACKET$2:
// LEFTCURLYBRACKET is allowed since mdn/data uses it w/o quoting
// check next char isn't a number, because it's likely a disjoined multiplier
code = tokenizer.nextCharCode();
if (code < 48 || code > 57) {
return maybeToken$1(tokenizer);
}
break;
default:
return maybeToken$1(tokenizer);
}
}
function parse$1t(source) {
const tokenizer$1 = new tokenizer$3.Tokenizer(source);
const result = readImplicitGroup$1(tokenizer$1);
if (tokenizer$1.pos !== source.length) {
tokenizer$1.error('Unexpected input');
}
// reduce redundant groups with single group term
if (result.terms.length === 1 && result.terms[0].type === 'Group') {
return result.terms[0];
}
return result;
}
parse$1u.parse = parse$1t;
const parse$1s = parse$1u;
const MATCH$1 = { type: 'Match' };
const MISMATCH$1 = { type: 'Mismatch' };
const DISALLOW_EMPTY$1 = { type: 'DisallowEmpty' };
const LEFTPARENTHESIS$4 = 40; // (
const RIGHTPARENTHESIS$4 = 41; // )
function createCondition$1(match, thenBranch, elseBranch) {
// reduce node count
if (thenBranch === MATCH$1 && elseBranch === MISMATCH$1) {
return match;
}
if (match === MATCH$1 && thenBranch === MATCH$1 && elseBranch === MATCH$1) {
return match;
}
if (match.type === 'If' && match.else === MISMATCH$1 && thenBranch === MATCH$1) {
thenBranch = match.then;
match = match.match;
}
return {
type: 'If',
match,
then: thenBranch,
else: elseBranch
};
}
function isFunctionType$1(name) {
return (
name.length > 2 &&
name.charCodeAt(name.length - 2) === LEFTPARENTHESIS$4 &&
name.charCodeAt(name.length - 1) === RIGHTPARENTHESIS$4
);
}
function isEnumCapatible$1(term) {
return (
term.type === 'Keyword' ||
term.type === 'AtKeyword' ||
term.type === 'Function' ||
term.type === 'Type' && isFunctionType$1(term.name)
);
}
function buildGroupMatchGraph$1(combinator, terms, atLeastOneTermMatched) {
switch (combinator) {
case ' ': {
// Juxtaposing components means that all of them must occur, in the given order.
//
// a b c
// =
// match a
// then match b
// then match c
// then MATCH
// else MISMATCH
// else MISMATCH
// else MISMATCH
let result = MATCH$1;
for (let i = terms.length - 1; i >= 0; i--) {
const term = terms[i];
result = createCondition$1(
term,
result,
MISMATCH$1
);
}
return result;
}
case '|': {
// A bar (|) separates two or more alternatives: exactly one of them must occur.
//
// a | b | c
// =
// match a
// then MATCH
// else match b
// then MATCH
// else match c
// then MATCH
// else MISMATCH
let result = MISMATCH$1;
let map = null;
for (let i = terms.length - 1; i >= 0; i--) {
let term = terms[i];
// reduce sequence of keywords into a Enum
if (isEnumCapatible$1(term)) {
if (map === null && i > 0 && isEnumCapatible$1(terms[i - 1])) {
map = Object.create(null);
result = createCondition$1(
{
type: 'Enum',
map
},
MATCH$1,
result
);
}
if (map !== null) {
const key = (isFunctionType$1(term.name) ? term.name.slice(0, -1) : term.name).toLowerCase();
if (key in map === false) {
map[key] = term;
continue;
}
}
}
map = null;
// create a new conditonal node
result = createCondition$1(
term,
MATCH$1,
result
);
}
return result;
}
case '&&': {
// A double ampersand (&&) separates two or more components,
// all of which must occur, in any order.
// Use MatchOnce for groups with a large number of terms,
// since &&-groups produces at least N!-node trees
if (terms.length > 5) {
return {
type: 'MatchOnce',
terms,
all: true
};
}
// Use a combination tree for groups with small number of terms
//
// a && b && c
// =
// match a
// then [b && c]
// else match b
// then [a && c]
// else match c
// then [a && b]
// else MISMATCH
//
// a && b
// =
// match a
// then match b
// then MATCH
// else MISMATCH
// else match b
// then match a
// then MATCH
// else MISMATCH
// else MISMATCH
let result = MISMATCH$1;
for (let i = terms.length - 1; i >= 0; i--) {
const term = terms[i];
let thenClause;
if (terms.length > 1) {
thenClause = buildGroupMatchGraph$1(
combinator,
terms.filter(function(newGroupTerm) {
return newGroupTerm !== term;
}),
false
);
} else {
thenClause = MATCH$1;
}
result = createCondition$1(
term,
thenClause,
result
);
}
return result;
}
case '||': {
// A double bar (||) separates two or more options:
// one or more of them must occur, in any order.
// Use MatchOnce for groups with a large number of terms,
// since ||-groups produces at least N!-node trees
if (terms.length > 5) {
return {
type: 'MatchOnce',
terms,
all: false
};
}
// Use a combination tree for groups with small number of terms
//
// a || b || c
// =
// match a
// then [b || c]
// else match b
// then [a || c]
// else match c
// then [a || b]
// else MISMATCH
//
// a || b
// =
// match a
// then match b
// then MATCH
// else MATCH
// else match b
// then match a
// then MATCH
// else MATCH
// else MISMATCH
let result = atLeastOneTermMatched ? MATCH$1 : MISMATCH$1;
for (let i = terms.length - 1; i >= 0; i--) {
const term = terms[i];
let thenClause;
if (terms.length > 1) {
thenClause = buildGroupMatchGraph$1(
combinator,
terms.filter(function(newGroupTerm) {
return newGroupTerm !== term;
}),
true
);
} else {
thenClause = MATCH$1;
}
result = createCondition$1(
term,
thenClause,
result
);
}
return result;
}
}
}
function buildMultiplierMatchGraph$1(node) {
let result = MATCH$1;
let matchTerm = buildMatchGraphInternal$1(node.term);
if (node.max === 0) {
// disable repeating of empty match to prevent infinite loop
matchTerm = createCondition$1(
matchTerm,
DISALLOW_EMPTY$1,
MISMATCH$1
);
// an occurrence count is not limited, make a cycle;
// to collect more terms on each following matching mismatch
result = createCondition$1(
matchTerm,
null, // will be a loop
MISMATCH$1
);
result.then = createCondition$1(
MATCH$1,
MATCH$1,
result // make a loop
);
if (node.comma) {
result.then.else = createCondition$1(
{ type: 'Comma', syntax: node },
result,
MISMATCH$1
);
}
} else {
// create a match node chain for [min .. max] interval with optional matches
for (let i = node.min || 1; i <= node.max; i++) {
if (node.comma && result !== MATCH$1) {
result = createCondition$1(
{ type: 'Comma', syntax: node },
result,
MISMATCH$1
);
}
result = createCondition$1(
matchTerm,
createCondition$1(
MATCH$1,
MATCH$1,
result
),
MISMATCH$1
);
}
}
if (node.min === 0) {
// allow zero match
result = createCondition$1(
MATCH$1,
MATCH$1,
result
);
} else {
// create a match node chain to collect [0 ... min - 1] required matches
for (let i = 0; i < node.min - 1; i++) {
if (node.comma && result !== MATCH$1) {
result = createCondition$1(
{ type: 'Comma', syntax: node },
result,
MISMATCH$1
);
}
result = createCondition$1(
matchTerm,
result,
MISMATCH$1
);
}
}
return result;
}
function buildMatchGraphInternal$1(node) {
if (typeof node === 'function') {
return {
type: 'Generic',
fn: node
};
}
switch (node.type) {
case 'Group': {
let result = buildGroupMatchGraph$1(
node.combinator,
node.terms.map(buildMatchGraphInternal$1),
false
);
if (node.disallowEmpty) {
result = createCondition$1(
result,
DISALLOW_EMPTY$1,
MISMATCH$1
);
}
return result;
}
case 'Multiplier':
return buildMultiplierMatchGraph$1(node);
case 'Type':
case 'Property':
return {
type: node.type,
name: node.name,
syntax: node
};
case 'Keyword':
return {
type: node.type,
name: node.name.toLowerCase(),
syntax: node
};
case 'AtKeyword':
return {
type: node.type,
name: '@' + node.name.toLowerCase(),
syntax: node
};
case 'Function':
return {
type: node.type,
name: node.name.toLowerCase() + '(',
syntax: node
};
case 'String':
// convert a one char length String to a Token
if (node.value.length === 3) {
return {
type: 'Token',
value: node.value.charAt(1),
syntax: node
};
}
// otherwise use it as is
return {
type: node.type,
value: node.value.substr(1, node.value.length - 2).replace(/\\'/g, '\''),
syntax: node
};
case 'Token':
return {
type: node.type,
value: node.value,
syntax: node
};
case 'Comma':
return {
type: node.type,
syntax: node
};
default:
throw new Error('Unknown node type:', node.type);
}
}
function buildMatchGraph$1(syntaxTree, ref) {
if (typeof syntaxTree === 'string') {
syntaxTree = parse$1s.parse(syntaxTree);
}
return {
type: 'MatchGraph',
match: buildMatchGraphInternal$1(syntaxTree),
syntax: ref || null,
source: syntaxTree
};
}
matchGraph$5.DISALLOW_EMPTY = DISALLOW_EMPTY$1;
matchGraph$5.MATCH = MATCH$1;
matchGraph$5.MISMATCH = MISMATCH$1;
matchGraph$5.buildMatchGraph = buildMatchGraph$1;
var match$3 = {};
const matchGraph$4 = matchGraph$5;
const types$1A = types$1K;
const { hasOwnProperty: hasOwnProperty$a } = Object.prototype;
const STUB$1 = 0;
const TOKEN$1 = 1;
const OPEN_SYNTAX$1 = 2;
const CLOSE_SYNTAX$1 = 3;
const EXIT_REASON_MATCH$1 = 'Match';
const EXIT_REASON_MISMATCH$1 = 'Mismatch';
const EXIT_REASON_ITERATION_LIMIT$1 = 'Maximum iteration number exceeded (please fill an issue on https://github.com/csstree/csstree/issues)';
const ITERATION_LIMIT$1 = 15000;
function reverseList$1(list) {
let prev = null;
let next = null;
let item = list;
while (item !== null) {
next = item.prev;
item.prev = prev;
prev = item;
item = next;
}
return prev;
}
function areStringsEqualCaseInsensitive$1(testStr, referenceStr) {
if (testStr.length !== referenceStr.length) {
return false;
}
for (let i = 0; i < testStr.length; i++) {
const referenceCode = referenceStr.charCodeAt(i);
let testCode = testStr.charCodeAt(i);
// testCode.toLowerCase() for U+0041 LATIN CAPITAL LETTER A (A) .. U+005A LATIN CAPITAL LETTER Z (Z).
if (testCode >= 0x0041 && testCode <= 0x005A) {
testCode = testCode | 32;
}
if (testCode !== referenceCode) {
return false;
}
}
return true;
}
function isContextEdgeDelim$1(token) {
if (token.type !== types$1A.Delim) {
return false;
}
// Fix matching for unicode-range: U+30??, U+FF00-FF9F
// Probably we need to check out previous match instead
return token.value !== '?';
}
function isCommaContextStart$1(token) {
if (token === null) {
return true;
}
return (
token.type === types$1A.Comma ||
token.type === types$1A.Function ||
token.type === types$1A.LeftParenthesis ||
token.type === types$1A.LeftSquareBracket ||
token.type === types$1A.LeftCurlyBracket ||
isContextEdgeDelim$1(token)
);
}
function isCommaContextEnd$1(token) {
if (token === null) {
return true;
}
return (
token.type === types$1A.RightParenthesis ||
token.type === types$1A.RightSquareBracket ||
token.type === types$1A.RightCurlyBracket ||
(token.type === types$1A.Delim && token.value === '/')
);
}
function internalMatch$1(tokens, state, syntaxes) {
function moveToNextToken() {
do {
tokenIndex++;
token = tokenIndex < tokens.length ? tokens[tokenIndex] : null;
} while (token !== null && (token.type === types$1A.WhiteSpace || token.type === types$1A.Comment));
}
function getNextToken(offset) {
const nextIndex = tokenIndex + offset;
return nextIndex < tokens.length ? tokens[nextIndex] : null;
}
function stateSnapshotFromSyntax(nextState, prev) {
return {
nextState,
matchStack,
syntaxStack,
thenStack,
tokenIndex,
prev
};
}
function pushThenStack(nextState) {
thenStack = {
nextState,
matchStack,
syntaxStack,
prev: thenStack
};
}
function pushElseStack(nextState) {
elseStack = stateSnapshotFromSyntax(nextState, elseStack);
}
function addTokenToMatch() {
matchStack = {
type: TOKEN$1,
syntax: state.syntax,
token,
prev: matchStack
};
moveToNextToken();
syntaxStash = null;
if (tokenIndex > longestMatch) {
longestMatch = tokenIndex;
}
}
function openSyntax() {
syntaxStack = {
syntax: state.syntax,
opts: state.syntax.opts || (syntaxStack !== null && syntaxStack.opts) || null,
prev: syntaxStack
};
matchStack = {
type: OPEN_SYNTAX$1,
syntax: state.syntax,
token: matchStack.token,
prev: matchStack
};
}
function closeSyntax() {
if (matchStack.type === OPEN_SYNTAX$1) {
matchStack = matchStack.prev;
} else {
matchStack = {
type: CLOSE_SYNTAX$1,
syntax: syntaxStack.syntax,
token: matchStack.token,
prev: matchStack
};
}
syntaxStack = syntaxStack.prev;
}
let syntaxStack = null;
let thenStack = null;
let elseStack = null;
// null stashing allowed, nothing stashed
// false stashing disabled, nothing stashed
// anithing else fail stashable syntaxes, some syntax stashed
let syntaxStash = null;
let iterationCount = 0; // count iterations and prevent infinite loop
let exitReason = null;
let token = null;
let tokenIndex = -1;
let longestMatch = 0;
let matchStack = {
type: STUB$1,
syntax: null,
token: null,
prev: null
};
moveToNextToken();
while (exitReason === null && ++iterationCount < ITERATION_LIMIT$1) {
// function mapList(list, fn) {
// const result = [];
// while (list) {
// result.unshift(fn(list));
// list = list.prev;
// }
// return result;
// }
// console.log('--\n',
// '#' + iterationCount,
// require('util').inspect({
// match: mapList(matchStack, x => x.type === TOKEN ? x.token && x.token.value : x.syntax ? ({ [OPEN_SYNTAX]: '<', [CLOSE_SYNTAX]: '</' }[x.type] || x.type) + '!' + x.syntax.name : null),
// token: token && token.value,
// tokenIndex,
// syntax: syntax.type + (syntax.id ? ' #' + syntax.id : '')
// }, { depth: null })
// );
switch (state.type) {
case 'Match':
if (thenStack === null) {
// turn to MISMATCH when some tokens left unmatched
if (token !== null) {
// doesn't mismatch if just one token left and it's an IE hack
if (tokenIndex !== tokens.length - 1 || (token.value !== '\\0' && token.value !== '\\9')) {
state = matchGraph$4.MISMATCH;
break;
}
}
// break the main loop, return a result - MATCH
exitReason = EXIT_REASON_MATCH$1;
break;
}
// go to next syntax (`then` branch)
state = thenStack.nextState;
// check match is not empty
if (state === matchGraph$4.DISALLOW_EMPTY) {
if (thenStack.matchStack === matchStack) {
state = matchGraph$4.MISMATCH;
break;
} else {
state = matchGraph$4.MATCH;
}
}
// close syntax if needed
while (thenStack.syntaxStack !== syntaxStack) {
closeSyntax();
}
// pop stack
thenStack = thenStack.prev;
break;
case 'Mismatch':
// when some syntax is stashed
if (syntaxStash !== null && syntaxStash !== false) {
// there is no else branches or a branch reduce match stack
if (elseStack === null || tokenIndex > elseStack.tokenIndex) {
// restore state from the stash
elseStack = syntaxStash;
syntaxStash = false; // disable stashing
}
} else if (elseStack === null) {
// no else branches -> break the main loop
// return a result - MISMATCH
exitReason = EXIT_REASON_MISMATCH$1;
break;
}
// go to next syntax (`else` branch)
state = elseStack.nextState;
// restore all the rest stack states
thenStack = elseStack.thenStack;
syntaxStack = elseStack.syntaxStack;
matchStack = elseStack.matchStack;
tokenIndex = elseStack.tokenIndex;
token = tokenIndex < tokens.length ? tokens[tokenIndex] : null;
// pop stack
elseStack = elseStack.prev;
break;
case 'MatchGraph':
state = state.match;
break;
case 'If':
// IMPORTANT: else stack push must go first,
// since it stores the state of thenStack before changes
if (state.else !== matchGraph$4.MISMATCH) {
pushElseStack(state.else);
}
if (state.then !== matchGraph$4.MATCH) {
pushThenStack(state.then);
}
state = state.match;
break;
case 'MatchOnce':
state = {
type: 'MatchOnceBuffer',
syntax: state,
index: 0,
mask: 0
};
break;
case 'MatchOnceBuffer': {
const terms = state.syntax.terms;
if (state.index === terms.length) {
// no matches at all or it's required all terms to be matched
if (state.mask === 0 || state.syntax.all) {
state = matchGraph$4.MISMATCH;
break;
}
// a partial match is ok
state = matchGraph$4.MATCH;
break;
}
// all terms are matched
if (state.mask === (1 << terms.length) - 1) {
state = matchGraph$4.MATCH;
break;
}
for (; state.index < terms.length; state.index++) {
const matchFlag = 1 << state.index;
if ((state.mask & matchFlag) === 0) {
// IMPORTANT: else stack push must go first,
// since it stores the state of thenStack before changes
pushElseStack(state);
pushThenStack({
type: 'AddMatchOnce',
syntax: state.syntax,
mask: state.mask | matchFlag
});
// match
state = terms[state.index++];
break;
}
}
break;
}
case 'AddMatchOnce':
state = {
type: 'MatchOnceBuffer',
syntax: state.syntax,
index: 0,
mask: state.mask
};
break;
case 'Enum':
if (token !== null) {
let name = token.value.toLowerCase();
// drop \0 and \9 hack from keyword name
if (name.indexOf('\\') !== -1) {
name = name.replace(/\\[09].*$/, '');
}
if (hasOwnProperty$a.call(state.map, name)) {
state = state.map[name];
break;
}
}
state = matchGraph$4.MISMATCH;
break;
case 'Generic': {
const opts = syntaxStack !== null ? syntaxStack.opts : null;
const lastTokenIndex = tokenIndex + Math.floor(state.fn(token, getNextToken, opts));
if (!isNaN(lastTokenIndex) && lastTokenIndex > tokenIndex) {
while (tokenIndex < lastTokenIndex) {
addTokenToMatch();
}
state = matchGraph$4.MATCH;
} else {
state = matchGraph$4.MISMATCH;
}
break;
}
case 'Type':
case 'Property': {
const syntaxDict = state.type === 'Type' ? 'types' : 'properties';
const dictSyntax = hasOwnProperty$a.call(syntaxes, syntaxDict) ? syntaxes[syntaxDict][state.name] : null;
if (!dictSyntax || !dictSyntax.match) {
throw new Error(
'Bad syntax reference: ' +
(state.type === 'Type'
? '<' + state.name + '>'
: '<\'' + state.name + '\'>')
);
}
// stash a syntax for types with low priority
if (syntaxStash !== false && token !== null && state.type === 'Type') {
const lowPriorityMatching =
// https://drafts.csswg.org/css-values-4/#custom-idents
// When parsing positionally-ambiguous keywords in a property value, a <custom-ident> production
// can only claim the keyword if no other unfulfilled production can claim it.
(state.name === 'custom-ident' && token.type === types$1A.Ident) ||
// https://drafts.csswg.org/css-values-4/#lengths
// ... if a `0` could be parsed as either a <number> or a <length> in a property (such as line-height),
// it must parse as a <number>
(state.name === 'length' && token.value === '0');
if (lowPriorityMatching) {
if (syntaxStash === null) {
syntaxStash = stateSnapshotFromSyntax(state, elseStack);
}
state = matchGraph$4.MISMATCH;
break;
}
}
openSyntax();
state = dictSyntax.match;
break;
}
case 'Keyword': {
const name = state.name;
if (token !== null) {
let keywordName = token.value;
// drop \0 and \9 hack from keyword name
if (keywordName.indexOf('\\') !== -1) {
keywordName = keywordName.replace(/\\[09].*$/, '');
}
if (areStringsEqualCaseInsensitive$1(keywordName, name)) {
addTokenToMatch();
state = matchGraph$4.MATCH;
break;
}
}
state = matchGraph$4.MISMATCH;
break;
}
case 'AtKeyword':
case 'Function':
if (token !== null && areStringsEqualCaseInsensitive$1(token.value, state.name)) {
addTokenToMatch();
state = matchGraph$4.MATCH;
break;
}
state = matchGraph$4.MISMATCH;
break;
case 'Token':
if (token !== null && token.value === state.value) {
addTokenToMatch();
state = matchGraph$4.MATCH;
break;
}
state = matchGraph$4.MISMATCH;
break;
case 'Comma':
if (token !== null && token.type === types$1A.Comma) {
if (isCommaContextStart$1(matchStack.token)) {
state = matchGraph$4.MISMATCH;
} else {
addTokenToMatch();
state = isCommaContextEnd$1(token) ? matchGraph$4.MISMATCH : matchGraph$4.MATCH;
}
} else {
state = isCommaContextStart$1(matchStack.token) || isCommaContextEnd$1(token) ? matchGraph$4.MATCH : matchGraph$4.MISMATCH;
}
break;
case 'String':
let string = '';
let lastTokenIndex = tokenIndex;
for (; lastTokenIndex < tokens.length && string.length < state.value.length; lastTokenIndex++) {
string += tokens[lastTokenIndex].value;
}
if (areStringsEqualCaseInsensitive$1(string, state.value)) {
while (tokenIndex < lastTokenIndex) {
addTokenToMatch();
}
state = matchGraph$4.MATCH;
} else {
state = matchGraph$4.MISMATCH;
}
break;
default:
throw new Error('Unknown node type: ' + state.type);
}
}
switch (exitReason) {
case null:
console.warn('[csstree-match] BREAK after ' + ITERATION_LIMIT$1 + ' iterations');
exitReason = EXIT_REASON_ITERATION_LIMIT$1;
matchStack = null;
break;
case EXIT_REASON_MATCH$1:
while (syntaxStack !== null) {
closeSyntax();
}
break;
default:
matchStack = null;
}
return {
tokens,
reason: exitReason,
iterations: iterationCount,
match: matchStack,
longestMatch
};
}
function matchAsList$1(tokens, matchGraph, syntaxes) {
const matchResult = internalMatch$1(tokens, matchGraph, syntaxes || {});
if (matchResult.match !== null) {
let item = reverseList$1(matchResult.match).prev;
matchResult.match = [];
while (item !== null) {
switch (item.type) {
case OPEN_SYNTAX$1:
case CLOSE_SYNTAX$1:
matchResult.match.push({
type: item.type,
syntax: item.syntax
});
break;
default:
matchResult.match.push({
token: item.token.value,
node: item.token.node
});
break;
}
item = item.prev;
}
}
return matchResult;
}
function matchAsTree$1(tokens, matchGraph, syntaxes) {
const matchResult = internalMatch$1(tokens, matchGraph, syntaxes || {});
if (matchResult.match === null) {
return matchResult;
}
let item = matchResult.match;
let host = matchResult.match = {
syntax: matchGraph.syntax || null,
match: []
};
const hostStack = [host];
// revert a list and start with 2nd item since 1st is a stub item
item = reverseList$1(item).prev;
// build a tree
while (item !== null) {
switch (item.type) {
case OPEN_SYNTAX$1:
host.match.push(host = {
syntax: item.syntax,
match: []
});
hostStack.push(host);
break;
case CLOSE_SYNTAX$1:
hostStack.pop();
host = hostStack[hostStack.length - 1];
break;
default:
host.match.push({
syntax: item.syntax || null,
token: item.token.value,
node: item.token.node
});
}
item = item.prev;
}
return matchResult;
}
match$3.matchAsList = matchAsList$1;
match$3.matchAsTree = matchAsTree$1;
var trace$3 = {};
function getTrace$1(node) {
function shouldPutToTrace(syntax) {
if (syntax === null) {
return false;
}
return (
syntax.type === 'Type' ||
syntax.type === 'Property' ||
syntax.type === 'Keyword'
);
}
function hasMatch(matchNode) {
if (Array.isArray(matchNode.match)) {
// use for-loop for better perfomance
for (let i = 0; i < matchNode.match.length; i++) {
if (hasMatch(matchNode.match[i])) {
if (shouldPutToTrace(matchNode.syntax)) {
result.unshift(matchNode.syntax);
}
return true;
}
}
} else if (matchNode.node === node) {
result = shouldPutToTrace(matchNode.syntax)
? [matchNode.syntax]
: [];
return true;
}
return false;
}
let result = null;
if (this.matched !== null) {
hasMatch(this.matched);
}
return result;
}
function isType$1(node, type) {
return testNode$1(this, node, match => match.type === 'Type' && match.name === type);
}
function isProperty$1(node, property) {
return testNode$1(this, node, match => match.type === 'Property' && match.name === property);
}
function isKeyword$1(node) {
return testNode$1(this, node, match => match.type === 'Keyword');
}
function testNode$1(match, node, fn) {
const trace = getTrace$1.call(match, node);
if (trace === null) {
return false;
}
return trace.some(fn);
}
trace$3.getTrace = getTrace$1;
trace$3.isKeyword = isKeyword$1;
trace$3.isProperty = isProperty$1;
trace$3.isType = isType$1;
var search$3 = {};
const List$b = List$f;
function getFirstMatchNode$1(matchNode) {
if ('node' in matchNode) {
return matchNode.node;
}
return getFirstMatchNode$1(matchNode.match[0]);
}
function getLastMatchNode$1(matchNode) {
if ('node' in matchNode) {
return matchNode.node;
}
return getLastMatchNode$1(matchNode.match[matchNode.match.length - 1]);
}
function matchFragments$1(lexer, ast, match, type, name) {
function findFragments(matchNode) {
if (matchNode.syntax !== null &&
matchNode.syntax.type === type &&
matchNode.syntax.name === name) {
const start = getFirstMatchNode$1(matchNode);
const end = getLastMatchNode$1(matchNode);
lexer.syntax.walk(ast, function(node, item, list) {
if (node === start) {
const nodes = new List$b.List();
do {
nodes.appendData(item.data);
if (item.data === end) {
break;
}
item = item.next;
} while (item !== null);
fragments.push({
parent: list,
nodes
});
}
});
}
if (Array.isArray(matchNode.match)) {
matchNode.match.forEach(findFragments);
}
}
const fragments = [];
if (match.matched !== null) {
findFragments(match.matched);
}
return fragments;
}
search$3.matchFragments = matchFragments$1;
var structure$1k = {};
const List$a = List$f;
const { hasOwnProperty: hasOwnProperty$9 } = Object.prototype;
function isValidNumber$1(value) {
// Number.isInteger(value) && value >= 0
return (
typeof value === 'number' &&
isFinite(value) &&
Math.floor(value) === value &&
value >= 0
);
}
function isValidLocation$1(loc) {
return (
Boolean(loc) &&
isValidNumber$1(loc.offset) &&
isValidNumber$1(loc.line) &&
isValidNumber$1(loc.column)
);
}
function createNodeStructureChecker$1(type, fields) {
return function checkNode(node, warn) {
if (!node || node.constructor !== Object) {
return warn(node, 'Type of node should be an Object');
}
for (let key in node) {
let valid = true;
if (hasOwnProperty$9.call(node, key) === false) {
continue;
}
if (key === 'type') {
if (node.type !== type) {
warn(node, 'Wrong node type `' + node.type + '`, expected `' + type + '`');
}
} else if (key === 'loc') {
if (node.loc === null) {
continue;
} else if (node.loc && node.loc.constructor === Object) {
if (typeof node.loc.source !== 'string') {
key += '.source';
} else if (!isValidLocation$1(node.loc.start)) {
key += '.start';
} else if (!isValidLocation$1(node.loc.end)) {
key += '.end';
} else {
continue;
}
}
valid = false;
} else if (fields.hasOwnProperty(key)) {
valid = false;
for (let i = 0; !valid && i < fields[key].length; i++) {
const fieldType = fields[key][i];
switch (fieldType) {
case String:
valid = typeof node[key] === 'string';
break;
case Boolean:
valid = typeof node[key] === 'boolean';
break;
case null:
valid = node[key] === null;
break;
default:
if (typeof fieldType === 'string') {
valid = node[key] && node[key].type === fieldType;
} else if (Array.isArray(fieldType)) {
valid = node[key] instanceof List$a.List;
}
}
}
} else {
warn(node, 'Unknown field `' + key + '` for ' + type + ' node type');
}
if (!valid) {
warn(node, 'Bad value for `' + type + '.' + key + '`');
}
}
for (const key in fields) {
if (hasOwnProperty$9.call(fields, key) &&
hasOwnProperty$9.call(node, key) === false) {
warn(node, 'Field `' + type + '.' + key + '` is missed');
}
}
};
}
function processStructure$1(name, nodeType) {
const structure = nodeType.structure;
const fields = {
type: String,
loc: true
};
const docs = {
type: '"' + name + '"'
};
for (const key in structure) {
if (hasOwnProperty$9.call(structure, key) === false) {
continue;
}
const docsTypes = [];
const fieldTypes = fields[key] = Array.isArray(structure[key])
? structure[key].slice()
: [structure[key]];
for (let i = 0; i < fieldTypes.length; i++) {
const fieldType = fieldTypes[i];
if (fieldType === String || fieldType === Boolean) {
docsTypes.push(fieldType.name);
} else if (fieldType === null) {
docsTypes.push('null');
} else if (typeof fieldType === 'string') {
docsTypes.push('<' + fieldType + '>');
} else if (Array.isArray(fieldType)) {
docsTypes.push('List'); // TODO: use type enum
} else {
throw new Error('Wrong value `' + fieldType + '` in `' + name + '.' + key + '` structure definition');
}
}
docs[key] = docsTypes.join(' | ');
}
return {
docs,
check: createNodeStructureChecker$1(name, fields)
};
}
function getStructureFromConfig$1(config) {
const structure = {};
if (config.node) {
for (const name in config.node) {
if (hasOwnProperty$9.call(config.node, name)) {
const nodeType = config.node[name];
if (nodeType.structure) {
structure[name] = processStructure$1(name, nodeType);
} else {
throw new Error('Missed `structure` field in `' + name + '` node type definition');
}
}
}
}
return structure;
}
structure$1k.getStructureFromConfig = getStructureFromConfig$1;
var walk$a = {};
const noop$3 = function() {};
function ensureFunction$2(value) {
return typeof value === 'function' ? value : noop$3;
}
function walk$9(node, options, context) {
function walk(node) {
enter.call(context, node);
switch (node.type) {
case 'Group':
node.terms.forEach(walk);
break;
case 'Multiplier':
walk(node.term);
break;
case 'Type':
case 'Property':
case 'Keyword':
case 'AtKeyword':
case 'Function':
case 'String':
case 'Token':
case 'Comma':
break;
default:
throw new Error('Unknown type: ' + node.type);
}
leave.call(context, node);
}
let enter = noop$3;
let leave = noop$3;
if (typeof options === 'function') {
enter = options;
} else if (options) {
enter = ensureFunction$2(options.enter);
leave = ensureFunction$2(options.leave);
}
if (enter === noop$3 && leave === noop$3) {
throw new Error('Neither `enter` nor `leave` walker handler is set or both aren\'t a function');
}
walk(node);
}
walk$a.walk = walk$9;
const error$3 = error$4;
const names$b = names$c;
const genericConst$3 = genericConst$5;
const generic$2 = generic$3;
const units = units$1;
const prepareTokens$2 = prepareTokens_1$1;
const matchGraph$3 = matchGraph$5;
const match$2 = match$3;
const trace$2 = trace$3;
const search$2 = search$3;
const structure$1j = structure$1k;
const parse$1r = parse$1u;
const generate$1r = generate$1u;
const walk$8 = walk$a;
const cssWideKeywordsSyntax$1 = matchGraph$3.buildMatchGraph(genericConst$3.cssWideKeywords.join(' | '));
function dumpMapSyntax$1(map, compact, syntaxAsAst) {
const result = {};
for (const name in map) {
if (map[name].syntax) {
result[name] = syntaxAsAst
? map[name].syntax
: generate$1r.generate(map[name].syntax, { compact });
}
}
return result;
}
function dumpAtruleMapSyntax$1(map, compact, syntaxAsAst) {
const result = {};
for (const [name, atrule] of Object.entries(map)) {
result[name] = {
prelude: atrule.prelude && (
syntaxAsAst
? atrule.prelude.syntax
: generate$1r.generate(atrule.prelude.syntax, { compact })
),
descriptors: atrule.descriptors && dumpMapSyntax$1(atrule.descriptors, compact, syntaxAsAst)
};
}
return result;
}
function valueHasVar$1(tokens) {
for (let i = 0; i < tokens.length; i++) {
if (tokens[i].value.toLowerCase() === 'var(') {
return true;
}
}
return false;
}
function buildMatchResult$1(matched, error, iterations) {
return {
matched,
iterations,
error,
...trace$2
};
}
function matchSyntax$1(lexer, syntax, value, useCssWideKeywords) {
const tokens = prepareTokens$2(value, lexer.syntax);
let result;
if (valueHasVar$1(tokens)) {
return buildMatchResult$1(null, new Error('Matching for a tree with var() is not supported'));
}
if (useCssWideKeywords) {
result = match$2.matchAsTree(tokens, lexer.cssWideKeywordsSyntax, lexer);
}
if (!useCssWideKeywords || !result.match) {
result = match$2.matchAsTree(tokens, syntax.match, lexer);
if (!result.match) {
return buildMatchResult$1(
null,
new error$3.SyntaxMatchError(result.reason, syntax.syntax, value, result),
result.iterations
);
}
}
return buildMatchResult$1(result.match, null, result.iterations);
}
let Lexer$6 = class Lexer {
constructor(config, syntax, structure$1) {
this.cssWideKeywordsSyntax = cssWideKeywordsSyntax$1;
this.syntax = syntax;
this.generic = false;
this.units = { ...units };
this.atrules = Object.create(null);
this.properties = Object.create(null);
this.types = Object.create(null);
this.structure = structure$1 || structure$1j.getStructureFromConfig(config);
if (config) {
if (config.units) {
for (const group of Object.keys(units)) {
if (Array.isArray(config.units[group])) {
this.units[group] = config.units[group];
}
}
}
if (config.types) {
for (const name in config.types) {
this.addType_(name, config.types[name]);
}
}
if (config.generic) {
this.generic = true;
for (const [name, value] of Object.entries(generic$2.createGenericTypes(this.units))) {
this.addType_(name, value);
}
}
if (config.atrules) {
for (const name in config.atrules) {
this.addAtrule_(name, config.atrules[name]);
}
}
if (config.properties) {
for (const name in config.properties) {
this.addProperty_(name, config.properties[name]);
}
}
}
}
checkStructure(ast) {
function collectWarning(node, message) {
warns.push({ node, message });
}
const structure = this.structure;
const warns = [];
this.syntax.walk(ast, function(node) {
if (structure.hasOwnProperty(node.type)) {
structure[node.type].check(node, collectWarning);
} else {
collectWarning(node, 'Unknown node type `' + node.type + '`');
}
});
return warns.length ? warns : false;
}
createDescriptor(syntax, type, name, parent = null) {
const ref = {
type,
name
};
const descriptor = {
type,
name,
parent,
serializable: typeof syntax === 'string' || (syntax && typeof syntax.type === 'string'),
syntax: null,
match: null
};
if (typeof syntax === 'function') {
descriptor.match = matchGraph$3.buildMatchGraph(syntax, ref);
} else {
if (typeof syntax === 'string') {
// lazy parsing on first access
Object.defineProperty(descriptor, 'syntax', {
get() {
Object.defineProperty(descriptor, 'syntax', {
value: parse$1r.parse(syntax)
});
return descriptor.syntax;
}
});
} else {
descriptor.syntax = syntax;
}
// lazy graph build on first access
Object.defineProperty(descriptor, 'match', {
get() {
Object.defineProperty(descriptor, 'match', {
value: matchGraph$3.buildMatchGraph(descriptor.syntax, ref)
});
return descriptor.match;
}
});
}
return descriptor;
}
addAtrule_(name, syntax) {
if (!syntax) {
return;
}
this.atrules[name] = {
type: 'Atrule',
name: name,
prelude: syntax.prelude ? this.createDescriptor(syntax.prelude, 'AtrulePrelude', name) : null,
descriptors: syntax.descriptors
? Object.keys(syntax.descriptors).reduce(
(map, descName) => {
map[descName] = this.createDescriptor(syntax.descriptors[descName], 'AtruleDescriptor', descName, name);
return map;
},
Object.create(null)
)
: null
};
}
addProperty_(name, syntax) {
if (!syntax) {
return;
}
this.properties[name] = this.createDescriptor(syntax, 'Property', name);
}
addType_(name, syntax) {
if (!syntax) {
return;
}
this.types[name] = this.createDescriptor(syntax, 'Type', name);
}
checkAtruleName(atruleName) {
if (!this.getAtrule(atruleName)) {
return new error$3.SyntaxReferenceError('Unknown at-rule', '@' + atruleName);
}
}
checkAtrulePrelude(atruleName, prelude) {
const error = this.checkAtruleName(atruleName);
if (error) {
return error;
}
const atrule = this.getAtrule(atruleName);
if (!atrule.prelude && prelude) {
return new SyntaxError('At-rule `@' + atruleName + '` should not contain a prelude');
}
if (atrule.prelude && !prelude) {
if (!matchSyntax$1(this, atrule.prelude, '', false).matched) {
return new SyntaxError('At-rule `@' + atruleName + '` should contain a prelude');
}
}
}
checkAtruleDescriptorName(atruleName, descriptorName) {
const error$1 = this.checkAtruleName(atruleName);
if (error$1) {
return error$1;
}
const atrule = this.getAtrule(atruleName);
const descriptor = names$b.keyword(descriptorName);
if (!atrule.descriptors) {
return new SyntaxError('At-rule `@' + atruleName + '` has no known descriptors');
}
if (!atrule.descriptors[descriptor.name] &&
!atrule.descriptors[descriptor.basename]) {
return new error$3.SyntaxReferenceError('Unknown at-rule descriptor', descriptorName);
}
}
checkPropertyName(propertyName) {
if (!this.getProperty(propertyName)) {
return new error$3.SyntaxReferenceError('Unknown property', propertyName);
}
}
matchAtrulePrelude(atruleName, prelude) {
const error = this.checkAtrulePrelude(atruleName, prelude);
if (error) {
return buildMatchResult$1(null, error);
}
const atrule = this.getAtrule(atruleName);
if (!atrule.prelude) {
return buildMatchResult$1(null, null);
}
return matchSyntax$1(this, atrule.prelude, prelude || '', false);
}
matchAtruleDescriptor(atruleName, descriptorName, value) {
const error = this.checkAtruleDescriptorName(atruleName, descriptorName);
if (error) {
return buildMatchResult$1(null, error);
}
const atrule = this.getAtrule(atruleName);
const descriptor = names$b.keyword(descriptorName);
return matchSyntax$1(this, atrule.descriptors[descriptor.name] || atrule.descriptors[descriptor.basename], value, false);
}
matchDeclaration(node) {
if (node.type !== 'Declaration') {
return buildMatchResult$1(null, new Error('Not a Declaration node'));
}
return this.matchProperty(node.property, node.value);
}
matchProperty(propertyName, value) {
// don't match syntax for a custom property at the moment
if (names$b.property(propertyName).custom) {
return buildMatchResult$1(null, new Error('Lexer matching doesn\'t applicable for custom properties'));
}
const error = this.checkPropertyName(propertyName);
if (error) {
return buildMatchResult$1(null, error);
}
return matchSyntax$1(this, this.getProperty(propertyName), value, true);
}
matchType(typeName, value) {
const typeSyntax = this.getType(typeName);
if (!typeSyntax) {
return buildMatchResult$1(null, new error$3.SyntaxReferenceError('Unknown type', typeName));
}
return matchSyntax$1(this, typeSyntax, value, false);
}
match(syntax, value) {
if (typeof syntax !== 'string' && (!syntax || !syntax.type)) {
return buildMatchResult$1(null, new error$3.SyntaxReferenceError('Bad syntax'));
}
if (typeof syntax === 'string' || !syntax.match) {
syntax = this.createDescriptor(syntax, 'Type', 'anonymous');
}
return matchSyntax$1(this, syntax, value, false);
}
findValueFragments(propertyName, value, type, name) {
return search$2.matchFragments(this, value, this.matchProperty(propertyName, value), type, name);
}
findDeclarationValueFragments(declaration, type, name) {
return search$2.matchFragments(this, declaration.value, this.matchDeclaration(declaration), type, name);
}
findAllFragments(ast, type, name) {
const result = [];
this.syntax.walk(ast, {
visit: 'Declaration',
enter: (declaration) => {
result.push.apply(result, this.findDeclarationValueFragments(declaration, type, name));
}
});
return result;
}
getAtrule(atruleName, fallbackBasename = true) {
const atrule = names$b.keyword(atruleName);
const atruleEntry = atrule.vendor && fallbackBasename
? this.atrules[atrule.name] || this.atrules[atrule.basename]
: this.atrules[atrule.name];
return atruleEntry || null;
}
getAtrulePrelude(atruleName, fallbackBasename = true) {
const atrule = this.getAtrule(atruleName, fallbackBasename);
return atrule && atrule.prelude || null;
}
getAtruleDescriptor(atruleName, name) {
return this.atrules.hasOwnProperty(atruleName) && this.atrules.declarators
? this.atrules[atruleName].declarators[name] || null
: null;
}
getProperty(propertyName, fallbackBasename = true) {
const property = names$b.property(propertyName);
const propertyEntry = property.vendor && fallbackBasename
? this.properties[property.name] || this.properties[property.basename]
: this.properties[property.name];
return propertyEntry || null;
}
getType(name) {
return hasOwnProperty.call(this.types, name) ? this.types[name] : null;
}
validate() {
function validate(syntax, name, broken, descriptor) {
if (broken.has(name)) {
return broken.get(name);
}
broken.set(name, false);
if (descriptor.syntax !== null) {
walk$8.walk(descriptor.syntax, function(node) {
if (node.type !== 'Type' && node.type !== 'Property') {
return;
}
const map = node.type === 'Type' ? syntax.types : syntax.properties;
const brokenMap = node.type === 'Type' ? brokenTypes : brokenProperties;
if (!hasOwnProperty.call(map, node.name) || validate(syntax, node.name, brokenMap, map[node.name])) {
broken.set(name, true);
}
}, this);
}
}
let brokenTypes = new Map();
let brokenProperties = new Map();
for (const key in this.types) {
validate(this, key, brokenTypes, this.types[key]);
}
for (const key in this.properties) {
validate(this, key, brokenProperties, this.properties[key]);
}
brokenTypes = [...brokenTypes.keys()].filter(name => brokenTypes.get(name));
brokenProperties = [...brokenProperties.keys()].filter(name => brokenProperties.get(name));
if (brokenTypes.length || brokenProperties.length) {
return {
types: brokenTypes,
properties: brokenProperties
};
}
return null;
}
dump(syntaxAsAst, pretty) {
return {
generic: this.generic,
units: this.units,
types: dumpMapSyntax$1(this.types, !pretty, syntaxAsAst),
properties: dumpMapSyntax$1(this.properties, !pretty, syntaxAsAst),
atrules: dumpAtruleMapSyntax$1(this.atrules, !pretty, syntaxAsAst)
};
}
toString() {
return JSON.stringify(this.dump());
}
};
Lexer$7.Lexer = Lexer$6;
function appendOrSet(a, b) {
if (typeof b === 'string' && /^\s*\|/.test(b)) {
return typeof a === 'string'
? a + b
: b.replace(/^\s*\|\s*/, '');
}
return b || null;
}
function sliceProps(obj, props) {
const result = Object.create(null);
for (const [key, value] of Object.entries(obj)) {
if (value) {
result[key] = {};
for (const prop of Object.keys(value)) {
if (props.includes(prop)) {
result[key][prop] = value[prop];
}
}
}
}
return result;
}
function mix$3(dest, src) {
const result = { ...dest };
for (const [prop, value] of Object.entries(src)) {
switch (prop) {
case 'generic':
result[prop] = Boolean(value);
break;
case 'units':
result[prop] = { ...dest[prop] };
for (const [name, patch] of Object.entries(value)) {
result[prop][name] = Array.isArray(patch) ? patch : [];
}
break;
case 'atrules':
result[prop] = { ...dest[prop] };
for (const [name, atrule] of Object.entries(value)) {
const exists = result[prop][name] || {};
const current = result[prop][name] = {
prelude: exists.prelude || null,
descriptors: {
...exists.descriptors
}
};
if (!atrule) {
continue;
}
current.prelude = atrule.prelude
? appendOrSet(current.prelude, atrule.prelude)
: current.prelude || null;
for (const [descriptorName, descriptorValue] of Object.entries(atrule.descriptors || {})) {
current.descriptors[descriptorName] = descriptorValue
? appendOrSet(current.descriptors[descriptorName], descriptorValue)
: null;
}
if (!Object.keys(current.descriptors).length) {
current.descriptors = null;
}
}
break;
case 'types':
case 'properties':
result[prop] = { ...dest[prop] };
for (const [name, syntax] of Object.entries(value)) {
result[prop][name] = appendOrSet(result[prop][name], syntax);
}
break;
case 'scope':
result[prop] = { ...dest[prop] };
for (const [name, props] of Object.entries(value)) {
result[prop][name] = { ...result[prop][name], ...props };
}
break;
case 'parseContext':
result[prop] = {
...dest[prop],
...value
};
break;
case 'atrule':
case 'pseudo':
result[prop] = {
...dest[prop],
...sliceProps(value, ['parse']) };
break;
case 'node':
result[prop] = {
...dest[prop],
...sliceProps(value, ['name', 'structure', 'parse', 'generate', 'walkContext'])
};
break;
}
}
return result;
}
var mix_1$1 = mix$3;
const index$g = tokenizer$5;
const create$a = create$e;
const create$2$2 = create$d;
const create$3$1 = create$c;
const create$1$2 = create$b;
const Lexer$5 = Lexer$7;
const mix$2 = mix_1$1;
function createSyntax$2(config) {
const parse = create$a.createParser(config);
const walk = create$1$2.createWalker(config);
const generate = create$2$2.createGenerator(config);
const { fromPlainObject, toPlainObject } = create$3$1.createConvertor(walk);
const syntax = {
lexer: null,
createLexer: config => new Lexer$5.Lexer(config, syntax, syntax.lexer.structure),
tokenize: index$g.tokenize,
parse,
generate,
walk,
find: walk.find,
findLast: walk.findLast,
findAll: walk.findAll,
fromPlainObject,
toPlainObject,
fork(extension) {
const base = mix$2({}, config); // copy of config
return createSyntax$2(
typeof extension === 'function'
? extension(base, Object.assign)
: mix$2(base, extension)
);
}
};
syntax.lexer = new Lexer$5.Lexer({
generic: true,
units: config.units,
types: config.types,
atrules: config.atrules,
properties: config.properties,
node: config.node
}, syntax);
return syntax;
}
const createSyntax$1$1 = config => createSyntax$2(mix$2({}, config));
var create_1$1 = createSyntax$1$1;
const atrules$1 = {
charset: {
prelude: "<string>"
},
"font-face": {
descriptors: {
"unicode-range": {
comment: "replaces <unicode-range>, an old production name",
syntax: "<urange>#"
}
}
},
nest: {
prelude: "<complex-selector-list>"
}
};
const properties$2 = {
"-moz-background-clip": {
comment: "deprecated syntax in old Firefox, https://developer.mozilla.org/en/docs/Web/CSS/background-clip",
syntax: "padding | border"
},
"-moz-border-radius-bottomleft": {
comment: "https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-left-radius",
syntax: "<'border-bottom-left-radius'>"
},
"-moz-border-radius-bottomright": {
comment: "https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-right-radius",
syntax: "<'border-bottom-right-radius'>"
},
"-moz-border-radius-topleft": {
comment: "https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-left-radius",
syntax: "<'border-top-left-radius'>"
},
"-moz-border-radius-topright": {
comment: "https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-right-radius",
syntax: "<'border-bottom-right-radius'>"
},
"-moz-control-character-visibility": {
comment: "firefox specific keywords, https://bugzilla.mozilla.org/show_bug.cgi?id=947588",
syntax: "visible | hidden"
},
"-moz-osx-font-smoothing": {
comment: "misssed old syntax https://developer.mozilla.org/en-US/docs/Web/CSS/font-smooth",
syntax: "auto | grayscale"
},
"-moz-user-select": {
comment: "https://developer.mozilla.org/en-US/docs/Web/CSS/user-select",
syntax: "none | text | all | -moz-none"
},
"-ms-flex-align": {
comment: "misssed old syntax implemented in IE, https://www.w3.org/TR/2012/WD-css3-flexbox-20120322/#flex-align",
syntax: "start | end | center | baseline | stretch"
},
"-ms-flex-item-align": {
comment: "misssed old syntax implemented in IE, https://www.w3.org/TR/2012/WD-css3-flexbox-20120322/#flex-align",
syntax: "auto | start | end | center | baseline | stretch"
},
"-ms-flex-line-pack": {
comment: "misssed old syntax implemented in IE, https://www.w3.org/TR/2012/WD-css3-flexbox-20120322/#flex-line-pack",
syntax: "start | end | center | justify | distribute | stretch"
},
"-ms-flex-negative": {
comment: "misssed old syntax implemented in IE; TODO: find references for comfirmation",
syntax: "<'flex-shrink'>"
},
"-ms-flex-pack": {
comment: "misssed old syntax implemented in IE, https://www.w3.org/TR/2012/WD-css3-flexbox-20120322/#flex-pack",
syntax: "start | end | center | justify | distribute"
},
"-ms-flex-order": {
comment: "misssed old syntax implemented in IE; https://msdn.microsoft.com/en-us/library/jj127303(v=vs.85).aspx",
syntax: "<integer>"
},
"-ms-flex-positive": {
comment: "misssed old syntax implemented in IE; TODO: find references for comfirmation",
syntax: "<'flex-grow'>"
},
"-ms-flex-preferred-size": {
comment: "misssed old syntax implemented in IE; TODO: find references for comfirmation",
syntax: "<'flex-basis'>"
},
"-ms-interpolation-mode": {
comment: "https://msdn.microsoft.com/en-us/library/ff521095(v=vs.85).aspx",
syntax: "nearest-neighbor | bicubic"
},
"-ms-grid-column-align": {
comment: "add this property first since it uses as fallback for flexbox, https://msdn.microsoft.com/en-us/library/windows/apps/hh466338.aspx",
syntax: "start | end | center | stretch"
},
"-ms-grid-row-align": {
comment: "add this property first since it uses as fallback for flexbox, https://msdn.microsoft.com/en-us/library/windows/apps/hh466348.aspx",
syntax: "start | end | center | stretch"
},
"-ms-hyphenate-limit-last": {
comment: "misssed old syntax implemented in IE; https://www.w3.org/TR/css-text-4/#hyphenate-line-limits",
syntax: "none | always | column | page | spread"
},
"-webkit-appearance": {
comment: "webkit specific keywords",
references: [
"http://css-infos.net/property/-webkit-appearance"
],
syntax: "none | button | button-bevel | caps-lock-indicator | 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 | scrollbarbutton-down | scrollbarbutton-left | scrollbarbutton-right | scrollbarbutton-up | scrollbargripper-horizontal | scrollbargripper-vertical | scrollbarthumb-horizontal | scrollbarthumb-vertical | scrollbartrack-horizontal | scrollbartrack-vertical | 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-background-clip": {
comment: "https://developer.mozilla.org/en/docs/Web/CSS/background-clip",
syntax: "[ <box> | border | padding | content | text ]#"
},
"-webkit-column-break-after": {
comment: "added, http://help.dottoro.com/lcrthhhv.php",
syntax: "always | auto | avoid"
},
"-webkit-column-break-before": {
comment: "added, http://help.dottoro.com/lcxquvkf.php",
syntax: "always | auto | avoid"
},
"-webkit-column-break-inside": {
comment: "added, http://help.dottoro.com/lclhnthl.php",
syntax: "always | auto | avoid"
},
"-webkit-font-smoothing": {
comment: "https://developer.mozilla.org/en-US/docs/Web/CSS/font-smooth",
syntax: "auto | none | antialiased | subpixel-antialiased"
},
"-webkit-mask-box-image": {
comment: "missed; https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-mask-box-image",
syntax: "[ <url> | <gradient> | none ] [ <length-percentage>{4} <-webkit-mask-box-repeat>{2} ]?"
},
"-webkit-print-color-adjust": {
comment: "missed",
references: [
"https://developer.mozilla.org/en/docs/Web/CSS/-webkit-print-color-adjust"
],
syntax: "economy | exact"
},
"-webkit-text-security": {
comment: "missed; http://help.dottoro.com/lcbkewgt.php",
syntax: "none | circle | disc | square"
},
"-webkit-user-drag": {
comment: "missed; http://help.dottoro.com/lcbixvwm.php",
syntax: "none | element | auto"
},
"-webkit-user-select": {
comment: "auto is supported by old webkit, https://developer.mozilla.org/en-US/docs/Web/CSS/user-select",
syntax: "auto | none | text | all"
},
"alignment-baseline": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/text.html#AlignmentBaselineProperty"
],
syntax: "auto | baseline | before-edge | text-before-edge | middle | central | after-edge | text-after-edge | ideographic | alphabetic | hanging | mathematical"
},
"background-clip": {
comment: "used <bg-clip> from CSS Backgrounds and Borders 4 since it adds new values",
references: [
"https://github.com/csstree/csstree/issues/190"
],
syntax: "<bg-clip>#"
},
"baseline-shift": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/text.html#BaselineShiftProperty"
],
syntax: "baseline | sub | super | <svg-length>"
},
behavior: {
comment: "added old IE property https://msdn.microsoft.com/en-us/library/ms530723(v=vs.85).aspx",
syntax: "<url>+"
},
"clip-rule": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/masking.html#ClipRuleProperty"
],
syntax: "nonzero | evenodd"
},
cue: {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<'cue-before'> <'cue-after'>?"
},
"cue-after": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<url> <decibel>? | none"
},
"cue-before": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<url> <decibel>? | none"
},
cursor: {
comment: "added legacy keywords: hand, -webkit-grab. -webkit-grabbing, -webkit-zoom-in, -webkit-zoom-out, -moz-grab, -moz-grabbing, -moz-zoom-in, -moz-zoom-out",
references: [
"https://www.sitepoint.com/css3-cursor-styles/"
],
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 | hand | -webkit-grab | -webkit-grabbing | -webkit-zoom-in | -webkit-zoom-out | -moz-grab | -moz-grabbing | -moz-zoom-in | -moz-zoom-out ] ]"
},
display: {
comment: "extended with -ms-flexbox",
syntax: "| <-non-standard-display>"
},
position: {
comment: "extended with -webkit-sticky",
syntax: "| -webkit-sticky"
},
"dominant-baseline": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/text.html#DominantBaselineProperty"
],
syntax: "auto | use-script | no-change | reset-size | ideographic | alphabetic | hanging | mathematical | central | middle | text-after-edge | text-before-edge"
},
"image-rendering": {
comment: "extended with <-non-standard-image-rendering>, added SVG keywords optimizeSpeed and optimizeQuality",
references: [
"https://developer.mozilla.org/en/docs/Web/CSS/image-rendering",
"https://www.w3.org/TR/SVG/painting.html#ImageRenderingProperty"
],
syntax: "| optimizeSpeed | optimizeQuality | <-non-standard-image-rendering>"
},
fill: {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#FillProperty"
],
syntax: "<paint>"
},
"fill-opacity": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#FillProperty"
],
syntax: "<number-zero-one>"
},
"fill-rule": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#FillProperty"
],
syntax: "nonzero | evenodd"
},
filter: {
comment: "extend with IE legacy syntaxes",
syntax: "| <-ms-filter-function-list>"
},
"glyph-orientation-horizontal": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/text.html#GlyphOrientationHorizontalProperty"
],
syntax: "<angle>"
},
"glyph-orientation-vertical": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/text.html#GlyphOrientationVerticalProperty"
],
syntax: "<angle>"
},
kerning: {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/text.html#KerningProperty"
],
syntax: "auto | <svg-length>"
},
"letter-spacing": {
comment: "fix syntax <length> -> <length-percentage>",
references: [
"https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/letter-spacing"
],
syntax: "normal | <length-percentage>"
},
marker: {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#MarkerProperties"
],
syntax: "none | <url>"
},
"marker-end": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#MarkerProperties"
],
syntax: "none | <url>"
},
"marker-mid": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#MarkerProperties"
],
syntax: "none | <url>"
},
"marker-start": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#MarkerProperties"
],
syntax: "none | <url>"
},
"max-width": {
comment: "extend by non-standard width keywords https://developer.mozilla.org/en-US/docs/Web/CSS/max-width",
syntax: "| <-non-standard-width>"
},
width: {
references: [
"https://developer.mozilla.org/en-US/docs/Web/CSS/width",
"https://github.com/csstree/stylelint-validator/issues/29"
],
syntax: "| fill | stretch | intrinsic | -moz-max-content | -webkit-max-content | -moz-fit-content | -webkit-fit-content"
},
"min-width": {
comment: "extend by non-standard width keywords https://developer.mozilla.org/en-US/docs/Web/CSS/width",
syntax: "| <-non-standard-width>"
},
overflow: {
comment: "extend by vendor keywords https://developer.mozilla.org/en-US/docs/Web/CSS/overflow",
syntax: "| <-non-standard-overflow>"
},
pause: {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<'pause-before'> <'pause-after'>?"
},
"pause-after": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<time> | none | x-weak | weak | medium | strong | x-strong"
},
"pause-before": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<time> | none | x-weak | weak | medium | strong | x-strong"
},
rest: {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<'rest-before'> <'rest-after'>?"
},
"rest-after": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<time> | none | x-weak | weak | medium | strong | x-strong"
},
"rest-before": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<time> | none | x-weak | weak | medium | strong | x-strong"
},
"shape-rendering": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#ShapeRenderingPropert"
],
syntax: "auto | optimizeSpeed | crispEdges | geometricPrecision"
},
src: {
comment: "added @font-face's src property https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/src",
syntax: "[ <url> [ format( <string># ) ]? | local( <family-name> ) ]#"
},
speak: {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "auto | none | normal"
},
"speak-as": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "normal | spell-out || digits || [ literal-punctuation | no-punctuation ]"
},
stroke: {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
],
syntax: "<paint>"
},
"stroke-dasharray": {
comment: "added SVG property; a list of comma and/or white space separated <length>s and <percentage>s",
references: [
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
],
syntax: "none | [ <svg-length>+ ]#"
},
"stroke-dashoffset": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
],
syntax: "<svg-length>"
},
"stroke-linecap": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
],
syntax: "butt | round | square"
},
"stroke-linejoin": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
],
syntax: "miter | round | bevel"
},
"stroke-miterlimit": {
comment: "added SVG property (<miterlimit> = <number-one-or-greater>) ",
references: [
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
],
syntax: "<number-one-or-greater>"
},
"stroke-opacity": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
],
syntax: "<number-zero-one>"
},
"stroke-width": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
],
syntax: "<svg-length>"
},
"text-anchor": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/text.html#TextAlignmentProperties"
],
syntax: "start | middle | end"
},
"unicode-bidi": {
comment: "added prefixed keywords https://developer.mozilla.org/en-US/docs/Web/CSS/unicode-bidi",
syntax: "| -moz-isolate | -moz-isolate-override | -moz-plaintext | -webkit-isolate | -webkit-isolate-override | -webkit-plaintext"
},
"unicode-range": {
comment: "added missed property https://developer.mozilla.org/en-US/docs/Web/CSS/%40font-face/unicode-range",
syntax: "<urange>#"
},
"voice-balance": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<number> | left | center | right | leftwards | rightwards"
},
"voice-duration": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "auto | <time>"
},
"voice-family": {
comment: "<name> -> <family-name>, https://www.w3.org/TR/css3-speech/#property-index",
syntax: "[ [ <family-name> | <generic-voice> ] , ]* [ <family-name> | <generic-voice> ] | preserve"
},
"voice-pitch": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<frequency> && absolute | [ [ x-low | low | medium | high | x-high ] || [ <frequency> | <semitones> | <percentage> ] ]"
},
"voice-range": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<frequency> && absolute | [ [ x-low | low | medium | high | x-high ] || [ <frequency> | <semitones> | <percentage> ] ]"
},
"voice-rate": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "[ normal | x-slow | slow | medium | fast | x-fast ] || <percentage>"
},
"voice-stress": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "normal | strong | moderate | none | reduced"
},
"voice-volume": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "silent | [ [ x-soft | soft | medium | loud | x-loud ] || <decibel> ]"
},
"writing-mode": {
comment: "extend with SVG keywords",
syntax: "| <svg-writing-mode>"
}
};
const types$1z = {
"-legacy-gradient": {
comment: "added collection of legacy gradient syntaxes",
syntax: "<-webkit-gradient()> | <-legacy-linear-gradient> | <-legacy-repeating-linear-gradient> | <-legacy-radial-gradient> | <-legacy-repeating-radial-gradient>"
},
"-legacy-linear-gradient": {
comment: "like standard syntax but w/o `to` keyword https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient",
syntax: "-moz-linear-gradient( <-legacy-linear-gradient-arguments> ) | -webkit-linear-gradient( <-legacy-linear-gradient-arguments> ) | -o-linear-gradient( <-legacy-linear-gradient-arguments> )"
},
"-legacy-repeating-linear-gradient": {
comment: "like standard syntax but w/o `to` keyword https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient",
syntax: "-moz-repeating-linear-gradient( <-legacy-linear-gradient-arguments> ) | -webkit-repeating-linear-gradient( <-legacy-linear-gradient-arguments> ) | -o-repeating-linear-gradient( <-legacy-linear-gradient-arguments> )"
},
"-legacy-linear-gradient-arguments": {
comment: "like standard syntax but w/o `to` keyword https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient",
syntax: "[ <angle> | <side-or-corner> ]? , <color-stop-list>"
},
"-legacy-radial-gradient": {
comment: "deprecated syntax that implemented by some browsers https://www.w3.org/TR/2011/WD-css3-images-20110908/#radial-gradients",
syntax: "-moz-radial-gradient( <-legacy-radial-gradient-arguments> ) | -webkit-radial-gradient( <-legacy-radial-gradient-arguments> ) | -o-radial-gradient( <-legacy-radial-gradient-arguments> )"
},
"-legacy-repeating-radial-gradient": {
comment: "deprecated syntax that implemented by some browsers https://www.w3.org/TR/2011/WD-css3-images-20110908/#radial-gradients",
syntax: "-moz-repeating-radial-gradient( <-legacy-radial-gradient-arguments> ) | -webkit-repeating-radial-gradient( <-legacy-radial-gradient-arguments> ) | -o-repeating-radial-gradient( <-legacy-radial-gradient-arguments> )"
},
"-legacy-radial-gradient-arguments": {
comment: "deprecated syntax that implemented by some browsers https://www.w3.org/TR/2011/WD-css3-images-20110908/#radial-gradients",
syntax: "[ <position> , ]? [ [ [ <-legacy-radial-gradient-shape> || <-legacy-radial-gradient-size> ] | [ <length> | <percentage> ]{2} ] , ]? <color-stop-list>"
},
"-legacy-radial-gradient-size": {
comment: "before a standard it contains 2 extra keywords (`contain` and `cover`) https://www.w3.org/TR/2011/WD-css3-images-20110908/#ltsize",
syntax: "closest-side | closest-corner | farthest-side | farthest-corner | contain | cover"
},
"-legacy-radial-gradient-shape": {
comment: "define to double sure it doesn't extends in future https://www.w3.org/TR/2011/WD-css3-images-20110908/#ltshape",
syntax: "circle | ellipse"
},
"-non-standard-font": {
comment: "non standard fonts",
references: [
"https://webkit.org/blog/3709/using-the-system-font-in-web-content/"
],
syntax: "-apple-system-body | -apple-system-headline | -apple-system-subheadline | -apple-system-caption1 | -apple-system-caption2 | -apple-system-footnote | -apple-system-short-body | -apple-system-short-headline | -apple-system-short-subheadline | -apple-system-short-caption1 | -apple-system-short-footnote | -apple-system-tall-body"
},
"-non-standard-color": {
comment: "non standard colors",
references: [
"http://cssdot.ru/%D0%A1%D0%BF%D1%80%D0%B0%D0%B2%D0%BE%D1%87%D0%BD%D0%B8%D0%BA_CSS/color-i305.html",
"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Mozilla_Color_Preference_Extensions"
],
syntax: "-moz-ButtonDefault | -moz-ButtonHoverFace | -moz-ButtonHoverText | -moz-CellHighlight | -moz-CellHighlightText | -moz-Combobox | -moz-ComboboxText | -moz-Dialog | -moz-DialogText | -moz-dragtargetzone | -moz-EvenTreeRow | -moz-Field | -moz-FieldText | -moz-html-CellHighlight | -moz-html-CellHighlightText | -moz-mac-accentdarkestshadow | -moz-mac-accentdarkshadow | -moz-mac-accentface | -moz-mac-accentlightesthighlight | -moz-mac-accentlightshadow | -moz-mac-accentregularhighlight | -moz-mac-accentregularshadow | -moz-mac-chrome-active | -moz-mac-chrome-inactive | -moz-mac-focusring | -moz-mac-menuselect | -moz-mac-menushadow | -moz-mac-menutextselect | -moz-MenuHover | -moz-MenuHoverText | -moz-MenuBarText | -moz-MenuBarHoverText | -moz-nativehyperlinktext | -moz-OddTreeRow | -moz-win-communicationstext | -moz-win-mediatext | -moz-activehyperlinktext | -moz-default-background-color | -moz-default-color | -moz-hyperlinktext | -moz-visitedhyperlinktext | -webkit-activelink | -webkit-focus-ring-color | -webkit-link | -webkit-text"
},
"-non-standard-image-rendering": {
comment: "non-standard keywords http://phrogz.net/tmp/canvas_image_zoom.html",
syntax: "optimize-contrast | -moz-crisp-edges | -o-crisp-edges | -webkit-optimize-contrast"
},
"-non-standard-overflow": {
comment: "non-standard keywords https://developer.mozilla.org/en-US/docs/Web/CSS/overflow",
syntax: "-moz-scrollbars-none | -moz-scrollbars-horizontal | -moz-scrollbars-vertical | -moz-hidden-unscrollable"
},
"-non-standard-width": {
comment: "non-standard keywords https://developer.mozilla.org/en-US/docs/Web/CSS/width",
syntax: "fill-available | min-intrinsic | intrinsic | -moz-available | -moz-fit-content | -moz-min-content | -moz-max-content | -webkit-min-content | -webkit-max-content"
},
"-webkit-gradient()": {
comment: "first Apple proposal gradient syntax https://webkit.org/blog/175/introducing-css-gradients/ - TODO: simplify when after match algorithm improvement ( [, point, radius | , point] -> [, radius]? , point )",
syntax: "-webkit-gradient( <-webkit-gradient-type>, <-webkit-gradient-point> [, <-webkit-gradient-point> | , <-webkit-gradient-radius>, <-webkit-gradient-point> ] [, <-webkit-gradient-radius>]? [, <-webkit-gradient-color-stop>]* )"
},
"-webkit-gradient-color-stop": {
comment: "first Apple proposal gradient syntax https://webkit.org/blog/175/introducing-css-gradients/",
syntax: "from( <color> ) | color-stop( [ <number-zero-one> | <percentage> ] , <color> ) | to( <color> )"
},
"-webkit-gradient-point": {
comment: "first Apple proposal gradient syntax https://webkit.org/blog/175/introducing-css-gradients/",
syntax: "[ left | center | right | <length-percentage> ] [ top | center | bottom | <length-percentage> ]"
},
"-webkit-gradient-radius": {
comment: "first Apple proposal gradient syntax https://webkit.org/blog/175/introducing-css-gradients/",
syntax: "<length> | <percentage>"
},
"-webkit-gradient-type": {
comment: "first Apple proposal gradient syntax https://webkit.org/blog/175/introducing-css-gradients/",
syntax: "linear | radial"
},
"-webkit-mask-box-repeat": {
comment: "missed; https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-mask-box-image",
syntax: "repeat | stretch | round"
},
"-webkit-mask-clip-style": {
comment: "missed; there is no enough information about `-webkit-mask-clip` property, but looks like all those keywords are working",
syntax: "border | border-box | padding | padding-box | content | content-box | text"
},
"-ms-filter-function-list": {
comment: "https://developer.mozilla.org/en-US/docs/Web/CSS/-ms-filter",
syntax: "<-ms-filter-function>+"
},
"-ms-filter-function": {
comment: "https://developer.mozilla.org/en-US/docs/Web/CSS/-ms-filter",
syntax: "<-ms-filter-function-progid> | <-ms-filter-function-legacy>"
},
"-ms-filter-function-progid": {
comment: "https://developer.mozilla.org/en-US/docs/Web/CSS/-ms-filter",
syntax: "'progid:' [ <ident-token> '.' ]* [ <ident-token> | <function-token> <any-value>? ) ]"
},
"-ms-filter-function-legacy": {
comment: "https://developer.mozilla.org/en-US/docs/Web/CSS/-ms-filter",
syntax: "<ident-token> | <function-token> <any-value>? )"
},
"-ms-filter": {
syntax: "<string>"
},
age: {
comment: "https://www.w3.org/TR/css3-speech/#voice-family",
syntax: "child | young | old"
},
"attr-name": {
syntax: "<wq-name>"
},
"attr-fallback": {
syntax: "<any-value>"
},
"bg-clip": {
comment: "missed, https://drafts.csswg.org/css-backgrounds-4/#typedef-bg-clip",
syntax: "<box> | border | text"
},
bottom: {
comment: "missed; not sure we should add it, but no others except `shape` is using it so it's ok for now; https://drafts.fxtf.org/css-masking-1/#funcdef-clip-rect",
syntax: "<length> | auto"
},
"content-list": {
comment: "added attr(), see https://github.com/csstree/csstree/issues/201",
syntax: "[ <string> | contents | <image> | <counter> | <quote> | <target> | <leader()> | <attr()> ]+"
},
"element()": {
comment: "https://drafts.csswg.org/css-gcpm/#element-syntax & https://drafts.csswg.org/css-images-4/#element-notation",
syntax: "element( <custom-ident> , [ first | start | last | first-except ]? ) | element( <id-selector> )"
},
"generic-voice": {
comment: "https://www.w3.org/TR/css3-speech/#voice-family",
syntax: "[ <age>? <gender> <integer>? ]"
},
gender: {
comment: "https://www.w3.org/TR/css3-speech/#voice-family",
syntax: "male | female | neutral"
},
"generic-family": {
comment: "added -apple-system",
references: [
"https://webkit.org/blog/3709/using-the-system-font-in-web-content/"
],
syntax: "| -apple-system"
},
gradient: {
comment: "added legacy syntaxes support",
syntax: "| <-legacy-gradient>"
},
left: {
comment: "missed; not sure we should add it, but no others except `shape` is using it so it's ok for now; https://drafts.fxtf.org/css-masking-1/#funcdef-clip-rect",
syntax: "<length> | auto"
},
"mask-image": {
comment: "missed; https://drafts.fxtf.org/css-masking-1/#the-mask-image",
syntax: "<mask-reference>#"
},
"named-color": {
comment: "added non standard color names",
syntax: "| <-non-standard-color>"
},
paint: {
comment: "used by SVG https://www.w3.org/TR/SVG/painting.html#SpecifyingPaint",
syntax: "none | <color> | <url> [ none | <color> ]? | context-fill | context-stroke"
},
right: {
comment: "missed; not sure we should add it, but no others except `shape` is using it so it's ok for now; https://drafts.fxtf.org/css-masking-1/#funcdef-clip-rect",
syntax: "<length> | auto"
},
shape: {
comment: "missed spaces in function body and add backwards compatible syntax",
syntax: "rect( <top>, <right>, <bottom>, <left> ) | rect( <top> <right> <bottom> <left> )"
},
"scroll-timeline-axis": {
comment: "missed definition",
syntax: "block | inline | vertical | horizontal"
},
"scroll-timeline-name": {
comment: "missed definition",
references: [
"https://w3c.github.io/csswg-drafts/scroll-animations/#propdef-scroll-timeline-name"
],
syntax: "none | <custom-ident>"
},
"single-animation-composition": {
comment: "missed definition",
references: [
"https://w3c.github.io/csswg-drafts/css-animations-2/#typedef-single-animation-composition"
],
syntax: "replace | add | accumulate"
},
"svg-length": {
comment: "All coordinates and lengths in SVG can be specified with or without a unit identifier",
references: [
"https://www.w3.org/TR/SVG11/coords.html#Units"
],
syntax: "<percentage> | <length> | <number>"
},
"svg-writing-mode": {
comment: "SVG specific keywords (deprecated for CSS)",
references: [
"https://developer.mozilla.org/en/docs/Web/CSS/writing-mode",
"https://www.w3.org/TR/SVG/text.html#WritingModeProperty"
],
syntax: "lr-tb | rl-tb | tb-rl | lr | rl | tb"
},
top: {
comment: "missed; not sure we should add it, but no others except `shape` is using it so it's ok for now; https://drafts.fxtf.org/css-masking-1/#funcdef-clip-rect",
syntax: "<length> | auto"
},
x: {
comment: "missed; not sure we should add it, but no others except `cursor` is using it so it's ok for now; https://drafts.csswg.org/css-ui-3/#cursor",
syntax: "<number>"
},
y: {
comment: "missed; not sure we should add it, but no others except `cursor` is using so it's ok for now; https://drafts.csswg.org/css-ui-3/#cursor",
syntax: "<number>"
},
declaration: {
comment: "missed, restored by https://drafts.csswg.org/css-syntax",
syntax: "<ident-token> : <declaration-value>? [ '!' important ]?"
},
"declaration-list": {
comment: "missed, restored by https://drafts.csswg.org/css-syntax",
syntax: "[ <declaration>? ';' ]* <declaration>?"
},
url: {
comment: "https://drafts.csswg.org/css-values-4/#urls",
syntax: "url( <string> <url-modifier>* ) | <url-token>"
},
"url-modifier": {
comment: "https://drafts.csswg.org/css-values-4/#typedef-url-modifier",
syntax: "<ident> | <function-token> <any-value> )"
},
"number-zero-one": {
syntax: "<number [0,1]>"
},
"number-one-or-greater": {
syntax: "<number [1,∞]>"
},
"-non-standard-display": {
syntax: "-ms-inline-flexbox | -ms-grid | -ms-inline-grid | -webkit-flex | -webkit-inline-flex | -webkit-box | -webkit-inline-box | -moz-inline-stack | -moz-box | -moz-inline-box"
}
};
const require$$0$4 = {
atrules: atrules$1,
properties: properties$2,
types: types$1z
};
const patch$2 = require$$0$4;
const patch$1$1 = patch$2;
var dataPatch$3 = patch$1$1;
const require$$1$1 = {
"@charset": {
syntax: "@charset \"<charset>\";",
groups: [
"CSS Charsets"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@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}",
interfaces: [
"CSSCounterStyleRule"
],
groups: [
"CSS Counter Styles"
],
descriptors: {
"additive-symbols": {
syntax: "[ <integer> && <symbol> ]#",
media: "all",
initial: "n/a (required)",
percentages: "no",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard"
},
fallback: {
syntax: "<counter-style-name>",
media: "all",
initial: "decimal",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
negative: {
syntax: "<symbol> <symbol>?",
media: "all",
initial: "\"-\" hyphen-minus",
percentages: "no",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard"
},
pad: {
syntax: "<integer> && <symbol>",
media: "all",
initial: "0 \"\"",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
prefix: {
syntax: "<symbol>",
media: "all",
initial: "\"\"",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
range: {
syntax: "[ [ <integer> | infinite ]{2} ]# | auto",
media: "all",
initial: "auto",
percentages: "no",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard"
},
"speak-as": {
syntax: "auto | bullets | numbers | words | spell-out | <counter-style-name>",
media: "all",
initial: "auto",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
suffix: {
syntax: "<symbol>",
media: "all",
initial: "\". \"",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
symbols: {
syntax: "<symbol>+",
media: "all",
initial: "n/a (required)",
percentages: "no",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard"
},
system: {
syntax: "cyclic | numeric | alphabetic | symbolic | additive | [ fixed <integer>? ] | [ extends <counter-style-name> ]",
media: "all",
initial: "symbolic",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
}
},
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@counter-style"
},
"@document": {
syntax: "@document [ <url> | url-prefix(<string>) | domain(<string>) | media-document(<string>) | regexp(<string>) ]# {\n <group-rule-body>\n}",
interfaces: [
"CSSGroupingRule",
"CSSConditionRule"
],
groups: [
"CSS Conditional Rules"
],
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@document"
},
"@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}",
interfaces: [
"CSSFontFaceRule"
],
groups: [
"CSS Fonts"
],
descriptors: {
"ascent-override": {
syntax: "normal | <percentage>",
media: "all",
initial: "normal",
percentages: "asSpecified",
computed: "asSpecified",
order: "orderOfAppearance",
status: "experimental"
},
"descent-override": {
syntax: "normal | <percentage>",
media: "all",
initial: "normal",
percentages: "asSpecified",
computed: "asSpecified",
order: "orderOfAppearance",
status: "experimental"
},
"font-display": {
syntax: "[ auto | block | swap | fallback | optional ]",
media: "visual",
percentages: "no",
initial: "auto",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental"
},
"font-family": {
syntax: "<family-name>",
media: "all",
initial: "n/a (required)",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
"font-feature-settings": {
syntax: "normal | <feature-tag-value>#",
media: "all",
initial: "normal",
percentages: "no",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard"
},
"font-variation-settings": {
syntax: "normal | [ <string> <number> ]#",
media: "all",
initial: "normal",
percentages: "no",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard"
},
"font-stretch": {
syntax: "<font-stretch-absolute>{1,2}",
media: "all",
initial: "normal",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
"font-style": {
syntax: "normal | italic | oblique <angle>{0,2}",
media: "all",
initial: "normal",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
"font-weight": {
syntax: "<font-weight-absolute>{1,2}",
media: "all",
initial: "normal",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
"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 ]",
media: "all",
initial: "normal",
percentages: "no",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard"
},
"line-gap-override": {
syntax: "normal | <percentage>",
media: "all",
initial: "normal",
percentages: "asSpecified",
computed: "asSpecified",
order: "orderOfAppearance",
status: "experimental"
},
"size-adjust": {
syntax: "<percentage>",
media: "all",
initial: "100%",
percentages: "asSpecified",
computed: "asSpecified",
order: "orderOfAppearance",
status: "experimental"
},
src: {
syntax: "[ <url> [ format( <string># ) ]? | local( <family-name> ) ]#",
media: "all",
initial: "n/a (required)",
percentages: "no",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard"
},
"unicode-range": {
syntax: "<unicode-range>#",
media: "all",
initial: "U+0-10FFFF",
percentages: "no",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard"
}
},
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@font-face"
},
"@font-feature-values": {
syntax: "@font-feature-values <family-name># {\n <feature-value-block-list>\n}",
interfaces: [
"CSSFontFeatureValuesRule"
],
groups: [
"CSS Fonts"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@font-feature-values"
},
"@import": {
syntax: "@import [ <string> | <url> ]\n [ layer | layer(<layer-name>) ]?\n [ supports( [ <supports-condition> | <declaration> ] ) ]?\n <media-query-list>? ;",
groups: [
"CSS Conditional Rules",
"Media Queries"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@import"
},
"@keyframes": {
syntax: "@keyframes <keyframes-name> {\n <keyframe-block-list>\n}",
interfaces: [
"CSSKeyframeRule",
"CSSKeyframesRule"
],
groups: [
"CSS Animations"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@keyframes"
},
"@layer": {
syntax: "@layer [ <layer-name># | <layer-name>? {\n <stylesheet>\n} ]",
interfaces: [
"CSSLayerBlockRule",
"CSSLayerStatementRule"
],
groups: [
"CSS Cascading and Inheritance"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@layer"
},
"@media": {
syntax: "@media <media-query-list> {\n <group-rule-body>\n}",
interfaces: [
"CSSGroupingRule",
"CSSConditionRule",
"CSSMediaRule",
"CSSCustomMediaRule"
],
groups: [
"CSS Conditional Rules",
"Media Queries"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@media"
},
"@namespace": {
syntax: "@namespace <namespace-prefix>? [ <string> | <url> ];",
groups: [
"CSS Namespaces"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@namespace"
},
"@page": {
syntax: "@page <page-selector-list> {\n <page-body>\n}",
interfaces: [
"CSSPageRule"
],
groups: [
"CSS Pages"
],
descriptors: {
bleed: {
syntax: "auto | <length>",
media: [
"visual",
"paged"
],
initial: "auto",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
marks: {
syntax: "none | [ crop || cross ]",
media: [
"visual",
"paged"
],
initial: "none",
percentages: "no",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard"
},
size: {
syntax: "<length>{1,2} | auto | [ <page-size> || [ portrait | landscape ] ]",
media: [
"visual",
"paged"
],
initial: "auto",
percentages: "no",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "orderOfAppearance",
status: "standard"
}
},
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@page"
},
"@property": {
syntax: "@property <custom-property-name> {\n <declaration-list>\n}",
interfaces: [
"CSS",
"CSSPropertyRule"
],
groups: [
"CSS Houdini"
],
descriptors: {
syntax: {
syntax: "<string>",
media: "all",
percentages: "no",
initial: "n/a (required)",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental"
},
inherits: {
syntax: "true | false",
media: "all",
percentages: "no",
initial: "auto",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental"
},
"initial-value": {
syntax: "<string>",
media: "all",
initial: "n/a (required)",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental"
}
},
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@property"
},
"@scroll-timeline": {
syntax: "@scroll-timeline <timeline-name> { <declaration-list> }",
interfaces: [
"ScrollTimeline"
],
groups: [
"CSS Animations"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@scroll-timeline"
},
"@supports": {
syntax: "@supports <supports-condition> {\n <group-rule-body>\n}",
interfaces: [
"CSSGroupingRule",
"CSSConditionRule",
"CSSSupportsRule"
],
groups: [
"CSS Conditional Rules"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@supports"
},
"@viewport": {
syntax: "@viewport {\n <group-rule-body>\n}",
interfaces: [
"CSSViewportRule"
],
groups: [
"CSS Device Adaptation"
],
descriptors: {
height: {
syntax: "<viewport-length>{1,2}",
media: [
"visual",
"continuous"
],
initial: [
"min-height",
"max-height"
],
percentages: [
"min-height",
"max-height"
],
computed: [
"min-height",
"max-height"
],
order: "orderOfAppearance",
status: "standard"
},
"max-height": {
syntax: "<viewport-length>",
media: [
"visual",
"continuous"
],
initial: "auto",
percentages: "referToHeightOfInitialViewport",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard"
},
"max-width": {
syntax: "<viewport-length>",
media: [
"visual",
"continuous"
],
initial: "auto",
percentages: "referToWidthOfInitialViewport",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard"
},
"max-zoom": {
syntax: "auto | <number> | <percentage>",
media: [
"visual",
"continuous"
],
initial: "auto",
percentages: "the zoom factor itself",
computed: "autoNonNegativeOrPercentage",
order: "uniqueOrder",
status: "standard"
},
"min-height": {
syntax: "<viewport-length>",
media: [
"visual",
"continuous"
],
initial: "auto",
percentages: "referToHeightOfInitialViewport",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard"
},
"min-width": {
syntax: "<viewport-length>",
media: [
"visual",
"continuous"
],
initial: "auto",
percentages: "referToWidthOfInitialViewport",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard"
},
"min-zoom": {
syntax: "auto | <number> | <percentage>",
media: [
"visual",
"continuous"
],
initial: "auto",
percentages: "the zoom factor itself",
computed: "autoNonNegativeOrPercentage",
order: "uniqueOrder",
status: "standard"
},
orientation: {
syntax: "auto | portrait | landscape",
media: [
"visual",
"continuous"
],
initial: "auto",
percentages: "referToSizeOfBoundingBox",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
"user-zoom": {
syntax: "zoom | fixed",
media: [
"visual",
"continuous"
],
initial: "zoom",
percentages: "referToSizeOfBoundingBox",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
"viewport-fit": {
syntax: "auto | contain | cover",
media: [
"visual",
"continuous"
],
initial: "auto",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
width: {
syntax: "<viewport-length>{1,2}",
media: [
"visual",
"continuous"
],
initial: [
"min-width",
"max-width"
],
percentages: [
"min-width",
"max-width"
],
computed: [
"min-width",
"max-width"
],
order: "orderOfAppearance",
status: "standard"
},
zoom: {
syntax: "auto | <number> | <percentage>",
media: [
"visual",
"continuous"
],
initial: "auto",
percentages: "the zoom factor itself",
computed: "autoNonNegativeOrPercentage",
order: "uniqueOrder",
status: "standard"
}
},
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@viewport"
}
};
const all$1 = {
syntax: "initial | inherit | unset | revert | revert-layer",
media: "noPracticalMedia",
inherited: false,
animationType: "eachOfShorthandPropertiesExceptUnicodeBiDiAndDirection",
percentages: "no",
groups: [
"CSS Miscellaneous"
],
initial: "noPracticalInitialValue",
appliesto: "allElements",
computed: "asSpecifiedAppliesToEachProperty",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/all"
};
const animation$1 = {
syntax: "<single-animation>#",
media: "visual",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: [
"animation-name",
"animation-duration",
"animation-timing-function",
"animation-delay",
"animation-iteration-count",
"animation-direction",
"animation-fill-mode",
"animation-play-state",
"animation-timeline"
],
appliesto: "allElementsAndPseudos",
computed: [
"animation-name",
"animation-duration",
"animation-timing-function",
"animation-delay",
"animation-direction",
"animation-iteration-count",
"animation-fill-mode",
"animation-play-state",
"animation-timeline"
],
order: "orderOfAppearance",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/animation"
};
const appearance$1 = {
syntax: "none | auto | textfield | menulist-button | <compat-auto>",
media: "all",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/appearance"
};
const azimuth$1 = {
syntax: "<angle> | [ [ left-side | far-left | left | center-left | center | center-right | right | far-right | right-side ] || behind ] | leftwards | rightwards",
media: "aural",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Speech"
],
initial: "center",
appliesto: "allElements",
computed: "normalizedAngle",
order: "orderOfAppearance",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/azimuth"
};
const background$3 = {
syntax: "[ <bg-layer> , ]* <final-bg-layer>",
media: "visual",
inherited: false,
animationType: [
"background-color",
"background-image",
"background-clip",
"background-position",
"background-size",
"background-repeat",
"background-attachment"
],
percentages: [
"background-position",
"background-size"
],
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"background-image",
"background-position",
"background-size",
"background-repeat",
"background-origin",
"background-clip",
"background-attachment",
"background-color"
],
appliesto: "allElements",
computed: [
"background-image",
"background-position",
"background-size",
"background-repeat",
"background-origin",
"background-clip",
"background-attachment",
"background-color"
],
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background"
};
const border$3 = {
syntax: "<line-width> || <line-style> || <color>",
media: "visual",
inherited: false,
animationType: [
"border-color",
"border-style",
"border-width"
],
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"border-width",
"border-style",
"border-color"
],
appliesto: "allElements",
computed: [
"border-width",
"border-style",
"border-color"
],
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border"
};
const bottom$1 = {
syntax: "<length> | <percentage> | auto",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToContainingBlockHeight",
groups: [
"CSS Positioning"
],
initial: "auto",
appliesto: "positionedElements",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/bottom"
};
const caret = {
syntax: "<'caret-color'> || <'caret-shape'>",
media: "interactive",
inherited: true,
animationType: [
"caret-color",
"caret-shape"
],
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: [
"caret-color",
"caret-shape"
],
appliesto: "elementsThatAcceptInput",
computed: [
"caret-color",
"caret-shape"
],
order: "perGrammar",
status: "standard"
};
const clear$1 = {
syntax: "none | left | right | both | inline-start | inline-end",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Positioning"
],
initial: "none",
appliesto: "blockLevelElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/clear"
};
const clip$1 = {
syntax: "<shape> | auto",
media: "visual",
inherited: false,
animationType: "rectangle",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "auto",
appliesto: "absolutelyPositionedElements",
computed: "autoOrRectangle",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/clip"
};
const color$5 = {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Color"
],
initial: "canvastext",
appliesto: "allElementsAndText",
computed: "computedColor",
order: "perGrammar",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/color"
};
const columns$1 = {
syntax: "<'column-width'> || <'column-count'>",
media: "visual",
inherited: false,
animationType: [
"column-width",
"column-count"
],
percentages: "no",
groups: [
"CSS Columns"
],
initial: [
"column-width",
"column-count"
],
appliesto: "blockContainersExceptTableWrappers",
computed: [
"column-width",
"column-count"
],
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/columns"
};
const contain$1 = {
syntax: "none | strict | content | [ [ size || inline-size ] || layout || style || paint ]",
media: "all",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Containment"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/contain"
};
const content$1 = {
syntax: "normal | none | [ <content-replacement> | <content-list> ] [/ [ <string> | <counter> ]+ ]?",
media: "all",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Generated Content"
],
initial: "normal",
appliesto: "allElementsTreeAbidingPseudoElementsPageMarginBoxes",
computed: "normalOnElementsForPseudosNoneAbsoluteURIStringOrAsSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/content"
};
const cursor$1 = {
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 ] ]",
media: [
"visual",
"interactive"
],
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecifiedURLsAbsolute",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/cursor"
};
const direction$1 = {
syntax: "ltr | rtl",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Writing Modes"
],
initial: "ltr",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/direction"
};
const display$1 = {
syntax: "[ <display-outside> || <display-inside> ] | <display-listitem> | <display-internal> | <display-box> | <display-legacy>",
media: "all",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Display"
],
initial: "inline",
appliesto: "allElements",
computed: "asSpecifiedExceptPositionedFloatingAndRootElementsKeywordMaybeDifferent",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/display"
};
const filter$1 = {
syntax: "none | <filter-function-list>",
media: "visual",
inherited: false,
animationType: "filterList",
percentages: "no",
groups: [
"Filter Effects"
],
initial: "none",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/filter"
};
const flex$1 = {
syntax: "none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]",
media: "visual",
inherited: false,
animationType: [
"flex-grow",
"flex-shrink",
"flex-basis"
],
percentages: "no",
groups: [
"CSS Flexible Box Layout"
],
initial: [
"flex-grow",
"flex-shrink",
"flex-basis"
],
appliesto: "flexItemsAndInFlowPseudos",
computed: [
"flex-grow",
"flex-shrink",
"flex-basis"
],
order: "orderOfAppearance",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/flex"
};
const float$1 = {
syntax: "left | right | none | inline-start | inline-end",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Positioning"
],
initial: "none",
appliesto: "allElementsNoEffectIfDisplayNone",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/float"
};
const font$3 = {
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",
media: "visual",
inherited: true,
animationType: [
"font-style",
"font-variant",
"font-weight",
"font-stretch",
"font-size",
"line-height",
"font-family"
],
percentages: [
"font-size",
"line-height"
],
groups: [
"CSS Fonts"
],
initial: [
"font-style",
"font-variant",
"font-weight",
"font-stretch",
"font-size",
"line-height",
"font-family"
],
appliesto: "allElements",
computed: [
"font-style",
"font-variant",
"font-weight",
"font-stretch",
"font-size",
"line-height",
"font-family"
],
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font"
};
const gap$1 = {
syntax: "<'row-gap'> <'column-gap'>?",
media: "visual",
inherited: false,
animationType: [
"row-gap",
"column-gap"
],
percentages: "no",
groups: [
"CSS Box Alignment"
],
initial: [
"row-gap",
"column-gap"
],
appliesto: "multiColumnElementsFlexContainersGridContainers",
computed: [
"row-gap",
"column-gap"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/gap"
};
const grid$1 = {
syntax: "<'grid-template'> | <'grid-template-rows'> / [ auto-flow && dense? ] <'grid-auto-columns'>? | [ auto-flow && dense? ] <'grid-auto-rows'>? / <'grid-template-columns'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: [
"grid-template-rows",
"grid-template-columns",
"grid-auto-rows",
"grid-auto-columns"
],
groups: [
"CSS Grid Layout"
],
initial: [
"grid-template-rows",
"grid-template-columns",
"grid-template-areas",
"grid-auto-rows",
"grid-auto-columns",
"grid-auto-flow",
"grid-column-gap",
"grid-row-gap",
"column-gap",
"row-gap"
],
appliesto: "gridContainers",
computed: [
"grid-template-rows",
"grid-template-columns",
"grid-template-areas",
"grid-auto-rows",
"grid-auto-columns",
"grid-auto-flow",
"grid-column-gap",
"grid-row-gap",
"column-gap",
"row-gap"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid"
};
const height$1 = {
syntax: "auto | <length> | <percentage> | min-content | max-content | fit-content | fit-content(<length-percentage>)",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "regardingHeightOfGeneratedBoxContainingBlockPercentagesRelativeToContainingBlock",
groups: [
"CSS Box Model"
],
initial: "auto",
appliesto: "allElementsButNonReplacedAndTableColumns",
computed: "percentageAutoOrAbsoluteLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/height"
};
const hyphens$1 = {
syntax: "none | manual | auto",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "manual",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/hyphens"
};
const inset$1 = {
syntax: "<'top'>{1,4}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "logicalHeightOrWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: [
"top",
"bottom",
"left",
"right"
],
appliesto: "positionedElements",
computed: [
"top",
"bottom",
"left",
"right"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/inset"
};
const isolation$1 = {
syntax: "auto | isolate",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Compositing and Blending"
],
initial: "auto",
appliesto: "allElementsSVGContainerGraphicsAndGraphicsReferencingElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/isolation"
};
const left$1 = {
syntax: "<length> | <percentage> | auto",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Positioning"
],
initial: "auto",
appliesto: "positionedElements",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/left"
};
const margin$1 = {
syntax: "[ <length> | <percentage> | auto ]{1,4}",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: [
"margin-bottom",
"margin-left",
"margin-right",
"margin-top"
],
appliesto: "allElementsExceptTableDisplayTypes",
computed: [
"margin-bottom",
"margin-left",
"margin-right",
"margin-top"
],
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin"
};
const mask$1 = {
syntax: "<mask-layer>#",
media: "visual",
inherited: false,
animationType: [
"mask-image",
"mask-mode",
"mask-repeat",
"mask-position",
"mask-clip",
"mask-origin",
"mask-size",
"mask-composite"
],
percentages: [
"mask-position"
],
groups: [
"CSS Masking"
],
initial: [
"mask-image",
"mask-mode",
"mask-repeat",
"mask-position",
"mask-clip",
"mask-origin",
"mask-size",
"mask-composite"
],
appliesto: "allElementsSVGContainerElements",
computed: [
"mask-image",
"mask-mode",
"mask-repeat",
"mask-position",
"mask-clip",
"mask-origin",
"mask-size",
"mask-composite"
],
order: "perGrammar",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask"
};
const offset$1 = {
syntax: "[ <'offset-position'>? [ <'offset-path'> [ <'offset-distance'> || <'offset-rotate'> ]? ]? ]! [ / <'offset-anchor'> ]?",
media: "visual",
inherited: false,
animationType: [
"offset-position",
"offset-path",
"offset-distance",
"offset-anchor",
"offset-rotate"
],
percentages: [
"offset-position",
"offset-distance",
"offset-anchor"
],
groups: [
"CSS Motion Path"
],
initial: [
"offset-position",
"offset-path",
"offset-distance",
"offset-anchor",
"offset-rotate"
],
appliesto: "transformableElements",
computed: [
"offset-position",
"offset-path",
"offset-distance",
"offset-anchor",
"offset-rotate"
],
order: "perGrammar",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/offset"
};
const opacity$1 = {
syntax: "<alpha-value>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "mapToRange0To1",
groups: [
"CSS Color"
],
initial: "1",
appliesto: "allElements",
computed: "specifiedValueNumberClipped0To1",
order: "perGrammar",
alsoAppliesTo: [
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/opacity"
};
const order$1 = {
syntax: "<integer>",
media: "visual",
inherited: false,
animationType: "integer",
percentages: "no",
groups: [
"CSS Flexible Box Layout"
],
initial: "0",
appliesto: "flexItemsGridItemsAbsolutelyPositionedContainerChildren",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/order"
};
const orphans$1 = {
syntax: "<integer>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fragmentation"
],
initial: "2",
appliesto: "blockContainerElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/orphans"
};
const outline$1 = {
syntax: "[ <'outline-color'> || <'outline-style'> || <'outline-width'> ]",
media: [
"visual",
"interactive"
],
inherited: false,
animationType: [
"outline-color",
"outline-width",
"outline-style"
],
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: [
"outline-color",
"outline-style",
"outline-width"
],
appliesto: "allElements",
computed: [
"outline-color",
"outline-width",
"outline-style"
],
order: "orderOfAppearance",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/outline"
};
const overflow$1 = {
syntax: "[ visible | hidden | clip | scroll | auto ]{1,2}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Overflow"
],
initial: "visible",
appliesto: "blockContainersFlexContainersGridContainers",
computed: [
"overflow-x",
"overflow-y"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/overflow"
};
const padding$1 = {
syntax: "[ <length> | <percentage> ]{1,4}",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: [
"padding-bottom",
"padding-left",
"padding-right",
"padding-top"
],
appliesto: "allElementsExceptInternalTableDisplayTypes",
computed: [
"padding-bottom",
"padding-left",
"padding-right",
"padding-top"
],
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding"
};
const perspective$1 = {
syntax: "none | <length>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "no",
groups: [
"CSS Transforms"
],
initial: "none",
appliesto: "transformableElements",
computed: "absoluteLengthOrNone",
order: "uniqueOrder",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/perspective"
};
const position$3 = {
syntax: "static | relative | absolute | sticky | fixed",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Positioning"
],
initial: "static",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/position"
};
const quotes$1 = {
syntax: "none | auto | [ <string> <string> ]+",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Generated Content"
],
initial: "dependsOnUserAgent",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/quotes"
};
const resize$1 = {
syntax: "none | both | horizontal | vertical | block | inline",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "none",
appliesto: "elementsWithOverflowNotVisibleAndReplacedElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/resize"
};
const right$1 = {
syntax: "<length> | <percentage> | auto",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Positioning"
],
initial: "auto",
appliesto: "positionedElements",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/right"
};
const rotate$1 = {
syntax: "none | <angle> | [ x | y | z | <number>{3} ] && <angle>",
media: "visual",
inherited: false,
animationType: "transform",
percentages: "no",
groups: [
"CSS Transforms"
],
initial: "none",
appliesto: "transformableElements",
computed: "asSpecified",
order: "perGrammar",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/rotate"
};
const scale$1 = {
syntax: "none | <number>{1,3}",
media: "visual",
inherited: false,
animationType: "transform",
percentages: "no",
groups: [
"CSS Transforms"
],
initial: "none",
appliesto: "transformableElements",
computed: "asSpecified",
order: "perGrammar",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scale"
};
const top$1 = {
syntax: "<length> | <percentage> | auto",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToContainingBlockHeight",
groups: [
"CSS Positioning"
],
initial: "auto",
appliesto: "positionedElements",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/top"
};
const transform$1 = {
syntax: "none | <transform-list>",
media: "visual",
inherited: false,
animationType: "transform",
percentages: "referToSizeOfBoundingBox",
groups: [
"CSS Transforms"
],
initial: "none",
appliesto: "transformableElements",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/transform"
};
const transition$1 = {
syntax: "<single-transition>#",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Transitions"
],
initial: [
"transition-delay",
"transition-duration",
"transition-property",
"transition-timing-function"
],
appliesto: "allElementsAndPseudos",
computed: [
"transition-delay",
"transition-duration",
"transition-property",
"transition-timing-function"
],
order: "orderOfAppearance",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/transition"
};
const translate$1 = {
syntax: "none | <length-percentage> [ <length-percentage> <length>? ]?",
media: "visual",
inherited: false,
animationType: "transform",
percentages: "referToSizeOfBoundingBox",
groups: [
"CSS Transforms"
],
initial: "none",
appliesto: "transformableElements",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "perGrammar",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/translate"
};
const visibility$1 = {
syntax: "visible | hidden | collapse",
media: "visual",
inherited: true,
animationType: "visibility",
percentages: "no",
groups: [
"CSS Box Model"
],
initial: "visible",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/visibility"
};
const widows$1 = {
syntax: "<integer>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fragmentation"
],
initial: "2",
appliesto: "blockContainerElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/widows"
};
const width$1 = {
syntax: "auto | <length> | <percentage> | min-content | max-content | fit-content | fit-content(<length-percentage>)",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "auto",
appliesto: "allElementsButNonReplacedAndTableRows",
computed: "percentageAutoOrAbsoluteLength",
order: "lengthOrPercentageBeforeKeywordIfBothPresent",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/width"
};
const zoom$1 = {
syntax: "normal | reset | <number> | <percentage>",
media: "visual",
inherited: false,
animationType: "integer",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/zoom"
};
const require$$2$1 = {
"--*": {
syntax: "<declaration-value>",
media: "all",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Variables"
],
initial: "seeProse",
appliesto: "allElements",
computed: "asSpecifiedWithVarsSubstituted",
order: "perGrammar",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/--*"
},
"-ms-accelerator": {
syntax: "false | true",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "false",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-accelerator"
},
"-ms-block-progression": {
syntax: "tb | rl | bt | lr",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "tb",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-block-progression"
},
"-ms-content-zoom-chaining": {
syntax: "none | chained",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "none",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-content-zoom-chaining"
},
"-ms-content-zooming": {
syntax: "none | zoom",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "zoomForTheTopLevelNoneForTheRest",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-content-zooming"
},
"-ms-content-zoom-limit": {
syntax: "<'-ms-content-zoom-limit-min'> <'-ms-content-zoom-limit-max'>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: [
"-ms-content-zoom-limit-max",
"-ms-content-zoom-limit-min"
],
groups: [
"Microsoft Extensions"
],
initial: [
"-ms-content-zoom-limit-max",
"-ms-content-zoom-limit-min"
],
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: [
"-ms-content-zoom-limit-max",
"-ms-content-zoom-limit-min"
],
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-content-zoom-limit"
},
"-ms-content-zoom-limit-max": {
syntax: "<percentage>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "maxZoomFactor",
groups: [
"Microsoft Extensions"
],
initial: "400%",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-content-zoom-limit-max"
},
"-ms-content-zoom-limit-min": {
syntax: "<percentage>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "minZoomFactor",
groups: [
"Microsoft Extensions"
],
initial: "100%",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-content-zoom-limit-min"
},
"-ms-content-zoom-snap": {
syntax: "<'-ms-content-zoom-snap-type'> || <'-ms-content-zoom-snap-points'>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: [
"-ms-content-zoom-snap-type",
"-ms-content-zoom-snap-points"
],
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: [
"-ms-content-zoom-snap-type",
"-ms-content-zoom-snap-points"
],
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-content-zoom-snap"
},
"-ms-content-zoom-snap-points": {
syntax: "snapInterval( <percentage>, <percentage> ) | snapList( <percentage># )",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "snapInterval(0%, 100%)",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-content-zoom-snap-points"
},
"-ms-content-zoom-snap-type": {
syntax: "none | proximity | mandatory",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "none",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-content-zoom-snap-type"
},
"-ms-filter": {
syntax: "<string>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "\"\"",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-filter"
},
"-ms-flow-from": {
syntax: "[ none | <custom-ident> ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "none",
appliesto: "nonReplacedElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-flow-from"
},
"-ms-flow-into": {
syntax: "[ none | <custom-ident> ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "none",
appliesto: "iframeElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-flow-into"
},
"-ms-grid-columns": {
syntax: "none | <track-list> | <auto-track-list>",
media: "visual",
inherited: false,
animationType: "simpleListOfLpcDifferenceLpc",
percentages: "referToDimensionOfContentArea",
groups: [
"CSS Grid Layout"
],
initial: "none",
appliesto: "gridContainers",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-grid-columns"
},
"-ms-grid-rows": {
syntax: "none | <track-list> | <auto-track-list>",
media: "visual",
inherited: false,
animationType: "simpleListOfLpcDifferenceLpc",
percentages: "referToDimensionOfContentArea",
groups: [
"CSS Grid Layout"
],
initial: "none",
appliesto: "gridContainers",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-grid-rows"
},
"-ms-high-contrast-adjust": {
syntax: "auto | none",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-high-contrast-adjust"
},
"-ms-hyphenate-limit-chars": {
syntax: "auto | <integer>{1,3}",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-hyphenate-limit-chars"
},
"-ms-hyphenate-limit-lines": {
syntax: "no-limit | <integer>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "no-limit",
appliesto: "blockContainerElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-hyphenate-limit-lines"
},
"-ms-hyphenate-limit-zone": {
syntax: "<percentage> | <length>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "referToLineBoxWidth",
groups: [
"Microsoft Extensions"
],
initial: "0",
appliesto: "blockContainerElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-hyphenate-limit-zone"
},
"-ms-ime-align": {
syntax: "auto | after",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-ime-align"
},
"-ms-overflow-style": {
syntax: "auto | none | scrollbar | -ms-autohiding-scrollbar",
media: "interactive",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "auto",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-overflow-style"
},
"-ms-scrollbar-3dlight-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "dependsOnUserAgent",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scrollbar-3dlight-color"
},
"-ms-scrollbar-arrow-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "ButtonText",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scrollbar-arrow-color"
},
"-ms-scrollbar-base-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "dependsOnUserAgent",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scrollbar-base-color"
},
"-ms-scrollbar-darkshadow-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "ThreeDDarkShadow",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scrollbar-darkshadow-color"
},
"-ms-scrollbar-face-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "ThreeDFace",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scrollbar-face-color"
},
"-ms-scrollbar-highlight-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "ThreeDHighlight",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scrollbar-highlight-color"
},
"-ms-scrollbar-shadow-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "ThreeDDarkShadow",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scrollbar-shadow-color"
},
"-ms-scrollbar-track-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "Scrollbar",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scrollbar-track-color"
},
"-ms-scroll-chaining": {
syntax: "chained | none",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "chained",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-chaining"
},
"-ms-scroll-limit": {
syntax: "<'-ms-scroll-limit-x-min'> <'-ms-scroll-limit-y-min'> <'-ms-scroll-limit-x-max'> <'-ms-scroll-limit-y-max'>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: [
"-ms-scroll-limit-x-min",
"-ms-scroll-limit-y-min",
"-ms-scroll-limit-x-max",
"-ms-scroll-limit-y-max"
],
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: [
"-ms-scroll-limit-x-min",
"-ms-scroll-limit-y-min",
"-ms-scroll-limit-x-max",
"-ms-scroll-limit-y-max"
],
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-limit"
},
"-ms-scroll-limit-x-max": {
syntax: "auto | <length>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "auto",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-limit-x-max"
},
"-ms-scroll-limit-x-min": {
syntax: "<length>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "0",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-limit-x-min"
},
"-ms-scroll-limit-y-max": {
syntax: "auto | <length>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "auto",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-limit-y-max"
},
"-ms-scroll-limit-y-min": {
syntax: "<length>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "0",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-limit-y-min"
},
"-ms-scroll-rails": {
syntax: "none | railed",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "railed",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-rails"
},
"-ms-scroll-snap-points-x": {
syntax: "snapInterval( <length-percentage>, <length-percentage> ) | snapList( <length-percentage># )",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "snapInterval(0px, 100%)",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-snap-points-x"
},
"-ms-scroll-snap-points-y": {
syntax: "snapInterval( <length-percentage>, <length-percentage> ) | snapList( <length-percentage># )",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "snapInterval(0px, 100%)",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-snap-points-y"
},
"-ms-scroll-snap-type": {
syntax: "none | proximity | mandatory",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "none",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-snap-type"
},
"-ms-scroll-snap-x": {
syntax: "<'-ms-scroll-snap-type'> <'-ms-scroll-snap-points-x'>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: [
"-ms-scroll-snap-type",
"-ms-scroll-snap-points-x"
],
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: [
"-ms-scroll-snap-type",
"-ms-scroll-snap-points-x"
],
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-snap-x"
},
"-ms-scroll-snap-y": {
syntax: "<'-ms-scroll-snap-type'> <'-ms-scroll-snap-points-y'>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: [
"-ms-scroll-snap-type",
"-ms-scroll-snap-points-y"
],
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: [
"-ms-scroll-snap-type",
"-ms-scroll-snap-points-y"
],
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-snap-y"
},
"-ms-scroll-translation": {
syntax: "none | vertical-to-horizontal",
media: "interactive",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-translation"
},
"-ms-text-autospace": {
syntax: "none | ideograph-alpha | ideograph-numeric | ideograph-parenthesis | ideograph-space",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-text-autospace"
},
"-ms-touch-select": {
syntax: "grippers | none",
media: "interactive",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "grippers",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-touch-select"
},
"-ms-user-select": {
syntax: "none | element | text",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "text",
appliesto: "nonReplacedElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-user-select"
},
"-ms-wrap-flow": {
syntax: "auto | both | start | end | maximum | clear",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "auto",
appliesto: "blockLevelElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-wrap-flow"
},
"-ms-wrap-margin": {
syntax: "<length>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "0",
appliesto: "exclusionElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-wrap-margin"
},
"-ms-wrap-through": {
syntax: "wrap | none",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "wrap",
appliesto: "blockLevelElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-wrap-through"
},
"-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",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions",
"WebKit Extensions"
],
initial: "noneButOverriddenInUserAgentCSS",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/appearance"
},
"-moz-binding": {
syntax: "<url> | none",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "none",
appliesto: "allElementsExceptGeneratedContentOrPseudoElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-binding"
},
"-moz-border-bottom-colors": {
syntax: "<color>+ | none",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-border-bottom-colors"
},
"-moz-border-left-colors": {
syntax: "<color>+ | none",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-border-left-colors"
},
"-moz-border-right-colors": {
syntax: "<color>+ | none",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-border-right-colors"
},
"-moz-border-top-colors": {
syntax: "<color>+ | none",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-border-top-colors"
},
"-moz-context-properties": {
syntax: "none | [ fill | fill-opacity | stroke | stroke-opacity ]#",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "none",
appliesto: "allElementsThatCanReferenceImages",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-context-properties"
},
"-moz-float-edge": {
syntax: "border-box | content-box | margin-box | padding-box",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "content-box",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-float-edge"
},
"-moz-force-broken-image-icon": {
syntax: "0 | 1",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "0",
appliesto: "images",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-force-broken-image-icon"
},
"-moz-image-region": {
syntax: "<shape> | auto",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "auto",
appliesto: "xulImageElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-image-region"
},
"-moz-orient": {
syntax: "inline | block | horizontal | vertical",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "inline",
appliesto: "anyElementEffectOnProgressAndMeter",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-orient"
},
"-moz-outline-radius": {
syntax: "<outline-radius>{1,4} [ / <outline-radius>{1,4} ]?",
media: "visual",
inherited: false,
animationType: [
"-moz-outline-radius-topleft",
"-moz-outline-radius-topright",
"-moz-outline-radius-bottomright",
"-moz-outline-radius-bottomleft"
],
percentages: [
"-moz-outline-radius-topleft",
"-moz-outline-radius-topright",
"-moz-outline-radius-bottomright",
"-moz-outline-radius-bottomleft"
],
groups: [
"Mozilla Extensions"
],
initial: [
"-moz-outline-radius-topleft",
"-moz-outline-radius-topright",
"-moz-outline-radius-bottomright",
"-moz-outline-radius-bottomleft"
],
appliesto: "allElements",
computed: [
"-moz-outline-radius-topleft",
"-moz-outline-radius-topright",
"-moz-outline-radius-bottomright",
"-moz-outline-radius-bottomleft"
],
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-outline-radius"
},
"-moz-outline-radius-bottomleft": {
syntax: "<outline-radius>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"Mozilla Extensions"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-outline-radius-bottomleft"
},
"-moz-outline-radius-bottomright": {
syntax: "<outline-radius>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"Mozilla Extensions"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-outline-radius-bottomright"
},
"-moz-outline-radius-topleft": {
syntax: "<outline-radius>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"Mozilla Extensions"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-outline-radius-topleft"
},
"-moz-outline-radius-topright": {
syntax: "<outline-radius>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"Mozilla Extensions"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-outline-radius-topright"
},
"-moz-stack-sizing": {
syntax: "ignore | stretch-to-fit",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "stretch-to-fit",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-stack-sizing"
},
"-moz-text-blink": {
syntax: "none | blink",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-text-blink"
},
"-moz-user-focus": {
syntax: "ignore | normal | select-after | select-before | select-menu | select-same | select-all | none",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-user-focus"
},
"-moz-user-input": {
syntax: "auto | none | enabled | disabled",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-user-input"
},
"-moz-user-modify": {
syntax: "read-only | read-write | write-only",
media: "interactive",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "read-only",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-user-modify"
},
"-moz-window-dragging": {
syntax: "drag | no-drag",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "drag",
appliesto: "allElementsCreatingNativeWindows",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-window-dragging"
},
"-moz-window-shadow": {
syntax: "default | menu | tooltip | sheet | none",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "default",
appliesto: "allElementsCreatingNativeWindows",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-window-shadow"
},
"-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",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "noneButOverriddenInUserAgentCSS",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/appearance"
},
"-webkit-border-before": {
syntax: "<'border-width'> || <'border-style'> || <color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: [
"-webkit-border-before-width"
],
groups: [
"WebKit Extensions"
],
initial: [
"border-width",
"border-style",
"color"
],
appliesto: "allElements",
computed: [
"border-width",
"border-style",
"color"
],
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-border-before"
},
"-webkit-border-before-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
status: "nonstandard"
},
"-webkit-border-before-style": {
syntax: "<'border-style'>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard"
},
"-webkit-border-before-width": {
syntax: "<'border-width'>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "logicalWidthOfContainingBlock",
groups: [
"WebKit Extensions"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthZeroIfBorderStyleNoneOrHidden",
order: "uniqueOrder",
status: "nonstandard"
},
"-webkit-box-reflect": {
syntax: "[ above | below | right | left ]? <length>? <image>?",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-box-reflect"
},
"-webkit-line-clamp": {
syntax: "none | <integer>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"WebKit Extensions",
"CSS Overflow"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-line-clamp"
},
"-webkit-mask": {
syntax: "[ <mask-reference> || <position> [ / <bg-size> ]? || <repeat-style> || [ <box> | border | padding | content | text ] || [ <box> | border | padding | content ] ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: [
"-webkit-mask-image",
"-webkit-mask-repeat",
"-webkit-mask-attachment",
"-webkit-mask-position",
"-webkit-mask-origin",
"-webkit-mask-clip"
],
appliesto: "allElements",
computed: [
"-webkit-mask-image",
"-webkit-mask-repeat",
"-webkit-mask-attachment",
"-webkit-mask-position",
"-webkit-mask-origin",
"-webkit-mask-clip"
],
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask"
},
"-webkit-mask-attachment": {
syntax: "<attachment>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "scroll",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-mask-attachment"
},
"-webkit-mask-clip": {
syntax: "[ <box> | border | padding | content | text ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "border",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-clip"
},
"-webkit-mask-composite": {
syntax: "<composite-style>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "source-over",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-mask-composite"
},
"-webkit-mask-image": {
syntax: "<mask-reference>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "absoluteURIOrNone",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-image"
},
"-webkit-mask-origin": {
syntax: "[ <box> | border | padding | content ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "padding",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-origin"
},
"-webkit-mask-position": {
syntax: "<position>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "referToSizeOfElement",
groups: [
"WebKit Extensions"
],
initial: "0% 0%",
appliesto: "allElements",
computed: "absoluteLengthOrPercentage",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-position"
},
"-webkit-mask-position-x": {
syntax: "[ <length-percentage> | left | center | right ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "referToSizeOfElement",
groups: [
"WebKit Extensions"
],
initial: "0%",
appliesto: "allElements",
computed: "absoluteLengthOrPercentage",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-mask-position-x"
},
"-webkit-mask-position-y": {
syntax: "[ <length-percentage> | top | center | bottom ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "referToSizeOfElement",
groups: [
"WebKit Extensions"
],
initial: "0%",
appliesto: "allElements",
computed: "absoluteLengthOrPercentage",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-mask-position-y"
},
"-webkit-mask-repeat": {
syntax: "<repeat-style>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "repeat",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-repeat"
},
"-webkit-mask-repeat-x": {
syntax: "repeat | no-repeat | space | round",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "repeat",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-mask-repeat-x"
},
"-webkit-mask-repeat-y": {
syntax: "repeat | no-repeat | space | round",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "repeat",
appliesto: "allElements",
computed: "absoluteLengthOrPercentage",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-mask-repeat-y"
},
"-webkit-mask-size": {
syntax: "<bg-size>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "relativeToBackgroundPositioningArea",
groups: [
"WebKit Extensions"
],
initial: "auto auto",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-size"
},
"-webkit-overflow-scrolling": {
syntax: "auto | touch",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "auto",
appliesto: "scrollingBoxes",
computed: "asSpecified",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-overflow-scrolling"
},
"-webkit-tap-highlight-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "black",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-tap-highlight-color"
},
"-webkit-text-fill-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "color",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-text-fill-color"
},
"-webkit-text-stroke": {
syntax: "<length> || <color>",
media: "visual",
inherited: true,
animationType: [
"-webkit-text-stroke-width",
"-webkit-text-stroke-color"
],
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: [
"-webkit-text-stroke-width",
"-webkit-text-stroke-color"
],
appliesto: "allElements",
computed: [
"-webkit-text-stroke-width",
"-webkit-text-stroke-color"
],
order: "canonicalOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-text-stroke"
},
"-webkit-text-stroke-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "color",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-text-stroke-color"
},
"-webkit-text-stroke-width": {
syntax: "<length>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "0",
appliesto: "allElements",
computed: "absoluteLength",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-text-stroke-width"
},
"-webkit-touch-callout": {
syntax: "default | none",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "default",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-touch-callout"
},
"-webkit-user-modify": {
syntax: "read-only | read-write | read-write-plaintext-only",
media: "interactive",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "read-only",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard"
},
"accent-color": {
syntax: "auto | <color>",
media: "interactive",
inherited: true,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "auto",
appliesto: "allElements",
computed: "asAutoOrColor",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/accent-color"
},
"align-content": {
syntax: "normal | <baseline-position> | <content-distribution> | <overflow-position>? <content-position>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Alignment"
],
initial: "normal",
appliesto: "multilineFlexContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/align-content"
},
"align-items": {
syntax: "normal | stretch | <baseline-position> | [ <overflow-position>? <self-position> ]",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Alignment"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/align-items"
},
"align-self": {
syntax: "auto | normal | stretch | <baseline-position> | <overflow-position>? <self-position>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Alignment"
],
initial: "auto",
appliesto: "flexItemsGridItemsAndAbsolutelyPositionedBoxes",
computed: "autoOnAbsolutelyPositionedElementsValueOfAlignItemsOnParent",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/align-self"
},
"align-tracks": {
syntax: "[ normal | <baseline-position> | <content-distribution> | <overflow-position>? <content-position> ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: "normal",
appliesto: "gridContainersWithMasonryLayoutInTheirBlockAxis",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/align-tracks"
},
all: all$1,
animation: animation$1,
"animation-composition": {
syntax: "<single-animation-composition>#",
media: "visual",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: "replace",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/animation-composition"
},
"animation-delay": {
syntax: "<time>#",
media: "visual",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: "0s",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/animation-delay"
},
"animation-direction": {
syntax: "<single-animation-direction>#",
media: "visual",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: "normal",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/animation-direction"
},
"animation-duration": {
syntax: "<time>#",
media: "visual",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: "0s",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/animation-duration"
},
"animation-fill-mode": {
syntax: "<single-animation-fill-mode>#",
media: "visual",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: "none",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/animation-fill-mode"
},
"animation-iteration-count": {
syntax: "<single-animation-iteration-count>#",
media: "visual",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: "1",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/animation-iteration-count"
},
"animation-name": {
syntax: "[ none | <keyframes-name> ]#",
media: "visual",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: "none",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/animation-name"
},
"animation-play-state": {
syntax: "<single-animation-play-state>#",
media: "visual",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: "running",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/animation-play-state"
},
"animation-timing-function": {
syntax: "<easing-function>#",
media: "visual",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: "ease",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/animation-timing-function"
},
"animation-timeline": {
syntax: "<single-animation-timeline>#",
media: "visual",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: "auto",
appliesto: "allElements",
computed: "listEachItemIdentifyerOrNoneAuto",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/animation-timeline"
},
appearance: appearance$1,
"aspect-ratio": {
syntax: "auto | <ratio>",
media: "all",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "auto",
appliesto: "allElementsExceptInlineBoxesAndInternalRubyOrTableBoxes",
computed: "asSpecified",
order: "perGrammar",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/aspect-ratio"
},
azimuth: azimuth$1,
"backdrop-filter": {
syntax: "none | <filter-function-list>",
media: "visual",
inherited: false,
animationType: "filterList",
percentages: "no",
groups: [
"Filter Effects"
],
initial: "none",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/backdrop-filter"
},
"backface-visibility": {
syntax: "visible | hidden",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Transforms"
],
initial: "visible",
appliesto: "transformableElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/backface-visibility"
},
background: background$3,
"background-attachment": {
syntax: "<attachment>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "scroll",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-attachment"
},
"background-blend-mode": {
syntax: "<blend-mode>#",
media: "none",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Compositing and Blending"
],
initial: "normal",
appliesto: "allElementsSVGContainerGraphicsAndGraphicsReferencingElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-blend-mode"
},
"background-clip": {
syntax: "<box>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "border-box",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-clip"
},
"background-color": {
syntax: "<color>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "transparent",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-color"
},
"background-image": {
syntax: "<bg-image>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecifiedURLsAbsolute",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-image"
},
"background-origin": {
syntax: "<box>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "padding-box",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-origin"
},
"background-position": {
syntax: "<bg-position>#",
media: "visual",
inherited: false,
animationType: "repeatableListOfSimpleListOfLpc",
percentages: "referToSizeOfBackgroundPositioningAreaMinusBackgroundImageSize",
groups: [
"CSS Backgrounds and Borders"
],
initial: "0% 0%",
appliesto: "allElements",
computed: [
"background-position-x",
"background-position-y"
],
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-position"
},
"background-position-x": {
syntax: "[ center | [ [ left | right | x-start | x-end ]? <length-percentage>? ]! ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "referToWidthOfBackgroundPositioningAreaMinusBackgroundImageHeight",
groups: [
"CSS Backgrounds and Borders"
],
initial: "0%",
appliesto: "allElements",
computed: "listEachItemConsistingOfAbsoluteLengthPercentageAndOrigin",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-position-x"
},
"background-position-y": {
syntax: "[ center | [ [ top | bottom | y-start | y-end ]? <length-percentage>? ]! ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "referToHeightOfBackgroundPositioningAreaMinusBackgroundImageHeight",
groups: [
"CSS Backgrounds and Borders"
],
initial: "0%",
appliesto: "allElements",
computed: "listEachItemConsistingOfAbsoluteLengthPercentageAndOrigin",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-position-y"
},
"background-repeat": {
syntax: "<repeat-style>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "repeat",
appliesto: "allElements",
computed: "listEachItemHasTwoKeywordsOnePerDimension",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-repeat"
},
"background-size": {
syntax: "<bg-size>#",
media: "visual",
inherited: false,
animationType: "repeatableListOfSimpleListOfLpc",
percentages: "relativeToBackgroundPositioningArea",
groups: [
"CSS Backgrounds and Borders"
],
initial: "auto auto",
appliesto: "allElements",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-size"
},
"block-overflow": {
syntax: "clip | ellipsis | <string>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Overflow"
],
initial: "clip",
appliesto: "blockContainers",
computed: "asSpecified",
order: "perGrammar",
status: "experimental"
},
"block-size": {
syntax: "<'width'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "blockSizeOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "auto",
appliesto: "sameAsWidthAndHeight",
computed: "sameAsWidthAndHeight",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/block-size"
},
border: border$3,
"border-block": {
syntax: "<'border-top-width'> || <'border-top-style'> || <color>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: [
"border-top-width",
"border-top-style",
"border-top-color"
],
appliesto: "allElements",
computed: [
"border-top-width",
"border-top-style",
"border-top-color"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block"
},
"border-block-color": {
syntax: "<'border-top-color'>{1,2}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-color"
},
"border-block-style": {
syntax: "<'border-top-style'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-style"
},
"border-block-width": {
syntax: "<'border-top-width'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthZeroIfBorderStyleNoneOrHidden",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-width"
},
"border-block-end": {
syntax: "<'border-top-width'> || <'border-top-style'> || <color>",
media: "visual",
inherited: false,
animationType: [
"border-block-end-color",
"border-block-end-style",
"border-block-end-width"
],
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: [
"border-top-width",
"border-top-style",
"border-top-color"
],
appliesto: "allElements",
computed: [
"border-top-width",
"border-top-style",
"border-top-color"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-end"
},
"border-block-end-color": {
syntax: "<'border-top-color'>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-end-color"
},
"border-block-end-style": {
syntax: "<'border-top-style'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-end-style"
},
"border-block-end-width": {
syntax: "<'border-top-width'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthZeroIfBorderStyleNoneOrHidden",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-end-width"
},
"border-block-start": {
syntax: "<'border-top-width'> || <'border-top-style'> || <color>",
media: "visual",
inherited: false,
animationType: [
"border-block-start-color",
"border-block-start-style",
"border-block-start-width"
],
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: [
"border-width",
"border-style",
"color"
],
appliesto: "allElements",
computed: [
"border-width",
"border-style",
"border-block-start-color"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-start"
},
"border-block-start-color": {
syntax: "<'border-top-color'>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-start-color"
},
"border-block-start-style": {
syntax: "<'border-top-style'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-start-style"
},
"border-block-start-width": {
syntax: "<'border-top-width'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthZeroIfBorderStyleNoneOrHidden",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-start-width"
},
"border-bottom": {
syntax: "<line-width> || <line-style> || <color>",
media: "visual",
inherited: false,
animationType: [
"border-bottom-color",
"border-bottom-style",
"border-bottom-width"
],
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"border-bottom-width",
"border-bottom-style",
"border-bottom-color"
],
appliesto: "allElements",
computed: [
"border-bottom-width",
"border-bottom-style",
"border-bottom-color"
],
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-bottom"
},
"border-bottom-color": {
syntax: "<'border-top-color'>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-bottom-color"
},
"border-bottom-left-radius": {
syntax: "<length-percentage>{1,2}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"CSS Backgrounds and Borders"
],
initial: "0",
appliesto: "allElementsUAsNotRequiredWhenCollapse",
computed: "twoAbsoluteLengthOrPercentages",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-bottom-left-radius"
},
"border-bottom-right-radius": {
syntax: "<length-percentage>{1,2}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"CSS Backgrounds and Borders"
],
initial: "0",
appliesto: "allElementsUAsNotRequiredWhenCollapse",
computed: "twoAbsoluteLengthOrPercentages",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-bottom-right-radius"
},
"border-bottom-style": {
syntax: "<line-style>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-bottom-style"
},
"border-bottom-width": {
syntax: "<line-width>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthOr0IfBorderBottomStyleNoneOrHidden",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-bottom-width"
},
"border-collapse": {
syntax: "collapse | separate",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Table"
],
initial: "separate",
appliesto: "tableElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-collapse"
},
"border-color": {
syntax: "<color>{1,4}",
media: "visual",
inherited: false,
animationType: [
"border-bottom-color",
"border-left-color",
"border-right-color",
"border-top-color"
],
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"border-top-color",
"border-right-color",
"border-bottom-color",
"border-left-color"
],
appliesto: "allElements",
computed: [
"border-bottom-color",
"border-left-color",
"border-right-color",
"border-top-color"
],
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-color"
},
"border-end-end-radius": {
syntax: "<length-percentage>{1,2}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "allElementsUAsNotRequiredWhenCollapse",
computed: "twoAbsoluteLengthOrPercentages",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-end-end-radius"
},
"border-end-start-radius": {
syntax: "<length-percentage>{1,2}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "allElementsUAsNotRequiredWhenCollapse",
computed: "twoAbsoluteLengthOrPercentages",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-end-start-radius"
},
"border-image": {
syntax: "<'border-image-source'> || <'border-image-slice'> [ / <'border-image-width'> | / <'border-image-width'>? / <'border-image-outset'> ]? || <'border-image-repeat'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: [
"border-image-slice",
"border-image-width"
],
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"border-image-source",
"border-image-slice",
"border-image-width",
"border-image-outset",
"border-image-repeat"
],
appliesto: "allElementsExceptTableElementsWhenCollapse",
computed: [
"border-image-outset",
"border-image-repeat",
"border-image-slice",
"border-image-source",
"border-image-width"
],
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-image"
},
"border-image-outset": {
syntax: "[ <length> | <number> ]{1,4}",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "0",
appliesto: "allElementsExceptTableElementsWhenCollapse",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-image-outset"
},
"border-image-repeat": {
syntax: "[ stretch | repeat | round | space ]{1,2}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "stretch",
appliesto: "allElementsExceptTableElementsWhenCollapse",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-image-repeat"
},
"border-image-slice": {
syntax: "<number-percentage>{1,4} && fill?",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "referToSizeOfBorderImage",
groups: [
"CSS Backgrounds and Borders"
],
initial: "100%",
appliesto: "allElementsExceptTableElementsWhenCollapse",
computed: "oneToFourPercentagesOrAbsoluteLengthsPlusFill",
order: "percentagesOrLengthsFollowedByFill",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-image-slice"
},
"border-image-source": {
syntax: "none | <image>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "none",
appliesto: "allElementsExceptTableElementsWhenCollapse",
computed: "noneOrImageWithAbsoluteURI",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-image-source"
},
"border-image-width": {
syntax: "[ <length-percentage> | <number> | auto ]{1,4}",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "referToWidthOrHeightOfBorderImageArea",
groups: [
"CSS Backgrounds and Borders"
],
initial: "1",
appliesto: "allElementsExceptTableElementsWhenCollapse",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-image-width"
},
"border-inline": {
syntax: "<'border-top-width'> || <'border-top-style'> || <color>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: [
"border-top-width",
"border-top-style",
"border-top-color"
],
appliesto: "allElements",
computed: [
"border-top-width",
"border-top-style",
"border-top-color"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline"
},
"border-inline-end": {
syntax: "<'border-top-width'> || <'border-top-style'> || <color>",
media: "visual",
inherited: false,
animationType: [
"border-inline-end-color",
"border-inline-end-style",
"border-inline-end-width"
],
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: [
"border-width",
"border-style",
"color"
],
appliesto: "allElements",
computed: [
"border-width",
"border-style",
"border-inline-end-color"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-end"
},
"border-inline-color": {
syntax: "<'border-top-color'>{1,2}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-color"
},
"border-inline-style": {
syntax: "<'border-top-style'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-style"
},
"border-inline-width": {
syntax: "<'border-top-width'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthZeroIfBorderStyleNoneOrHidden",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-width"
},
"border-inline-end-color": {
syntax: "<'border-top-color'>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-end-color"
},
"border-inline-end-style": {
syntax: "<'border-top-style'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-end-style"
},
"border-inline-end-width": {
syntax: "<'border-top-width'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthZeroIfBorderStyleNoneOrHidden",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-end-width"
},
"border-inline-start": {
syntax: "<'border-top-width'> || <'border-top-style'> || <color>",
media: "visual",
inherited: false,
animationType: [
"border-inline-start-color",
"border-inline-start-style",
"border-inline-start-width"
],
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: [
"border-width",
"border-style",
"color"
],
appliesto: "allElements",
computed: [
"border-width",
"border-style",
"border-inline-start-color"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-start"
},
"border-inline-start-color": {
syntax: "<'border-top-color'>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-start-color"
},
"border-inline-start-style": {
syntax: "<'border-top-style'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-start-style"
},
"border-inline-start-width": {
syntax: "<'border-top-width'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthZeroIfBorderStyleNoneOrHidden",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-start-width"
},
"border-left": {
syntax: "<line-width> || <line-style> || <color>",
media: "visual",
inherited: false,
animationType: [
"border-left-color",
"border-left-style",
"border-left-width"
],
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"border-left-width",
"border-left-style",
"border-left-color"
],
appliesto: "allElements",
computed: [
"border-left-width",
"border-left-style",
"border-left-color"
],
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-left"
},
"border-left-color": {
syntax: "<color>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-left-color"
},
"border-left-style": {
syntax: "<line-style>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-left-style"
},
"border-left-width": {
syntax: "<line-width>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthOr0IfBorderLeftStyleNoneOrHidden",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-left-width"
},
"border-radius": {
syntax: "<length-percentage>{1,4} [ / <length-percentage>{1,4} ]?",
media: "visual",
inherited: false,
animationType: [
"border-top-left-radius",
"border-top-right-radius",
"border-bottom-right-radius",
"border-bottom-left-radius"
],
percentages: "referToDimensionOfBorderBox",
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"border-top-left-radius",
"border-top-right-radius",
"border-bottom-right-radius",
"border-bottom-left-radius"
],
appliesto: "allElementsUAsNotRequiredWhenCollapse",
computed: [
"border-bottom-left-radius",
"border-bottom-right-radius",
"border-top-left-radius",
"border-top-right-radius"
],
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-radius"
},
"border-right": {
syntax: "<line-width> || <line-style> || <color>",
media: "visual",
inherited: false,
animationType: [
"border-right-color",
"border-right-style",
"border-right-width"
],
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"border-right-width",
"border-right-style",
"border-right-color"
],
appliesto: "allElements",
computed: [
"border-right-width",
"border-right-style",
"border-right-color"
],
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-right"
},
"border-right-color": {
syntax: "<color>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-right-color"
},
"border-right-style": {
syntax: "<line-style>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-right-style"
},
"border-right-width": {
syntax: "<line-width>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthOr0IfBorderRightStyleNoneOrHidden",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-right-width"
},
"border-spacing": {
syntax: "<length> <length>?",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Table"
],
initial: "0",
appliesto: "tableElements",
computed: "twoAbsoluteLengths",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-spacing"
},
"border-start-end-radius": {
syntax: "<length-percentage>{1,2}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "allElementsUAsNotRequiredWhenCollapse",
computed: "twoAbsoluteLengthOrPercentages",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-start-end-radius"
},
"border-start-start-radius": {
syntax: "<length-percentage>{1,2}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "allElementsUAsNotRequiredWhenCollapse",
computed: "twoAbsoluteLengthOrPercentages",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-start-start-radius"
},
"border-style": {
syntax: "<line-style>{1,4}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"border-top-style",
"border-right-style",
"border-bottom-style",
"border-left-style"
],
appliesto: "allElements",
computed: [
"border-bottom-style",
"border-left-style",
"border-right-style",
"border-top-style"
],
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-style"
},
"border-top": {
syntax: "<line-width> || <line-style> || <color>",
media: "visual",
inherited: false,
animationType: [
"border-top-color",
"border-top-style",
"border-top-width"
],
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"border-top-width",
"border-top-style",
"border-top-color"
],
appliesto: "allElements",
computed: [
"border-top-width",
"border-top-style",
"border-top-color"
],
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-top"
},
"border-top-color": {
syntax: "<color>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-top-color"
},
"border-top-left-radius": {
syntax: "<length-percentage>{1,2}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"CSS Backgrounds and Borders"
],
initial: "0",
appliesto: "allElementsUAsNotRequiredWhenCollapse",
computed: "twoAbsoluteLengthOrPercentages",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-top-left-radius"
},
"border-top-right-radius": {
syntax: "<length-percentage>{1,2}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"CSS Backgrounds and Borders"
],
initial: "0",
appliesto: "allElementsUAsNotRequiredWhenCollapse",
computed: "twoAbsoluteLengthOrPercentages",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-top-right-radius"
},
"border-top-style": {
syntax: "<line-style>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-top-style"
},
"border-top-width": {
syntax: "<line-width>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthOr0IfBorderTopStyleNoneOrHidden",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-top-width"
},
"border-width": {
syntax: "<line-width>{1,4}",
media: "visual",
inherited: false,
animationType: [
"border-bottom-width",
"border-left-width",
"border-right-width",
"border-top-width"
],
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"border-top-width",
"border-right-width",
"border-bottom-width",
"border-left-width"
],
appliesto: "allElements",
computed: [
"border-bottom-width",
"border-left-width",
"border-right-width",
"border-top-width"
],
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-width"
},
bottom: bottom$1,
"box-align": {
syntax: "start | center | end | baseline | stretch",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions",
"WebKit Extensions"
],
initial: "stretch",
appliesto: "elementsWithDisplayBoxOrInlineBox",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-align"
},
"box-decoration-break": {
syntax: "slice | clone",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fragmentation"
],
initial: "slice",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-decoration-break"
},
"box-direction": {
syntax: "normal | reverse | inherit",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions",
"WebKit Extensions"
],
initial: "normal",
appliesto: "elementsWithDisplayBoxOrInlineBox",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-direction"
},
"box-flex": {
syntax: "<number>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions",
"WebKit Extensions"
],
initial: "0",
appliesto: "directChildrenOfElementsWithDisplayMozBoxMozInlineBox",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-flex"
},
"box-flex-group": {
syntax: "<integer>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions",
"WebKit Extensions"
],
initial: "1",
appliesto: "inFlowChildrenOfBoxElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-flex-group"
},
"box-lines": {
syntax: "single | multiple",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions",
"WebKit Extensions"
],
initial: "single",
appliesto: "boxElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-lines"
},
"box-ordinal-group": {
syntax: "<integer>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions",
"WebKit Extensions"
],
initial: "1",
appliesto: "childrenOfBoxElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-ordinal-group"
},
"box-orient": {
syntax: "horizontal | vertical | inline-axis | block-axis | inherit",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions",
"WebKit Extensions"
],
initial: "inlineAxisHorizontalInXUL",
appliesto: "elementsWithDisplayBoxOrInlineBox",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-orient"
},
"box-pack": {
syntax: "start | center | end | justify",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions",
"WebKit Extensions"
],
initial: "start",
appliesto: "elementsWithDisplayMozBoxMozInlineBox",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-pack"
},
"box-shadow": {
syntax: "none | <shadow>#",
media: "visual",
inherited: false,
animationType: "shadowList",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "none",
appliesto: "allElements",
computed: "absoluteLengthsSpecifiedColorAsSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-shadow"
},
"box-sizing": {
syntax: "content-box | border-box",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Model"
],
initial: "content-box",
appliesto: "allElementsAcceptingWidthOrHeight",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-sizing"
},
"break-after": {
syntax: "auto | avoid | always | all | avoid-page | page | left | right | recto | verso | avoid-column | column | avoid-region | region",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fragmentation"
],
initial: "auto",
appliesto: "blockLevelElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/break-after"
},
"break-before": {
syntax: "auto | avoid | always | all | avoid-page | page | left | right | recto | verso | avoid-column | column | avoid-region | region",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fragmentation"
],
initial: "auto",
appliesto: "blockLevelElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/break-before"
},
"break-inside": {
syntax: "auto | avoid | avoid-page | avoid-column | avoid-region",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fragmentation"
],
initial: "auto",
appliesto: "blockLevelElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/break-inside"
},
"caption-side": {
syntax: "top | bottom | block-start | block-end | inline-start | inline-end",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Table"
],
initial: "top",
appliesto: "tableCaptionElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/caption-side"
},
caret: caret,
"caret-color": {
syntax: "auto | <color>",
media: "interactive",
inherited: true,
animationType: "color",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "auto",
appliesto: "allElements",
computed: "asAutoOrColor",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/caret-color"
},
"caret-shape": {
syntax: "auto | bar | block | underscore",
media: "interactive",
inherited: true,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "auto",
appliesto: "elementsThatAcceptInput",
computed: "asSpecified",
order: "perGrammar",
status: "standard"
},
clear: clear$1,
clip: clip$1,
"clip-path": {
syntax: "<clip-source> | [ <basic-shape> || <geometry-box> ] | none",
media: "visual",
inherited: false,
animationType: "basicShapeOtherwiseNo",
percentages: "referToReferenceBoxWhenSpecifiedOtherwiseBorderBox",
groups: [
"CSS Masking"
],
initial: "none",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecifiedURLsAbsolute",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/clip-path"
},
color: color$5,
"print-color-adjust": {
syntax: "economy | exact",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Color"
],
initial: "economy",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/print-color-adjust"
},
"color-scheme": {
syntax: "normal | [ light | dark | <custom-ident> ]+ && only?",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Color"
],
initial: "normal",
appliesto: "allElementsAndText",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/color-scheme"
},
"column-count": {
syntax: "<integer> | auto",
media: "visual",
inherited: false,
animationType: "integer",
percentages: "no",
groups: [
"CSS Columns"
],
initial: "auto",
appliesto: "blockContainersExceptTableWrappers",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/column-count"
},
"column-fill": {
syntax: "auto | balance | balance-all",
media: "visualInContinuousMediaNoEffectInOverflowColumns",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Columns"
],
initial: "balance",
appliesto: "multicolElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/column-fill"
},
"column-gap": {
syntax: "normal | <length-percentage>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfContentArea",
groups: [
"CSS Box Alignment"
],
initial: "normal",
appliesto: "multiColumnElementsFlexContainersGridContainers",
computed: "asSpecifiedWithLengthsAbsoluteAndNormalComputingToZeroExceptMultiColumn",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/column-gap"
},
"column-rule": {
syntax: "<'column-rule-width'> || <'column-rule-style'> || <'column-rule-color'>",
media: "visual",
inherited: false,
animationType: [
"column-rule-color",
"column-rule-style",
"column-rule-width"
],
percentages: "no",
groups: [
"CSS Columns"
],
initial: [
"column-rule-width",
"column-rule-style",
"column-rule-color"
],
appliesto: "multicolElements",
computed: [
"column-rule-color",
"column-rule-style",
"column-rule-width"
],
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/column-rule"
},
"column-rule-color": {
syntax: "<color>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Columns"
],
initial: "currentcolor",
appliesto: "multicolElements",
computed: "computedColor",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/column-rule-color"
},
"column-rule-style": {
syntax: "<'border-style'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Columns"
],
initial: "none",
appliesto: "multicolElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/column-rule-style"
},
"column-rule-width": {
syntax: "<'border-width'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "no",
groups: [
"CSS Columns"
],
initial: "medium",
appliesto: "multicolElements",
computed: "absoluteLength0IfColumnRuleStyleNoneOrHidden",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/column-rule-width"
},
"column-span": {
syntax: "none | all",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Columns"
],
initial: "none",
appliesto: "inFlowBlockLevelElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/column-span"
},
"column-width": {
syntax: "<length> | auto",
media: "visual",
inherited: false,
animationType: "length",
percentages: "no",
groups: [
"CSS Columns"
],
initial: "auto",
appliesto: "blockContainersExceptTableWrappers",
computed: "absoluteLengthZeroOrLarger",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/column-width"
},
columns: columns$1,
contain: contain$1,
"contain-intrinsic-size": {
syntax: "[ none | <length> | auto <length> ]{1,2}",
media: "visual",
inherited: false,
animationType: [
"contain-intrinsic-width",
"contain-intrinsic-height"
],
percentages: [
"contain-intrinsic-width",
"contain-intrinsic-height"
],
groups: [
"CSS Containment"
],
initial: [
"contain-intrinsic-width",
"contain-intrinsic-height"
],
appliesto: "elementsForWhichSizeContainmentCanApply",
computed: [
"contain-intrinsic-width",
"contain-intrinsic-height"
],
order: "perGrammar",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/contain-intrinsic-size"
},
"contain-intrinsic-block-size": {
syntax: "none | <length> | auto <length>",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Containment"
],
initial: "none",
appliesto: "elementsForWhichSizeContainmentCanApply",
computed: "asSpecifiedWithLengthValuesComputed",
order: "perGrammar",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/contain-intrinsic-block-size"
},
"contain-intrinsic-height": {
syntax: "none | <length> | auto <length>",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Containment"
],
initial: "none",
appliesto: "elementsForWhichSizeContainmentCanApply",
computed: "asSpecifiedWithLengthValuesComputed",
order: "perGrammar",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/contain-intrinsic-height"
},
"contain-intrinsic-inline-size": {
syntax: "none | <length> | auto <length>",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Containment"
],
initial: "none",
appliesto: "elementsForWhichSizeContainmentCanApply",
computed: "asSpecifiedWithLengthValuesComputed",
order: "perGrammar",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/contain-intrinsic-inline-size"
},
"contain-intrinsic-width": {
syntax: "none | <length> | auto <length>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Containment"
],
initial: "none",
appliesto: "elementsForWhichSizeContainmentCanApply",
computed: "asSpecifiedWithLengthValuesComputed",
order: "perGrammar",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/contain-intrinsic-width"
},
content: content$1,
"content-visibility": {
syntax: "visible | auto | hidden",
media: "all",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Containment"
],
initial: "visible",
appliesto: "elementsForWhichLayoutContainmentCanApply",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/content-visibility"
},
"counter-increment": {
syntax: "[ <counter-name> <integer>? ]+ | none",
media: "all",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Counter Styles"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/counter-increment"
},
"counter-reset": {
syntax: "[ <counter-name> <integer>? | <reversed-counter-name> <integer>? ]+ | none",
media: "all",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Counter Styles"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/counter-reset"
},
"counter-set": {
syntax: "[ <counter-name> <integer>? ]+ | none",
media: "all",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Counter Styles"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/counter-set"
},
cursor: cursor$1,
direction: direction$1,
display: display$1,
"empty-cells": {
syntax: "show | hide",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Table"
],
initial: "show",
appliesto: "tableCellElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/empty-cells"
},
filter: filter$1,
flex: flex$1,
"flex-basis": {
syntax: "content | <'width'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToFlexContainersInnerMainSize",
groups: [
"CSS Flexible Box Layout"
],
initial: "auto",
appliesto: "flexItemsAndInFlowPseudos",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "lengthOrPercentageBeforeKeywordIfBothPresent",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/flex-basis"
},
"flex-direction": {
syntax: "row | row-reverse | column | column-reverse",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Flexible Box Layout"
],
initial: "row",
appliesto: "flexContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/flex-direction"
},
"flex-flow": {
syntax: "<'flex-direction'> || <'flex-wrap'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Flexible Box Layout"
],
initial: [
"flex-direction",
"flex-wrap"
],
appliesto: "flexContainers",
computed: [
"flex-direction",
"flex-wrap"
],
order: "orderOfAppearance",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/flex-flow"
},
"flex-grow": {
syntax: "<number>",
media: "visual",
inherited: false,
animationType: "number",
percentages: "no",
groups: [
"CSS Flexible Box Layout"
],
initial: "0",
appliesto: "flexItemsAndInFlowPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/flex-grow"
},
"flex-shrink": {
syntax: "<number>",
media: "visual",
inherited: false,
animationType: "number",
percentages: "no",
groups: [
"CSS Flexible Box Layout"
],
initial: "1",
appliesto: "flexItemsAndInFlowPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/flex-shrink"
},
"flex-wrap": {
syntax: "nowrap | wrap | wrap-reverse",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Flexible Box Layout"
],
initial: "nowrap",
appliesto: "flexContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/flex-wrap"
},
float: float$1,
font: font$3,
"font-family": {
syntax: "[ <family-name> | <generic-family> ]#",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "dependsOnUserAgent",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-family"
},
"font-feature-settings": {
syntax: "normal | <feature-tag-value>#",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-feature-settings"
},
"font-kerning": {
syntax: "auto | normal | none",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-kerning"
},
"font-language-override": {
syntax: "normal | <string>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-language-override"
},
"font-optical-sizing": {
syntax: "auto | none",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-optical-sizing"
},
"font-variation-settings": {
syntax: "normal | [ <string> <number> ]#",
media: "visual",
inherited: true,
animationType: "transform",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-variation-settings"
},
"font-size": {
syntax: "<absolute-size> | <relative-size> | <length-percentage>",
media: "visual",
inherited: true,
animationType: "length",
percentages: "referToParentElementsFontSize",
groups: [
"CSS Fonts"
],
initial: "medium",
appliesto: "allElements",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-size"
},
"font-size-adjust": {
syntax: "none | [ ex-height | cap-height | ch-width | ic-width | ic-height ]? [ from-font | <number> ]",
media: "visual",
inherited: true,
animationType: "number",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-size-adjust"
},
"font-smooth": {
syntax: "auto | never | always | <absolute-size> | <length>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-smooth"
},
"font-stretch": {
syntax: "<font-stretch-absolute>",
media: "visual",
inherited: true,
animationType: "fontStretch",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-stretch"
},
"font-style": {
syntax: "normal | italic | oblique <angle>?",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-style"
},
"font-synthesis": {
syntax: "none | [ weight || style || small-caps ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "weight style",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-synthesis"
},
"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 ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-variant"
},
"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> ) ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-variant-alternates"
},
"font-variant-caps": {
syntax: "normal | small-caps | all-small-caps | petite-caps | all-petite-caps | unicase | titling-caps",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-variant-caps"
},
"font-variant-east-asian": {
syntax: "normal | [ <east-asian-variant-values> || <east-asian-width-values> || ruby ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-variant-east-asian"
},
"font-variant-ligatures": {
syntax: "normal | none | [ <common-lig-values> || <discretionary-lig-values> || <historical-lig-values> || <contextual-alt-values> ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-variant-ligatures"
},
"font-variant-numeric": {
syntax: "normal | [ <numeric-figure-values> || <numeric-spacing-values> || <numeric-fraction-values> || ordinal || slashed-zero ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-variant-numeric"
},
"font-variant-position": {
syntax: "normal | sub | super",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-variant-position"
},
"font-weight": {
syntax: "<font-weight-absolute> | bolder | lighter",
media: "visual",
inherited: true,
animationType: "fontWeight",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "keywordOrNumericalValueBolderLighterTransformedToRealValue",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-weight"
},
"forced-color-adjust": {
syntax: "auto | none",
media: "visual",
inherited: true,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Color"
],
initial: "auto",
appliesto: "allElementsAndText",
computed: "asSpecified",
order: "perGrammar",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/forced-color-adjust"
},
gap: gap$1,
grid: grid$1,
"grid-area": {
syntax: "<grid-line> [ / <grid-line> ]{0,3}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: [
"grid-row-start",
"grid-column-start",
"grid-row-end",
"grid-column-end"
],
appliesto: "gridItemsAndBoxesWithinGridContainer",
computed: [
"grid-row-start",
"grid-column-start",
"grid-row-end",
"grid-column-end"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-area"
},
"grid-auto-columns": {
syntax: "<track-size>+",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "referToDimensionOfContentArea",
groups: [
"CSS Grid Layout"
],
initial: "auto",
appliesto: "gridContainers",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-auto-columns"
},
"grid-auto-flow": {
syntax: "[ row | column ] || dense",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: "row",
appliesto: "gridContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-auto-flow"
},
"grid-auto-rows": {
syntax: "<track-size>+",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "referToDimensionOfContentArea",
groups: [
"CSS Grid Layout"
],
initial: "auto",
appliesto: "gridContainers",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-auto-rows"
},
"grid-column": {
syntax: "<grid-line> [ / <grid-line> ]?",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: [
"grid-column-start",
"grid-column-end"
],
appliesto: "gridItemsAndBoxesWithinGridContainer",
computed: [
"grid-column-start",
"grid-column-end"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-column"
},
"grid-column-end": {
syntax: "<grid-line>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: "auto",
appliesto: "gridItemsAndBoxesWithinGridContainer",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-column-end"
},
"grid-column-gap": {
syntax: "<length-percentage>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToDimensionOfContentArea",
groups: [
"CSS Grid Layout"
],
initial: "0",
appliesto: "gridContainers",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/column-gap"
},
"grid-column-start": {
syntax: "<grid-line>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: "auto",
appliesto: "gridItemsAndBoxesWithinGridContainer",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-column-start"
},
"grid-gap": {
syntax: "<'grid-row-gap'> <'grid-column-gap'>?",
media: "visual",
inherited: false,
animationType: [
"grid-row-gap",
"grid-column-gap"
],
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: [
"grid-row-gap",
"grid-column-gap"
],
appliesto: "gridContainers",
computed: [
"grid-row-gap",
"grid-column-gap"
],
order: "uniqueOrder",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/gap"
},
"grid-row": {
syntax: "<grid-line> [ / <grid-line> ]?",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: [
"grid-row-start",
"grid-row-end"
],
appliesto: "gridItemsAndBoxesWithinGridContainer",
computed: [
"grid-row-start",
"grid-row-end"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-row"
},
"grid-row-end": {
syntax: "<grid-line>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: "auto",
appliesto: "gridItemsAndBoxesWithinGridContainer",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-row-end"
},
"grid-row-gap": {
syntax: "<length-percentage>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToDimensionOfContentArea",
groups: [
"CSS Grid Layout"
],
initial: "0",
appliesto: "gridContainers",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/row-gap"
},
"grid-row-start": {
syntax: "<grid-line>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: "auto",
appliesto: "gridItemsAndBoxesWithinGridContainer",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-row-start"
},
"grid-template": {
syntax: "none | [ <'grid-template-rows'> / <'grid-template-columns'> ] | [ <line-names>? <string> <track-size>? <line-names>? ]+ [ / <explicit-track-list> ]?",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: [
"grid-template-columns",
"grid-template-rows"
],
groups: [
"CSS Grid Layout"
],
initial: [
"grid-template-columns",
"grid-template-rows",
"grid-template-areas"
],
appliesto: "gridContainers",
computed: [
"grid-template-columns",
"grid-template-rows",
"grid-template-areas"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-template"
},
"grid-template-areas": {
syntax: "none | <string>+",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: "none",
appliesto: "gridContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-template-areas"
},
"grid-template-columns": {
syntax: "none | <track-list> | <auto-track-list> | subgrid <line-name-list>?",
media: "visual",
inherited: false,
animationType: "simpleListOfLpcDifferenceLpc",
percentages: "referToDimensionOfContentArea",
groups: [
"CSS Grid Layout"
],
initial: "none",
appliesto: "gridContainers",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-template-columns"
},
"grid-template-rows": {
syntax: "none | <track-list> | <auto-track-list> | subgrid <line-name-list>?",
media: "visual",
inherited: false,
animationType: "simpleListOfLpcDifferenceLpc",
percentages: "referToDimensionOfContentArea",
groups: [
"CSS Grid Layout"
],
initial: "none",
appliesto: "gridContainers",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-template-rows"
},
"hanging-punctuation": {
syntax: "none | [ first || [ force-end | allow-end ] || last ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/hanging-punctuation"
},
height: height$1,
"hyphenate-character": {
syntax: "auto | <string>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/hyphenate-character"
},
hyphens: hyphens$1,
"image-orientation": {
syntax: "from-image | <angle> | [ <angle>? flip ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Images"
],
initial: "from-image",
appliesto: "allElements",
computed: "angleRoundedToNextQuarter",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/image-orientation"
},
"image-rendering": {
syntax: "auto | crisp-edges | pixelated",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Images"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/image-rendering"
},
"image-resolution": {
syntax: "[ from-image || <resolution> ] && snap?",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Images"
],
initial: "1dppx",
appliesto: "allElements",
computed: "asSpecifiedWithExceptionOfResolution",
order: "uniqueOrder",
status: "experimental"
},
"ime-mode": {
syntax: "auto | normal | active | inactive | disabled",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "auto",
appliesto: "textFields",
computed: "asSpecified",
order: "uniqueOrder",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/ime-mode"
},
"initial-letter": {
syntax: "normal | [ <number> <integer>? ]",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Inline"
],
initial: "normal",
appliesto: "firstLetterPseudoElementsAndInlineLevelFirstChildren",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/initial-letter"
},
"initial-letter-align": {
syntax: "[ auto | alphabetic | hanging | ideographic ]",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Inline"
],
initial: "auto",
appliesto: "firstLetterPseudoElementsAndInlineLevelFirstChildren",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/initial-letter-align"
},
"inline-size": {
syntax: "<'width'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "inlineSizeOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "auto",
appliesto: "sameAsWidthAndHeight",
computed: "sameAsWidthAndHeight",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/inline-size"
},
"input-security": {
syntax: "auto | none",
media: "interactive",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "auto",
appliesto: "sensitiveTextInputs",
computed: "asSpecified",
order: "perGrammar",
status: "standard"
},
inset: inset$1,
"inset-block": {
syntax: "<'top'>{1,2}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "logicalHeightOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: [
"inset-block-start",
"inset-block-end"
],
appliesto: "positionedElements",
computed: [
"inset-block-start",
"inset-block-end"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/inset-block"
},
"inset-block-end": {
syntax: "<'top'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "logicalHeightOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "auto",
appliesto: "positionedElements",
computed: "sameAsBoxOffsets",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/inset-block-end"
},
"inset-block-start": {
syntax: "<'top'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "logicalHeightOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "auto",
appliesto: "positionedElements",
computed: "sameAsBoxOffsets",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/inset-block-start"
},
"inset-inline": {
syntax: "<'top'>{1,2}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: [
"inset-inline-start",
"inset-inline-end"
],
appliesto: "positionedElements",
computed: [
"inset-inline-start",
"inset-inline-end"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/inset-inline"
},
"inset-inline-end": {
syntax: "<'top'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "auto",
appliesto: "positionedElements",
computed: "sameAsBoxOffsets",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/inset-inline-end"
},
"inset-inline-start": {
syntax: "<'top'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "auto",
appliesto: "positionedElements",
computed: "sameAsBoxOffsets",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/inset-inline-start"
},
isolation: isolation$1,
"justify-content": {
syntax: "normal | <content-distribution> | <overflow-position>? [ <content-position> | left | right ]",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Alignment"
],
initial: "normal",
appliesto: "flexContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/justify-content"
},
"justify-items": {
syntax: "normal | stretch | <baseline-position> | <overflow-position>? [ <self-position> | left | right ] | legacy | legacy && [ left | right | center ]",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Alignment"
],
initial: "legacy",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/justify-items"
},
"justify-self": {
syntax: "auto | normal | stretch | <baseline-position> | <overflow-position>? [ <self-position> | left | right ]",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Alignment"
],
initial: "auto",
appliesto: "blockLevelBoxesAndAbsolutelyPositionedBoxesAndGridItems",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/justify-self"
},
"justify-tracks": {
syntax: "[ normal | <content-distribution> | <overflow-position>? [ <content-position> | left | right ] ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: "normal",
appliesto: "gridContainersWithMasonryLayoutInTheirInlineAxis",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/justify-tracks"
},
left: left$1,
"letter-spacing": {
syntax: "normal | <length>",
media: "visual",
inherited: true,
animationType: "length",
percentages: "no",
groups: [
"CSS Text"
],
initial: "normal",
appliesto: "allElements",
computed: "optimumValueOfAbsoluteLengthOrNormal",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/letter-spacing"
},
"line-break": {
syntax: "auto | loose | normal | strict | anywhere",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/line-break"
},
"line-clamp": {
syntax: "none | <integer>",
media: "visual",
inherited: false,
animationType: "integer",
percentages: "no",
groups: [
"CSS Overflow"
],
initial: "none",
appliesto: "blockContainersExceptMultiColumnContainers",
computed: "asSpecified",
order: "perGrammar",
status: "experimental"
},
"line-height": {
syntax: "normal | <number> | <length> | <percentage>",
media: "visual",
inherited: true,
animationType: "numberOrLength",
percentages: "referToElementFontSize",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "absoluteLengthOrAsSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/line-height"
},
"line-height-step": {
syntax: "<length>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "0",
appliesto: "blockContainers",
computed: "absoluteLength",
order: "perGrammar",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/line-height-step"
},
"list-style": {
syntax: "<'list-style-type'> || <'list-style-position'> || <'list-style-image'>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Lists and Counters"
],
initial: [
"list-style-type",
"list-style-position",
"list-style-image"
],
appliesto: "listItems",
computed: [
"list-style-image",
"list-style-position",
"list-style-type"
],
order: "orderOfAppearance",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/list-style"
},
"list-style-image": {
syntax: "<image> | none",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Lists and Counters"
],
initial: "none",
appliesto: "listItems",
computed: "theKeywordListStyleImageNoneOrComputedValue",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/list-style-image"
},
"list-style-position": {
syntax: "inside | outside",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Lists and Counters"
],
initial: "outside",
appliesto: "listItems",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/list-style-position"
},
"list-style-type": {
syntax: "<counter-style> | <string> | none",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Lists and Counters"
],
initial: "disc",
appliesto: "listItems",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/list-style-type"
},
margin: margin$1,
"margin-block": {
syntax: "<'margin-left'>{1,2}",
media: "visual",
inherited: false,
animationType: "length",
percentages: "dependsOnLayoutModel",
groups: [
"CSS Logical Properties"
],
initial: [
"margin-block-start",
"margin-block-end"
],
appliesto: "sameAsMargin",
computed: [
"margin-block-start",
"margin-block-end"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-block"
},
"margin-block-end": {
syntax: "<'margin-left'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "dependsOnLayoutModel",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "sameAsMargin",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-block-end"
},
"margin-block-start": {
syntax: "<'margin-left'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "dependsOnLayoutModel",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "sameAsMargin",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-block-start"
},
"margin-bottom": {
syntax: "<length> | <percentage> | auto",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "0",
appliesto: "allElementsExceptTableDisplayTypes",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-bottom"
},
"margin-inline": {
syntax: "<'margin-left'>{1,2}",
media: "visual",
inherited: false,
animationType: "length",
percentages: "dependsOnLayoutModel",
groups: [
"CSS Logical Properties"
],
initial: [
"margin-inline-start",
"margin-inline-end"
],
appliesto: "sameAsMargin",
computed: [
"margin-inline-start",
"margin-inline-end"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-inline"
},
"margin-inline-end": {
syntax: "<'margin-left'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "dependsOnLayoutModel",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "sameAsMargin",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-inline-end"
},
"margin-inline-start": {
syntax: "<'margin-left'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "dependsOnLayoutModel",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "sameAsMargin",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-inline-start"
},
"margin-left": {
syntax: "<length> | <percentage> | auto",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "0",
appliesto: "allElementsExceptTableDisplayTypes",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-left"
},
"margin-right": {
syntax: "<length> | <percentage> | auto",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "0",
appliesto: "allElementsExceptTableDisplayTypes",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-right"
},
"margin-top": {
syntax: "<length> | <percentage> | auto",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "0",
appliesto: "allElementsExceptTableDisplayTypes",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-top"
},
"margin-trim": {
syntax: "none | in-flow | all",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Model"
],
initial: "none",
appliesto: "blockContainersAndMultiColumnContainers",
computed: "asSpecified",
order: "perGrammar",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-trim"
},
mask: mask$1,
"mask-border": {
syntax: "<'mask-border-source'> || <'mask-border-slice'> [ / <'mask-border-width'>? [ / <'mask-border-outset'> ]? ]? || <'mask-border-repeat'> || <'mask-border-mode'>",
media: "visual",
inherited: false,
animationType: [
"mask-border-mode",
"mask-border-outset",
"mask-border-repeat",
"mask-border-slice",
"mask-border-source",
"mask-border-width"
],
percentages: [
"mask-border-slice",
"mask-border-width"
],
groups: [
"CSS Masking"
],
initial: [
"mask-border-mode",
"mask-border-outset",
"mask-border-repeat",
"mask-border-slice",
"mask-border-source",
"mask-border-width"
],
appliesto: "allElementsSVGContainerElements",
computed: [
"mask-border-mode",
"mask-border-outset",
"mask-border-repeat",
"mask-border-slice",
"mask-border-source",
"mask-border-width"
],
order: "perGrammar",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-border"
},
"mask-border-mode": {
syntax: "luminance | alpha",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "alpha",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-border-mode"
},
"mask-border-outset": {
syntax: "[ <length> | <number> ]{1,4}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "0",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-border-outset"
},
"mask-border-repeat": {
syntax: "[ stretch | repeat | round | space ]{1,2}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "stretch",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-border-repeat"
},
"mask-border-slice": {
syntax: "<number-percentage>{1,4} fill?",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "referToSizeOfMaskBorderImage",
groups: [
"CSS Masking"
],
initial: "0",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-border-slice"
},
"mask-border-source": {
syntax: "none | <image>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "none",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecifiedURLsAbsolute",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-border-source"
},
"mask-border-width": {
syntax: "[ <length-percentage> | <number> | auto ]{1,4}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "relativeToMaskBorderImageArea",
groups: [
"CSS Masking"
],
initial: "auto",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-border-width"
},
"mask-clip": {
syntax: "[ <geometry-box> | no-clip ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "border-box",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-clip"
},
"mask-composite": {
syntax: "<compositing-operator>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "add",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-composite"
},
"mask-image": {
syntax: "<mask-reference>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "none",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecifiedURLsAbsolute",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-image"
},
"mask-mode": {
syntax: "<masking-mode>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "match-source",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-mode"
},
"mask-origin": {
syntax: "<geometry-box>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "border-box",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-origin"
},
"mask-position": {
syntax: "<position>#",
media: "visual",
inherited: false,
animationType: "repeatableListOfSimpleListOfLpc",
percentages: "referToSizeOfMaskPaintingArea",
groups: [
"CSS Masking"
],
initial: "center",
appliesto: "allElementsSVGContainerElements",
computed: "consistsOfTwoKeywordsForOriginAndOffsets",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-position"
},
"mask-repeat": {
syntax: "<repeat-style>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "repeat",
appliesto: "allElementsSVGContainerElements",
computed: "consistsOfTwoDimensionKeywords",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-repeat"
},
"mask-size": {
syntax: "<bg-size>#",
media: "visual",
inherited: false,
animationType: "repeatableListOfSimpleListOfLpc",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "auto",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-size"
},
"mask-type": {
syntax: "luminance | alpha",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "luminance",
appliesto: "maskElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-type"
},
"masonry-auto-flow": {
syntax: "[ pack | next ] || [ definite-first | ordered ]",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: "pack",
appliesto: "gridContainersWithMasonryLayout",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/masonry-auto-flow"
},
"math-depth": {
syntax: "auto-add | add(<integer>) | <integer>",
media: "visual",
inherited: true,
animationType: "notAnimatable",
percentages: "no",
groups: [
"MathML"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/math-depth"
},
"math-shift": {
syntax: "normal | compact",
media: "visual",
inherited: true,
animationType: "notAnimatable",
percentages: "no",
groups: [
"MathML"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/math-shift"
},
"math-style": {
syntax: "normal | compact",
media: "visual",
inherited: true,
animationType: "notAnimatable",
percentages: "no",
groups: [
"MathML"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/math-style"
},
"max-block-size": {
syntax: "<'max-width'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "blockSizeOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "none",
appliesto: "sameAsWidthAndHeight",
computed: "sameAsMaxWidthAndMaxHeight",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/max-block-size"
},
"max-height": {
syntax: "none | <length-percentage> | min-content | max-content | fit-content | fit-content(<length-percentage>)",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "regardingHeightOfGeneratedBoxContainingBlockPercentagesNone",
groups: [
"CSS Box Model"
],
initial: "none",
appliesto: "allElementsButNonReplacedAndTableColumns",
computed: "percentageAsSpecifiedAbsoluteLengthOrNone",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/max-height"
},
"max-inline-size": {
syntax: "<'max-width'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "inlineSizeOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "none",
appliesto: "sameAsWidthAndHeight",
computed: "sameAsMaxWidthAndMaxHeight",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/max-inline-size"
},
"max-lines": {
syntax: "none | <integer>",
media: "visual",
inherited: false,
animationType: "integer",
percentages: "no",
groups: [
"CSS Overflow"
],
initial: "none",
appliesto: "blockContainersExceptMultiColumnContainers",
computed: "asSpecified",
order: "perGrammar",
status: "experimental"
},
"max-width": {
syntax: "none | <length-percentage> | min-content | max-content | fit-content | fit-content(<length-percentage>)",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "none",
appliesto: "allElementsButNonReplacedAndTableRows",
computed: "percentageAsSpecifiedAbsoluteLengthOrNone",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/max-width"
},
"min-block-size": {
syntax: "<'min-width'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "blockSizeOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "sameAsWidthAndHeight",
computed: "sameAsMinWidthAndMinHeight",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/min-block-size"
},
"min-height": {
syntax: "auto | <length> | <percentage> | min-content | max-content | fit-content | fit-content(<length-percentage>)",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "regardingHeightOfGeneratedBoxContainingBlockPercentages0",
groups: [
"CSS Box Model"
],
initial: "auto",
appliesto: "allElementsButNonReplacedAndTableColumns",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/min-height"
},
"min-inline-size": {
syntax: "<'min-width'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "inlineSizeOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "sameAsWidthAndHeight",
computed: "sameAsMinWidthAndMinHeight",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/min-inline-size"
},
"min-width": {
syntax: "auto | <length> | <percentage> | min-content | max-content | fit-content | fit-content(<length-percentage>)",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "auto",
appliesto: "allElementsButNonReplacedAndTableRows",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/min-width"
},
"mix-blend-mode": {
syntax: "<blend-mode> | plus-lighter",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Compositing and Blending"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mix-blend-mode"
},
"object-fit": {
syntax: "fill | contain | cover | none | scale-down",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Images"
],
initial: "fill",
appliesto: "replacedElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/object-fit"
},
"object-position": {
syntax: "<position>",
media: "visual",
inherited: true,
animationType: "repeatableListOfSimpleListOfLpc",
percentages: "referToWidthAndHeightOfElement",
groups: [
"CSS Images"
],
initial: "50% 50%",
appliesto: "replacedElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/object-position"
},
offset: offset$1,
"offset-anchor": {
syntax: "auto | <position>",
media: "visual",
inherited: false,
animationType: "position",
percentages: "relativeToWidthAndHeight",
groups: [
"CSS Motion Path"
],
initial: "auto",
appliesto: "transformableElements",
computed: "forLengthAbsoluteValueOtherwisePercentage",
order: "perGrammar",
status: "standard"
},
"offset-distance": {
syntax: "<length-percentage>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToTotalPathLength",
groups: [
"CSS Motion Path"
],
initial: "0",
appliesto: "transformableElements",
computed: "forLengthAbsoluteValueOtherwisePercentage",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/offset-distance"
},
"offset-path": {
syntax: "none | ray( [ <angle> && <size> && contain? ] ) | <path()> | <url> | [ <basic-shape> || <geometry-box> ]",
media: "visual",
inherited: false,
animationType: "angleOrBasicShapeOrPath",
percentages: "no",
groups: [
"CSS Motion Path"
],
initial: "none",
appliesto: "transformableElements",
computed: "asSpecified",
order: "perGrammar",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/offset-path"
},
"offset-position": {
syntax: "auto | <position>",
media: "visual",
inherited: false,
animationType: "position",
percentages: "referToSizeOfContainingBlock",
groups: [
"CSS Motion Path"
],
initial: "auto",
appliesto: "transformableElements",
computed: "forLengthAbsoluteValueOtherwisePercentage",
order: "perGrammar",
status: "experimental"
},
"offset-rotate": {
syntax: "[ auto | reverse ] || <angle>",
media: "visual",
inherited: false,
animationType: "angleOrBasicShapeOrPath",
percentages: "no",
groups: [
"CSS Motion Path"
],
initial: "auto",
appliesto: "transformableElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/offset-rotate"
},
opacity: opacity$1,
order: order$1,
orphans: orphans$1,
outline: outline$1,
"outline-color": {
syntax: "<color> | invert",
media: [
"visual",
"interactive"
],
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "invertOrCurrentColor",
appliesto: "allElements",
computed: "invertForTranslucentColorRGBAOtherwiseRGB",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/outline-color"
},
"outline-offset": {
syntax: "<length>",
media: [
"visual",
"interactive"
],
inherited: false,
animationType: "length",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/outline-offset"
},
"outline-style": {
syntax: "auto | <'border-style'>",
media: [
"visual",
"interactive"
],
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/outline-style"
},
"outline-width": {
syntax: "<line-width>",
media: [
"visual",
"interactive"
],
inherited: false,
animationType: "length",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLength0ForNone",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/outline-width"
},
overflow: overflow$1,
"overflow-anchor": {
syntax: "auto | none",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Scroll Anchoring"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard"
},
"overflow-block": {
syntax: "visible | hidden | clip | scroll | auto",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Overflow"
],
initial: "auto",
appliesto: "blockContainersFlexContainersGridContainers",
computed: "asSpecifiedButVisibleOrClipReplacedToAutoOrHiddenIfOtherValueDifferent",
order: "perGrammar",
status: "standard"
},
"overflow-clip-box": {
syntax: "padding-box | content-box",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "padding-box",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Mozilla/CSS/overflow-clip-box"
},
"overflow-clip-margin": {
syntax: "<visual-box> || <length [0,∞]>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Overflow"
],
initial: "0px",
appliesto: "allElements",
computed: "theComputedLength",
order: "perGrammar",
status: "standard"
},
"overflow-inline": {
syntax: "visible | hidden | clip | scroll | auto",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Overflow"
],
initial: "auto",
appliesto: "blockContainersFlexContainersGridContainers",
computed: "asSpecifiedButVisibleOrClipReplacedToAutoOrHiddenIfOtherValueDifferent",
order: "perGrammar",
status: "standard"
},
"overflow-wrap": {
syntax: "normal | break-word | anywhere",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "normal",
appliesto: "nonReplacedInlineElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/overflow-wrap"
},
"overflow-x": {
syntax: "visible | hidden | clip | scroll | auto",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Overflow"
],
initial: "visible",
appliesto: "blockContainersFlexContainersGridContainers",
computed: "asSpecifiedButVisibleOrClipReplacedToAutoOrHiddenIfOtherValueDifferent",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/overflow-x"
},
"overflow-y": {
syntax: "visible | hidden | clip | scroll | auto",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Overflow"
],
initial: "visible",
appliesto: "blockContainersFlexContainersGridContainers",
computed: "asSpecifiedButVisibleOrClipReplacedToAutoOrHiddenIfOtherValueDifferent",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/overflow-y"
},
"overscroll-behavior": {
syntax: "[ contain | none | auto ]{1,2}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Model"
],
initial: "auto",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: [
"overscroll-behavior-x",
"overscroll-behavior-y"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/overscroll-behavior"
},
"overscroll-behavior-block": {
syntax: "contain | none | auto",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Model"
],
initial: "auto",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/overscroll-behavior-block"
},
"overscroll-behavior-inline": {
syntax: "contain | none | auto",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Model"
],
initial: "auto",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/overscroll-behavior-inline"
},
"overscroll-behavior-x": {
syntax: "contain | none | auto",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Model"
],
initial: "auto",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/overscroll-behavior-x"
},
"overscroll-behavior-y": {
syntax: "contain | none | auto",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Model"
],
initial: "auto",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/overscroll-behavior-y"
},
padding: padding$1,
"padding-block": {
syntax: "<'padding-left'>{1,2}",
media: "visual",
inherited: false,
animationType: "length",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: [
"padding-block-start",
"padding-block-end"
],
appliesto: "allElementsExceptInternalTableDisplayTypes",
computed: [
"padding-block-start",
"padding-block-end"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding-block"
},
"padding-block-end": {
syntax: "<'padding-left'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "allElementsExceptInternalTableDisplayTypes",
computed: "asLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding-block-end"
},
"padding-block-start": {
syntax: "<'padding-left'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "allElementsExceptInternalTableDisplayTypes",
computed: "asLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding-block-start"
},
"padding-bottom": {
syntax: "<length> | <percentage>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "0",
appliesto: "allElementsExceptInternalTableDisplayTypes",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding-bottom"
},
"padding-inline": {
syntax: "<'padding-left'>{1,2}",
media: "visual",
inherited: false,
animationType: "length",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: [
"padding-inline-start",
"padding-inline-end"
],
appliesto: "allElementsExceptInternalTableDisplayTypes",
computed: [
"padding-inline-start",
"padding-inline-end"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding-inline"
},
"padding-inline-end": {
syntax: "<'padding-left'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "allElementsExceptInternalTableDisplayTypes",
computed: "asLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding-inline-end"
},
"padding-inline-start": {
syntax: "<'padding-left'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "allElementsExceptInternalTableDisplayTypes",
computed: "asLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding-inline-start"
},
"padding-left": {
syntax: "<length> | <percentage>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "0",
appliesto: "allElementsExceptInternalTableDisplayTypes",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding-left"
},
"padding-right": {
syntax: "<length> | <percentage>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "0",
appliesto: "allElementsExceptInternalTableDisplayTypes",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding-right"
},
"padding-top": {
syntax: "<length> | <percentage>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "0",
appliesto: "allElementsExceptInternalTableDisplayTypes",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding-top"
},
"page-break-after": {
syntax: "auto | always | avoid | left | right | recto | verso",
media: [
"visual",
"paged"
],
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Pages"
],
initial: "auto",
appliesto: "blockElementsInNormalFlow",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/page-break-after"
},
"page-break-before": {
syntax: "auto | always | avoid | left | right | recto | verso",
media: [
"visual",
"paged"
],
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Pages"
],
initial: "auto",
appliesto: "blockElementsInNormalFlow",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/page-break-before"
},
"page-break-inside": {
syntax: "auto | avoid",
media: [
"visual",
"paged"
],
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Pages"
],
initial: "auto",
appliesto: "blockElementsInNormalFlow",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/page-break-inside"
},
"paint-order": {
syntax: "normal | [ fill || stroke || markers ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "normal",
appliesto: "textElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/paint-order"
},
perspective: perspective$1,
"perspective-origin": {
syntax: "<position>",
media: "visual",
inherited: false,
animationType: "simpleListOfLpc",
percentages: "referToSizeOfBoundingBox",
groups: [
"CSS Transforms"
],
initial: "50% 50%",
appliesto: "transformableElements",
computed: "forLengthAbsoluteValueOtherwisePercentage",
order: "oneOrTwoValuesLengthAbsoluteKeywordsPercentages",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/perspective-origin"
},
"place-content": {
syntax: "<'align-content'> <'justify-content'>?",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Alignment"
],
initial: [
"align-content",
"justify-content"
],
appliesto: "multilineFlexContainers",
computed: [
"align-content",
"justify-content"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/place-content"
},
"place-items": {
syntax: "<'align-items'> <'justify-items'>?",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Alignment"
],
initial: [
"align-items",
"justify-items"
],
appliesto: "allElements",
computed: [
"align-items",
"justify-items"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/place-items"
},
"place-self": {
syntax: "<'align-self'> <'justify-self'>?",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Alignment"
],
initial: [
"align-self",
"justify-self"
],
appliesto: "blockLevelBoxesAndAbsolutelyPositionedBoxesAndGridItems",
computed: [
"align-self",
"justify-self"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/place-self"
},
"pointer-events": {
syntax: "auto | none | visiblePainted | visibleFill | visibleStroke | visible | painted | fill | stroke | all | inherit",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/pointer-events"
},
position: position$3,
quotes: quotes$1,
resize: resize$1,
right: right$1,
rotate: rotate$1,
"row-gap": {
syntax: "normal | <length-percentage>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfContentArea",
groups: [
"CSS Box Alignment"
],
initial: "normal",
appliesto: "multiColumnElementsFlexContainersGridContainers",
computed: "asSpecifiedWithLengthsAbsoluteAndNormalComputingToZeroExceptMultiColumn",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/row-gap"
},
"ruby-align": {
syntax: "start | center | space-between | space-around",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Ruby"
],
initial: "space-around",
appliesto: "rubyBasesAnnotationsBaseAnnotationContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/ruby-align"
},
"ruby-merge": {
syntax: "separate | collapse | auto",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Ruby"
],
initial: "separate",
appliesto: "rubyAnnotationsContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental"
},
"ruby-position": {
syntax: "[ alternate || [ over | under ] ] | inter-character",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Ruby"
],
initial: "alternate",
appliesto: "rubyAnnotationsContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/ruby-position"
},
scale: scale$1,
"scrollbar-color": {
syntax: "auto | <color>{2}",
media: "visual",
inherited: true,
animationType: "color",
percentages: "no",
groups: [
"CSS Scrollbars"
],
initial: "auto",
appliesto: "scrollingBoxes",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scrollbar-color"
},
"scrollbar-gutter": {
syntax: "auto | stable && both-edges?",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Overflow"
],
initial: "auto",
appliesto: "scrollingBoxes",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scrollbar-gutter"
},
"scrollbar-width": {
syntax: "auto | thin | none",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Scrollbars"
],
initial: "auto",
appliesto: "scrollingBoxes",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scrollbar-width"
},
"scroll-behavior": {
syntax: "auto | smooth",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSSOM View"
],
initial: "auto",
appliesto: "scrollingBoxes",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-behavior"
},
"scroll-margin": {
syntax: "<length>{1,4}",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: [
"scroll-margin-bottom",
"scroll-margin-left",
"scroll-margin-right",
"scroll-margin-top"
],
appliesto: "allElements",
computed: [
"scroll-margin-bottom",
"scroll-margin-left",
"scroll-margin-right",
"scroll-margin-top"
],
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin"
},
"scroll-margin-block": {
syntax: "<length>{1,2}",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: [
"scroll-margin-block-start",
"scroll-margin-block-end"
],
appliesto: "allElements",
computed: [
"scroll-margin-block-start",
"scroll-margin-block-end"
],
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin-block"
},
"scroll-margin-block-start": {
syntax: "<length>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin-block-start"
},
"scroll-margin-block-end": {
syntax: "<length>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin-block-end"
},
"scroll-margin-bottom": {
syntax: "<length>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin-bottom"
},
"scroll-margin-inline": {
syntax: "<length>{1,2}",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: [
"scroll-margin-inline-start",
"scroll-margin-inline-end"
],
appliesto: "allElements",
computed: [
"scroll-margin-inline-start",
"scroll-margin-inline-end"
],
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin-inline"
},
"scroll-margin-inline-start": {
syntax: "<length>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin-inline-start"
},
"scroll-margin-inline-end": {
syntax: "<length>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin-inline-end"
},
"scroll-margin-left": {
syntax: "<length>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin-left"
},
"scroll-margin-right": {
syntax: "<length>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin-right"
},
"scroll-margin-top": {
syntax: "<length>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin-top"
},
"scroll-padding": {
syntax: "[ auto | <length-percentage> ]{1,4}",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: [
"scroll-padding-bottom",
"scroll-padding-left",
"scroll-padding-right",
"scroll-padding-top"
],
appliesto: "scrollContainers",
computed: [
"scroll-padding-bottom",
"scroll-padding-left",
"scroll-padding-right",
"scroll-padding-top"
],
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding"
},
"scroll-padding-block": {
syntax: "[ auto | <length-percentage> ]{1,2}",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: [
"scroll-padding-block-start",
"scroll-padding-block-end"
],
appliesto: "scrollContainers",
computed: [
"scroll-padding-block-start",
"scroll-padding-block-end"
],
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding-block"
},
"scroll-padding-block-start": {
syntax: "auto | <length-percentage>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: "auto",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding-block-start"
},
"scroll-padding-block-end": {
syntax: "auto | <length-percentage>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: "auto",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding-block-end"
},
"scroll-padding-bottom": {
syntax: "auto | <length-percentage>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: "auto",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding-bottom"
},
"scroll-padding-inline": {
syntax: "[ auto | <length-percentage> ]{1,2}",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: [
"scroll-padding-inline-start",
"scroll-padding-inline-end"
],
appliesto: "scrollContainers",
computed: [
"scroll-padding-inline-start",
"scroll-padding-inline-end"
],
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding-inline"
},
"scroll-padding-inline-start": {
syntax: "auto | <length-percentage>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: "auto",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding-inline-start"
},
"scroll-padding-inline-end": {
syntax: "auto | <length-percentage>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: "auto",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding-inline-end"
},
"scroll-padding-left": {
syntax: "auto | <length-percentage>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: "auto",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding-left"
},
"scroll-padding-right": {
syntax: "auto | <length-percentage>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: "auto",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding-right"
},
"scroll-padding-top": {
syntax: "auto | <length-percentage>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: "auto",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding-top"
},
"scroll-snap-align": {
syntax: "[ none | start | end | center ]{1,2}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-snap-align"
},
"scroll-snap-coordinate": {
syntax: "none | <position>#",
media: "interactive",
inherited: false,
animationType: "position",
percentages: "referToBorderBox",
groups: [
"CSS Scroll Snap"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-snap-coordinate"
},
"scroll-snap-destination": {
syntax: "<position>",
media: "interactive",
inherited: false,
animationType: "position",
percentages: "relativeToScrollContainerPaddingBoxAxis",
groups: [
"CSS Scroll Snap"
],
initial: "0px 0px",
appliesto: "scrollContainers",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-snap-destination"
},
"scroll-snap-points-x": {
syntax: "none | repeat( <length-percentage> )",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "relativeToScrollContainerPaddingBoxAxis",
groups: [
"CSS Scroll Snap"
],
initial: "none",
appliesto: "scrollContainers",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-snap-points-x"
},
"scroll-snap-points-y": {
syntax: "none | repeat( <length-percentage> )",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "relativeToScrollContainerPaddingBoxAxis",
groups: [
"CSS Scroll Snap"
],
initial: "none",
appliesto: "scrollContainers",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-snap-points-y"
},
"scroll-snap-stop": {
syntax: "normal | always",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-snap-stop"
},
"scroll-snap-type": {
syntax: "none | [ x | y | block | inline | both ] [ mandatory | proximity ]?",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-snap-type"
},
"scroll-snap-type-x": {
syntax: "none | mandatory | proximity",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "none",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-snap-type-x"
},
"scroll-snap-type-y": {
syntax: "none | mandatory | proximity",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "none",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-snap-type-y"
},
"scroll-timeline": {
syntax: "<scroll-timeline-name> || <scroll-timeline-axis>",
media: "visual",
inherited: false,
animationType: [
"scroll-timeline-name",
"scroll-timeline-axis"
],
percentages: "no",
groups: [
"CSS Animations"
],
initial: [
"scroll-timeline-name",
"scroll-timeline-axis"
],
appliesto: "scrollContainers",
computed: [
"scroll-timeline-name",
"scroll-timeline-axis"
],
order: "perGrammar",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-timeline"
},
"scroll-timeline-axis": {
syntax: "block | inline | vertical | horizontal",
media: "interactive",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: "block",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "perGrammar",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-timeline-axis"
},
"scroll-timeline-name": {
syntax: "none | <custom-ident>",
media: "interactive",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: "none",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "perGrammar",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-timeline-name"
},
"shape-image-threshold": {
syntax: "<alpha-value>",
media: "visual",
inherited: false,
animationType: "number",
percentages: "no",
groups: [
"CSS Shapes"
],
initial: "0.0",
appliesto: "floats",
computed: "specifiedValueNumberClipped0To1",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/shape-image-threshold"
},
"shape-margin": {
syntax: "<length-percentage>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Shapes"
],
initial: "0",
appliesto: "floats",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/shape-margin"
},
"shape-outside": {
syntax: "none | [ <shape-box> || <basic-shape> ] | <image>",
media: "visual",
inherited: false,
animationType: "basicShapeOtherwiseNo",
percentages: "no",
groups: [
"CSS Shapes"
],
initial: "none",
appliesto: "floats",
computed: "asDefinedForBasicShapeWithAbsoluteURIOtherwiseAsSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/shape-outside"
},
"tab-size": {
syntax: "<integer> | <length>",
media: "visual",
inherited: true,
animationType: "length",
percentages: "no",
groups: [
"CSS Text"
],
initial: "8",
appliesto: "blockContainers",
computed: "specifiedIntegerOrAbsoluteLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/tab-size"
},
"table-layout": {
syntax: "auto | fixed",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Table"
],
initial: "auto",
appliesto: "tableElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/table-layout"
},
"text-align": {
syntax: "start | end | left | right | center | justify | match-parent",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "startOrNamelessValueIfLTRRightIfRTL",
appliesto: "blockContainers",
computed: "asSpecifiedExceptMatchParent",
order: "orderOfAppearance",
alsoAppliesTo: [
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-align"
},
"text-align-last": {
syntax: "auto | start | end | left | right | center | justify",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "auto",
appliesto: "blockContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-align-last"
},
"text-combine-upright": {
syntax: "none | all | [ digits <integer>? ]",
media: "visual",
inherited: true,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Writing Modes"
],
initial: "none",
appliesto: "nonReplacedInlineElements",
computed: "keywordPlusIntegerIfDigits",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-combine-upright"
},
"text-decoration": {
syntax: "<'text-decoration-line'> || <'text-decoration-style'> || <'text-decoration-color'> || <'text-decoration-thickness'>",
media: "visual",
inherited: false,
animationType: [
"text-decoration-color",
"text-decoration-style",
"text-decoration-line",
"text-decoration-thickness"
],
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: [
"text-decoration-color",
"text-decoration-style",
"text-decoration-line"
],
appliesto: "allElements",
computed: [
"text-decoration-line",
"text-decoration-style",
"text-decoration-color",
"text-decoration-thickness"
],
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-decoration"
},
"text-decoration-color": {
syntax: "<color>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-decoration-color"
},
"text-decoration-line": {
syntax: "none | [ underline || overline || line-through || blink ] | spelling-error | grammar-error",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-decoration-line"
},
"text-decoration-skip": {
syntax: "none | [ objects || [ spaces | [ leading-spaces || trailing-spaces ] ] || edges || box-decoration ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: "objects",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-decoration-skip"
},
"text-decoration-skip-ink": {
syntax: "auto | all | none",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-decoration-skip-ink"
},
"text-decoration-style": {
syntax: "solid | double | dotted | dashed | wavy",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: "solid",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-decoration-style"
},
"text-decoration-thickness": {
syntax: "auto | from-font | <length> | <percentage> ",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "referToElementFontSize",
groups: [
"CSS Text Decoration"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-decoration-thickness"
},
"text-emphasis": {
syntax: "<'text-emphasis-style'> || <'text-emphasis-color'>",
media: "visual",
inherited: false,
animationType: [
"text-emphasis-color",
"text-emphasis-style"
],
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: [
"text-emphasis-style",
"text-emphasis-color"
],
appliesto: "allElements",
computed: [
"text-emphasis-style",
"text-emphasis-color"
],
order: "orderOfAppearance",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-emphasis"
},
"text-emphasis-color": {
syntax: "<color>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-emphasis-color"
},
"text-emphasis-position": {
syntax: "[ over | under ] && [ right | left ]",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: "over right",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-emphasis-position"
},
"text-emphasis-style": {
syntax: "none | [ [ filled | open ] || [ dot | circle | double-circle | triangle | sesame ] ] | <string>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-emphasis-style"
},
"text-indent": {
syntax: "<length-percentage> && hanging? && each-line?",
media: "visual",
inherited: true,
animationType: "lpc",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Text"
],
initial: "0",
appliesto: "blockContainers",
computed: "percentageOrAbsoluteLengthPlusKeywords",
order: "lengthOrPercentageBeforeKeywords",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-indent"
},
"text-justify": {
syntax: "auto | inter-character | inter-word | none",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "auto",
appliesto: "inlineLevelAndTableCellElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-justify"
},
"text-orientation": {
syntax: "mixed | upright | sideways",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Writing Modes"
],
initial: "mixed",
appliesto: "allElementsExceptTableRowGroupsRowsColumnGroupsAndColumns",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-orientation"
},
"text-overflow": {
syntax: "[ clip | ellipsis | <string> ]{1,2}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "clip",
appliesto: "blockContainerElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-overflow"
},
"text-rendering": {
syntax: "auto | optimizeSpeed | optimizeLegibility | geometricPrecision",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Miscellaneous"
],
initial: "auto",
appliesto: "textElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-rendering"
},
"text-shadow": {
syntax: "none | <shadow-t>#",
media: "visual",
inherited: true,
animationType: "shadowList",
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: "none",
appliesto: "allElements",
computed: "colorPlusThreeAbsoluteLengths",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-shadow"
},
"text-size-adjust": {
syntax: "none | auto | <percentage>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "referToSizeOfFont",
groups: [
"CSS Text"
],
initial: "autoForSmartphoneBrowsersSupportingInflation",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-size-adjust"
},
"text-transform": {
syntax: "none | capitalize | uppercase | lowercase | full-width | full-size-kana",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-transform"
},
"text-underline-offset": {
syntax: "auto | <length> | <percentage> ",
media: "visual",
inherited: true,
animationType: "byComputedValueType",
percentages: "referToElementFontSize",
groups: [
"CSS Text Decoration"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-underline-offset"
},
"text-underline-position": {
syntax: "auto | from-font | [ under || [ left | right ] ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-underline-position"
},
top: top$1,
"touch-action": {
syntax: "auto | none | [ [ pan-x | pan-left | pan-right ] || [ pan-y | pan-up | pan-down ] || pinch-zoom ] | manipulation",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Pointer Events"
],
initial: "auto",
appliesto: "allElementsExceptNonReplacedInlineElementsTableRowsColumnsRowColumnGroups",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/touch-action"
},
transform: transform$1,
"transform-box": {
syntax: "content-box | border-box | fill-box | stroke-box | view-box",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Transforms"
],
initial: "view-box",
appliesto: "transformableElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/transform-box"
},
"transform-origin": {
syntax: "[ <length-percentage> | left | center | right | top | bottom ] | [ [ <length-percentage> | left | center | right ] && [ <length-percentage> | top | center | bottom ] ] <length>?",
media: "visual",
inherited: false,
animationType: "simpleListOfLpc",
percentages: "referToSizeOfBoundingBox",
groups: [
"CSS Transforms"
],
initial: "50% 50% 0",
appliesto: "transformableElements",
computed: "forLengthAbsoluteValueOtherwisePercentage",
order: "oneOrTwoValuesLengthAbsoluteKeywordsPercentages",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/transform-origin"
},
"transform-style": {
syntax: "flat | preserve-3d",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Transforms"
],
initial: "flat",
appliesto: "transformableElements",
computed: "asSpecified",
order: "uniqueOrder",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/transform-style"
},
transition: transition$1,
"transition-delay": {
syntax: "<time>#",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Transitions"
],
initial: "0s",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/transition-delay"
},
"transition-duration": {
syntax: "<time>#",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Transitions"
],
initial: "0s",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/transition-duration"
},
"transition-property": {
syntax: "none | <single-transition-property>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Transitions"
],
initial: "all",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/transition-property"
},
"transition-timing-function": {
syntax: "<easing-function>#",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Transitions"
],
initial: "ease",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/transition-timing-function"
},
translate: translate$1,
"unicode-bidi": {
syntax: "normal | embed | isolate | bidi-override | isolate-override | plaintext",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Writing Modes"
],
initial: "normal",
appliesto: "allElementsSomeValuesNoEffectOnNonInlineElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/unicode-bidi"
},
"user-select": {
syntax: "auto | text | none | contain | all",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/user-select"
},
"vertical-align": {
syntax: "baseline | sub | super | text-top | text-bottom | middle | top | bottom | <percentage> | <length>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToLineHeight",
groups: [
"CSS Table"
],
initial: "baseline",
appliesto: "inlineLevelAndTableCellElements",
computed: "absoluteLengthOrKeyword",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/vertical-align"
},
visibility: visibility$1,
"white-space": {
syntax: "normal | pre | nowrap | pre-wrap | pre-line | break-spaces",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/white-space"
},
widows: widows$1,
width: width$1,
"will-change": {
syntax: "auto | <animateable-feature>#",
media: "all",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Will Change"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/will-change"
},
"word-break": {
syntax: "normal | break-all | keep-all | break-word",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/word-break"
},
"word-spacing": {
syntax: "normal | <length>",
media: "visual",
inherited: true,
animationType: "length",
percentages: "referToWidthOfAffectedGlyph",
groups: [
"CSS Text"
],
initial: "normal",
appliesto: "allElements",
computed: "absoluteLength",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/word-spacing"
},
"word-wrap": {
syntax: "normal | break-word",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "normal",
appliesto: "nonReplacedInlineElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/overflow-wrap"
},
"writing-mode": {
syntax: "horizontal-tb | vertical-rl | vertical-lr | sideways-rl | sideways-lr",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Writing Modes"
],
initial: "horizontal-tb",
appliesto: "allElementsExceptTableRowColumnGroupsTableRowsColumns",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/writing-mode"
},
"z-index": {
syntax: "auto | <integer>",
media: "visual",
inherited: false,
animationType: "integer",
percentages: "no",
groups: [
"CSS Positioning"
],
initial: "auto",
appliesto: "positionedElements",
computed: "asSpecified",
order: "uniqueOrder",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/z-index"
},
zoom: zoom$1
};
const attachment$1 = {
syntax: "scroll | fixed | local"
};
const axis = {
syntax: "block | inline | vertical | horizontal"
};
const box$1 = {
syntax: "border-box | padding-box | content-box"
};
const color$4 = {
syntax: "<rgb()> | <rgba()> | <hsl()> | <hsla()> | <hwb()> | <lab()> | <lch()> | <hex-color> | <named-color> | currentcolor | <deprecated-system-color>"
};
const combinator$1 = {
syntax: "'>' | '+' | '~' | [ '||' ]"
};
const counter$1 = {
syntax: "<counter()> | <counters()>"
};
const gradient$1 = {
syntax: "<linear-gradient()> | <repeating-linear-gradient()> | <radial-gradient()> | <repeating-radial-gradient()> | <conic-gradient()> | <repeating-conic-gradient()>"
};
const hue$1 = {
syntax: "<number> | <angle>"
};
const image$1 = {
syntax: "<url> | <image()> | <image-set()> | <element()> | <paint()> | <cross-fade()> | <gradient>"
};
const nth$3 = {
syntax: "<an-plus-b> | even | odd"
};
const position$2 = {
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> ] ]"
};
const quote$1 = {
syntax: "open-quote | close-quote | no-open-quote | no-close-quote"
};
const ratio = {
syntax: "<number [0,∞]> [ / <number [0,∞]> ]?"
};
const scroller = {
syntax: "root | nearest"
};
const shadow$1 = {
syntax: "inset? && <length>{2,4} && <color>?"
};
const shape$2 = {
syntax: "rect(<top>, <right>, <bottom>, <left>)"
};
const size$1 = {
syntax: "closest-side | farthest-side | closest-corner | farthest-corner | <length> | <length-percentage>{2}"
};
const symbol$1 = {
syntax: "<string> | <image> | <custom-ident>"
};
const target$1 = {
syntax: "<target-counter()> | <target-counters()> | <target-text()>"
};
const require$$3$1 = {
"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>"
},
"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: attachment$1,
"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: axis,
"baseline-position": {
syntax: "[ first | last ]? baseline"
},
"basic-shape": {
syntax: "<inset()> | <circle()> | <ellipse()> | <polygon()> | <path()>"
},
"bg-image": {
syntax: "none | <image>"
},
"bg-layer": {
syntax: "<bg-image> || <bg-position> [ / <bg-size> ]? || <repeat-style> || <attachment> || <box> || <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"
},
"blur()": {
syntax: "blur( <length> )"
},
"blend-mode": {
syntax: "normal | multiply | screen | overlay | darken | lighten | color-dodge | color-burn | hard-light | soft-light | difference | exclusion | hue | saturation | color | luminosity"
},
box: box$1,
"brightness()": {
syntax: "brightness( <number-percentage> )"
},
"calc()": {
syntax: "calc( <calc-sum> )"
},
"calc-sum": {
syntax: "<calc-product> [ [ '+' | '-' ] <calc-product> ]*"
},
"calc-product": {
syntax: "<calc-value> [ '*' <calc-value> | '/' <number> ]*"
},
"calc-value": {
syntax: "<number> | <dimension> | <percentage> | <calc-constant> | ( <calc-sum> )"
},
"calc-constant": {
syntax: "e | pi | infinity | -infinity | NaN"
},
"cf-final-image": {
syntax: "<image> | <color>"
},
"cf-mixing-image": {
syntax: "<percentage>? && <image>"
},
"circle()": {
syntax: "circle( [ <shape-radius> ]? [ at <position> ]? )"
},
"clamp()": {
syntax: "clamp( <calc-sum>#{3} )"
},
"class-selector": {
syntax: "'.' <ident-token>"
},
"clip-source": {
syntax: "<url>"
},
color: color$4,
"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>"
},
combinator: combinator$1,
"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"
},
"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>#"
},
"complex-selector": {
syntax: "<compound-selector> [ <combinator>? <compound-selector> ]*"
},
"complex-selector-list": {
syntax: "<complex-selector>#"
},
"conic-gradient()": {
syntax: "conic-gradient( [ from <angle> ]? [ at <position> ]?, <angular-color-stop-list> )"
},
"contextual-alt-values": {
syntax: "[ contextual | no-contextual ]"
},
"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>"
},
"contrast()": {
syntax: "contrast( [ <number-percentage> ] )"
},
"cos()": {
syntax: "cos( <calc-sum> )"
},
counter: counter$1,
"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>)"
},
"deprecated-system-color": {
syntax: "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"
},
"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( <length>{2,3} <color>? )"
},
"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( [ <shape-radius>{2} ]? [ 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>"
},
"fill-rule": {
syntax: "nonzero | evenodd"
},
"filter-function": {
syntax: "<blur()> | <brightness()> | <contrast()> | <drop-shadow()> | <grayscale()> | <hue-rotate()> | <invert()> | <opacity()> | <saturate()> | <sepia()>"
},
"filter-function-list": {
syntax: "[ <filter-function> | <url> ]+"
},
"final-bg-layer": {
syntax: "<'background-color'> || <bg-image> || <bg-position> [ / <bg-size> ]? || <repeat-style> || <attachment> || <box> || <box>"
},
"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: gradient$1,
"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>, <percentage>, <percentage>, <alpha-value>? )"
},
"hsla()": {
syntax: "hsla( <hue> <percentage> <percentage> [ / <alpha-value> ]? ) | hsla( <hue>, <percentage>, <percentage>, <alpha-value>? )"
},
hue: hue$1,
"hue-rotate()": {
syntax: "hue-rotate( <angle> )"
},
"hwb()": {
syntax: "hwb( [<hue> | none] [<percentage> | none] [<percentage> | none] [ / [<alpha-value> | none] ]? )"
},
"hypot()": {
syntax: "hypot( <calc-sum># )"
},
"id-selector": {
syntax: "<hash-token>"
},
image: image$1,
"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> )"
},
"keyframes-name": {
syntax: "<custom-ident> | <string>"
},
"keyframe-block": {
syntax: "<keyframe-selector># {\n <declaration-list>\n}"
},
"keyframe-block-list": {
syntax: "<keyframe-block>+"
},
"keyframe-selector": {
syntax: "from | to | <percentage>"
},
"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>"
},
"line-names": {
syntax: "'[' <custom-ident>* ']'"
},
"line-name-list": {
syntax: "[ <line-names> | <name-repeat> ]+"
},
"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-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> )"
},
"name-repeat": {
syntax: "repeat( [ <integer [1,∞]> | auto-fill ], <line-names>+ )"
},
"named-color": {
syntax: "transparent | 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 ]"
},
nth: nth$3,
"opacity()": {
syntax: "opacity( [ <number-percentage> ] )"
},
"overflow-position": {
syntax: "unsafe | safe"
},
"outline-radius": {
syntax: "<length> | <percentage>"
},
"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-list": {
syntax: "[ <page-selector># ]?"
},
"page-selector": {
syntax: "<pseudo-page>+ | <ident> <pseudo-page>*"
},
"page-size": {
syntax: "A5 | A4 | A3 | B5 | B4 | JIS-B5 | JIS-B4 | letter | legal | ledger"
},
"path()": {
syntax: "path( [ <fill-rule>, ]? <string> )"
},
"paint()": {
syntax: "paint( <ident>, <declaration-value>? )"
},
"perspective()": {
syntax: "perspective( [ <length [0,∞]> | none ] )"
},
"polygon()": {
syntax: "polygon( <fill-rule>? , [ <length-percentage> <length-percentage> ]# )"
},
position: position$2,
"pow()": {
syntax: "pow( <calc-sum>, <calc-sum> )"
},
"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: quote$1,
"radial-gradient()": {
syntax: "radial-gradient( [ <ending-shape> || <size> ]? [ at <position> ]? , <color-stop-list> )"
},
ratio: ratio,
"relative-selector": {
syntax: "<combinator>? <complex-selector>"
},
"relative-selector-list": {
syntax: "<relative-selector>#"
},
"relative-size": {
syntax: "larger | smaller"
},
"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( <percentage>#{3} , <alpha-value>? ) | rgb( <number>#{3} , <alpha-value>? )"
},
"rgba()": {
syntax: "rgba( <percentage>{3} [ / <alpha-value> ]? ) | rgba( <number>{3} [ / <alpha-value> ]? ) | rgba( <percentage>#{3} , <alpha-value>? ) | rgba( <number>#{3} , <alpha-value>? )"
},
"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> ] )"
},
scroller: scroller,
"self-position": {
syntax: "center | start | end | self-start | self-end | flex-start | flex-end"
},
"shape-radius": {
syntax: "<length-percentage> | closest-side | farthest-side"
},
"sign()": {
syntax: "sign( <calc-sum> )"
},
"skew()": {
syntax: "skew( [ <angle> | <zero> ] , [ <angle> | <zero> ]? )"
},
"skewX()": {
syntax: "skewX( [ <angle> | <zero> ] )"
},
"skewY()": {
syntax: "skewY( [ <angle> | <zero> ] )"
},
"sepia()": {
syntax: "sepia( <number-percentage> )"
},
shadow: shadow$1,
"shadow-t": {
syntax: "[ <length>{2,3} && <color>? ]"
},
shape: shape$2,
"shape-box": {
syntax: "<box> | margin-box"
},
"side-or-corner": {
syntax: "[ left | right ] || [ top | bottom ]"
},
"sin()": {
syntax: "sin( <calc-sum> )"
},
"single-animation": {
syntax: "<time> || <easing-function> || <time> || <single-animation-iteration-count> || <single-animation-direction> || <single-animation-fill-mode> || <single-animation-play-state> || [ none | <keyframes-name> ]"
},
"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 | <timeline-name> | scroll(<axis>? <scroller>?)"
},
"single-transition": {
syntax: "[ none | <single-transition-property> ] || <time> || <easing-function> || <time>"
},
"single-transition-property": {
syntax: "all | <custom-ident>"
},
size: size$1,
"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-in-parens": {
syntax: "( <supports-condition> ) | <supports-feature> | <general-enclosed>"
},
"supports-feature": {
syntax: "<supports-decl> | <supports-selector-fn>"
},
"supports-decl": {
syntax: "( <declaration> )"
},
"supports-selector-fn": {
syntax: "selector( <complex-selector> )"
},
symbol: symbol$1,
"tan()": {
syntax: "tan( <calc-sum> )"
},
target: target$1,
"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 ]? )"
},
"time-percentage": {
syntax: "<time> | <percentage>"
},
"timeline-name": {
syntax: "<custom-ident> | <string>"
},
"easing-function": {
syntax: "linear | <cubic-bezier-timing-function> | <step-timing-function>"
},
"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>+"
},
"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> )"
},
"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>? )"
},
"viewport-length": {
syntax: "auto | <length-percentage>"
},
"visual-box": {
syntax: "content-box | padding-box | border-box"
},
"wq-name": {
syntax: "<ns-prefix>? <ident-token>"
}
};
const dataPatch$2 = dataPatch$3;
const mdnAtrules$1 = require$$1$1;
const mdnProperties$1 = require$$2$1;
const mdnSyntaxes$1 = require$$3$1;
const extendSyntax$1 = /^\s*\|\s*/;
function preprocessAtrules$1(dict) {
const result = Object.create(null);
for (const atruleName in dict) {
const atrule = dict[atruleName];
let descriptors = null;
if (atrule.descriptors) {
descriptors = Object.create(null);
for (const descriptor in atrule.descriptors) {
descriptors[descriptor] = atrule.descriptors[descriptor].syntax;
}
}
result[atruleName.substr(1)] = {
prelude: atrule.syntax.trim().replace(/\{(.|\s)+\}/, '').match(/^@\S+\s+([^;\{]*)/)[1].trim() || null,
descriptors
};
}
return result;
}
function patchDictionary$1(dict, patchDict) {
const result = {};
// copy all syntaxes for an original dict
for (const key in dict) {
result[key] = dict[key].syntax || dict[key];
}
// apply a patch
for (const key in patchDict) {
if (key in dict) {
if (patchDict[key].syntax) {
result[key] = extendSyntax$1.test(patchDict[key].syntax)
? result[key] + ' ' + patchDict[key].syntax.trim()
: patchDict[key].syntax;
} else {
delete result[key];
}
} else {
if (patchDict[key].syntax) {
result[key] = patchDict[key].syntax.replace(extendSyntax$1, '');
}
}
}
return result;
}
function patchAtrules$1(dict, patchDict) {
const result = {};
// copy all syntaxes for an original dict
for (const key in dict) {
const atrulePatch = patchDict[key] || {};
result[key] = {
prelude: key in patchDict && 'prelude' in atrulePatch
? atrulePatch.prelude
: dict[key].prelude || null,
descriptors: patchDictionary$1(dict[key].descriptors || {}, atrulePatch.descriptors || {})
};
}
// apply a patch
for (const key in patchDict) {
if (!hasOwnProperty.call(dict, key)) {
const atrulePatch = patchDict[key] || {};
result[key] = {
prelude: atrulePatch.prelude || null,
descriptors: atrulePatch.descriptors && patchDictionary$1({}, atrulePatch.descriptors)
};
}
}
return result;
}
const definitions$1 = {
types: patchDictionary$1(mdnSyntaxes$1, dataPatch$2.types),
atrules: patchAtrules$1(preprocessAtrules$1(mdnAtrules$1), dataPatch$2.atrules),
properties: patchDictionary$1(mdnProperties$1, dataPatch$2.properties)
};
var data$3 = definitions$1;
var node$1 = {};
var AnPlusB$5 = {};
const types$1y = types$1K;
const charCodeDefinitions$i = charCodeDefinitions$p;
const PLUSSIGN$f = 0x002B; // U+002B PLUS SIGN (+)
const HYPHENMINUS$9 = 0x002D; // U+002D HYPHEN-MINUS (-)
const N$5 = 0x006E; // U+006E LATIN SMALL LETTER N (n)
const DISALLOW_SIGN$2 = true;
const ALLOW_SIGN$2 = false;
function checkInteger$2(offset, disallowSign) {
let pos = this.tokenStart + offset;
const code = this.charCodeAt(pos);
if (code === PLUSSIGN$f || code === HYPHENMINUS$9) {
if (disallowSign) {
this.error('Number sign is not allowed');
}
pos++;
}
for (; pos < this.tokenEnd; pos++) {
if (!charCodeDefinitions$i.isDigit(this.charCodeAt(pos))) {
this.error('Integer is expected', pos);
}
}
}
function checkTokenIsInteger$1(disallowSign) {
return checkInteger$2.call(this, 0, disallowSign);
}
function expectCharCode$1(offset, code) {
if (!this.cmpChar(this.tokenStart + offset, code)) {
let msg = '';
switch (code) {
case N$5:
msg = 'N is expected';
break;
case HYPHENMINUS$9:
msg = 'HyphenMinus is expected';
break;
}
this.error(msg, this.tokenStart + offset);
}
}
// ... <signed-integer>
// ... ['+' | '-'] <signless-integer>
function consumeB$2() {
let offset = 0;
let sign = 0;
let type = this.tokenType;
while (type === types$1y.WhiteSpace || type === types$1y.Comment) {
type = this.lookupType(++offset);
}
if (type !== types$1y.Number) {
if (this.isDelim(PLUSSIGN$f, offset) ||
this.isDelim(HYPHENMINUS$9, offset)) {
sign = this.isDelim(PLUSSIGN$f, offset) ? PLUSSIGN$f : HYPHENMINUS$9;
do {
type = this.lookupType(++offset);
} while (type === types$1y.WhiteSpace || type === types$1y.Comment);
if (type !== types$1y.Number) {
this.skip(offset);
checkTokenIsInteger$1.call(this, DISALLOW_SIGN$2);
}
} else {
return null;
}
}
if (offset > 0) {
this.skip(offset);
}
if (sign === 0) {
type = this.charCodeAt(this.tokenStart);
if (type !== PLUSSIGN$f && type !== HYPHENMINUS$9) {
this.error('Number sign is expected');
}
}
checkTokenIsInteger$1.call(this, sign !== 0);
return sign === HYPHENMINUS$9 ? '-' + this.consume(types$1y.Number) : this.consume(types$1y.Number);
}
// An+B microsyntax https://www.w3.org/TR/css-syntax-3/#anb
const name$1j = 'AnPlusB';
const structure$1i = {
a: [String, null],
b: [String, null]
};
function parse$1q() {
/* eslint-disable brace-style*/
const start = this.tokenStart;
let a = null;
let b = null;
// <integer>
if (this.tokenType === types$1y.Number) {
checkTokenIsInteger$1.call(this, ALLOW_SIGN$2);
b = this.consume(types$1y.Number);
}
// -n
// -n <signed-integer>
// -n ['+' | '-'] <signless-integer>
// -n- <signless-integer>
// <dashndashdigit-ident>
else if (this.tokenType === types$1y.Ident && this.cmpChar(this.tokenStart, HYPHENMINUS$9)) {
a = '-1';
expectCharCode$1.call(this, 1, N$5);
switch (this.tokenEnd - this.tokenStart) {
// -n
// -n <signed-integer>
// -n ['+' | '-'] <signless-integer>
case 2:
this.next();
b = consumeB$2.call(this);
break;
// -n- <signless-integer>
case 3:
expectCharCode$1.call(this, 2, HYPHENMINUS$9);
this.next();
this.skipSC();
checkTokenIsInteger$1.call(this, DISALLOW_SIGN$2);
b = '-' + this.consume(types$1y.Number);
break;
// <dashndashdigit-ident>
default:
expectCharCode$1.call(this, 2, HYPHENMINUS$9);
checkInteger$2.call(this, 3, DISALLOW_SIGN$2);
this.next();
b = this.substrToCursor(start + 2);
}
}
// '+'? n
// '+'? n <signed-integer>
// '+'? n ['+' | '-'] <signless-integer>
// '+'? n- <signless-integer>
// '+'? <ndashdigit-ident>
else if (this.tokenType === types$1y.Ident || (this.isDelim(PLUSSIGN$f) && this.lookupType(1) === types$1y.Ident)) {
let sign = 0;
a = '1';
// just ignore a plus
if (this.isDelim(PLUSSIGN$f)) {
sign = 1;
this.next();
}
expectCharCode$1.call(this, 0, N$5);
switch (this.tokenEnd - this.tokenStart) {
// '+'? n
// '+'? n <signed-integer>
// '+'? n ['+' | '-'] <signless-integer>
case 1:
this.next();
b = consumeB$2.call(this);
break;
// '+'? n- <signless-integer>
case 2:
expectCharCode$1.call(this, 1, HYPHENMINUS$9);
this.next();
this.skipSC();
checkTokenIsInteger$1.call(this, DISALLOW_SIGN$2);
b = '-' + this.consume(types$1y.Number);
break;
// '+'? <ndashdigit-ident>
default:
expectCharCode$1.call(this, 1, HYPHENMINUS$9);
checkInteger$2.call(this, 2, DISALLOW_SIGN$2);
this.next();
b = this.substrToCursor(start + sign + 1);
}
}
// <ndashdigit-dimension>
// <ndash-dimension> <signless-integer>
// <n-dimension>
// <n-dimension> <signed-integer>
// <n-dimension> ['+' | '-'] <signless-integer>
else if (this.tokenType === types$1y.Dimension) {
const code = this.charCodeAt(this.tokenStart);
const sign = code === PLUSSIGN$f || code === HYPHENMINUS$9;
let i = this.tokenStart + sign;
for (; i < this.tokenEnd; i++) {
if (!charCodeDefinitions$i.isDigit(this.charCodeAt(i))) {
break;
}
}
if (i === this.tokenStart + sign) {
this.error('Integer is expected', this.tokenStart + sign);
}
expectCharCode$1.call(this, i - this.tokenStart, N$5);
a = this.substring(start, i);
// <n-dimension>
// <n-dimension> <signed-integer>
// <n-dimension> ['+' | '-'] <signless-integer>
if (i + 1 === this.tokenEnd) {
this.next();
b = consumeB$2.call(this);
} else {
expectCharCode$1.call(this, i - this.tokenStart + 1, HYPHENMINUS$9);
// <ndash-dimension> <signless-integer>
if (i + 2 === this.tokenEnd) {
this.next();
this.skipSC();
checkTokenIsInteger$1.call(this, DISALLOW_SIGN$2);
b = '-' + this.consume(types$1y.Number);
}
// <ndashdigit-dimension>
else {
checkInteger$2.call(this, i - this.tokenStart + 2, DISALLOW_SIGN$2);
this.next();
b = this.substrToCursor(i + 1);
}
}
} else {
this.error();
}
if (a !== null && a.charCodeAt(0) === PLUSSIGN$f) {
a = a.substr(1);
}
if (b !== null && b.charCodeAt(0) === PLUSSIGN$f) {
b = b.substr(1);
}
return {
type: 'AnPlusB',
loc: this.getLocation(start, this.tokenStart),
a,
b
};
}
function generate$1q(node) {
if (node.a) {
const a =
node.a === '+1' && 'n' ||
node.a === '1' && 'n' ||
node.a === '-1' && '-n' ||
node.a + 'n';
if (node.b) {
const b = node.b[0] === '-' || node.b[0] === '+'
? node.b
: '+' + node.b;
this.tokenize(a + b);
} else {
this.tokenize(a);
}
} else {
this.tokenize(node.b);
}
}
AnPlusB$5.generate = generate$1q;
AnPlusB$5.name = name$1j;
AnPlusB$5.parse = parse$1q;
AnPlusB$5.structure = structure$1i;
var Atrule$9 = {};
const types$1x = types$1K;
function consumeRaw$b(startToken) {
return this.Raw(startToken, this.consumeUntilLeftCurlyBracketOrSemicolon, true);
}
function isDeclarationBlockAtrule$1() {
for (let offset = 1, type; type = this.lookupType(offset); offset++) {
if (type === types$1x.RightCurlyBracket) {
return true;
}
if (type === types$1x.LeftCurlyBracket ||
type === types$1x.AtKeyword) {
return false;
}
}
return false;
}
const name$1i = 'Atrule';
const walkContext$j = 'atrule';
const structure$1h = {
name: String,
prelude: ['AtrulePrelude', 'Raw', null],
block: ['Block', null]
};
function parse$1p(isDeclaration = false) {
const start = this.tokenStart;
let name;
let nameLowerCase;
let prelude = null;
let block = null;
this.eat(types$1x.AtKeyword);
name = this.substrToCursor(start + 1);
nameLowerCase = name.toLowerCase();
this.skipSC();
// parse prelude
if (this.eof === false &&
this.tokenType !== types$1x.LeftCurlyBracket &&
this.tokenType !== types$1x.Semicolon) {
if (this.parseAtrulePrelude) {
prelude = this.parseWithFallback(this.AtrulePrelude.bind(this, name, isDeclaration), consumeRaw$b);
} else {
prelude = consumeRaw$b.call(this, this.tokenIndex);
}
this.skipSC();
}
switch (this.tokenType) {
case types$1x.Semicolon:
this.next();
break;
case types$1x.LeftCurlyBracket:
if (hasOwnProperty.call(this.atrule, nameLowerCase) &&
typeof this.atrule[nameLowerCase].block === 'function') {
block = this.atrule[nameLowerCase].block.call(this, isDeclaration);
} else {
// TODO: should consume block content as Raw?
block = this.Block(isDeclarationBlockAtrule$1.call(this));
}
break;
}
return {
type: 'Atrule',
loc: this.getLocation(start, this.tokenStart),
name,
prelude,
block
};
}
function generate$1p(node) {
this.token(types$1x.AtKeyword, '@' + node.name);
if (node.prelude !== null) {
this.node(node.prelude);
}
if (node.block) {
this.node(node.block);
} else {
this.token(types$1x.Semicolon, ';');
}
}
Atrule$9.generate = generate$1p;
Atrule$9.name = name$1i;
Atrule$9.parse = parse$1p;
Atrule$9.structure = structure$1h;
Atrule$9.walkContext = walkContext$j;
var AtrulePrelude$5 = {};
const types$1w = types$1K;
const name$1h = 'AtrulePrelude';
const walkContext$i = 'atrulePrelude';
const structure$1g = {
children: [[]]
};
function parse$1o(name) {
let children = null;
if (name !== null) {
name = name.toLowerCase();
}
this.skipSC();
if (hasOwnProperty.call(this.atrule, name) &&
typeof this.atrule[name].prelude === 'function') {
// custom consumer
children = this.atrule[name].prelude.call(this);
} else {
// default consumer
children = this.readSequence(this.scope.AtrulePrelude);
}
this.skipSC();
if (this.eof !== true &&
this.tokenType !== types$1w.LeftCurlyBracket &&
this.tokenType !== types$1w.Semicolon) {
this.error('Semicolon or block is expected');
}
return {
type: 'AtrulePrelude',
loc: this.getLocationFromList(children),
children
};
}
function generate$1o(node) {
this.children(node);
}
AtrulePrelude$5.generate = generate$1o;
AtrulePrelude$5.name = name$1h;
AtrulePrelude$5.parse = parse$1o;
AtrulePrelude$5.structure = structure$1g;
AtrulePrelude$5.walkContext = walkContext$i;
var AttributeSelector$7 = {};
const types$1v = types$1K;
const DOLLARSIGN$3 = 0x0024; // U+0024 DOLLAR SIGN ($)
const ASTERISK$c = 0x002A; // U+002A ASTERISK (*)
const EQUALSSIGN$1 = 0x003D; // U+003D EQUALS SIGN (=)
const CIRCUMFLEXACCENT$1 = 0x005E; // U+005E (^)
const VERTICALLINE$6 = 0x007C; // U+007C VERTICAL LINE (|)
const TILDE$5 = 0x007E; // U+007E TILDE (~)
function getAttributeName$1() {
if (this.eof) {
this.error('Unexpected end of input');
}
const start = this.tokenStart;
let expectIdent = false;
if (this.isDelim(ASTERISK$c)) {
expectIdent = true;
this.next();
} else if (!this.isDelim(VERTICALLINE$6)) {
this.eat(types$1v.Ident);
}
if (this.isDelim(VERTICALLINE$6)) {
if (this.charCodeAt(this.tokenStart + 1) !== EQUALSSIGN$1) {
this.next();
this.eat(types$1v.Ident);
} else if (expectIdent) {
this.error('Identifier is expected', this.tokenEnd);
}
} else if (expectIdent) {
this.error('Vertical line is expected');
}
return {
type: 'Identifier',
loc: this.getLocation(start, this.tokenStart),
name: this.substrToCursor(start)
};
}
function getOperator$1() {
const start = this.tokenStart;
const code = this.charCodeAt(start);
if (code !== EQUALSSIGN$1 && // =
code !== TILDE$5 && // ~=
code !== CIRCUMFLEXACCENT$1 && // ^=
code !== DOLLARSIGN$3 && // $=
code !== ASTERISK$c && // *=
code !== VERTICALLINE$6 // |=
) {
this.error('Attribute selector (=, ~=, ^=, $=, *=, |=) is expected');
}
this.next();
if (code !== EQUALSSIGN$1) {
if (!this.isDelim(EQUALSSIGN$1)) {
this.error('Equal sign is expected');
}
this.next();
}
return this.substrToCursor(start);
}
// '[' <wq-name> ']'
// '[' <wq-name> <attr-matcher> [ <string-token> | <ident-token> ] <attr-modifier>? ']'
const name$1g = 'AttributeSelector';
const structure$1f = {
name: 'Identifier',
matcher: [String, null],
value: ['String', 'Identifier', null],
flags: [String, null]
};
function parse$1n() {
const start = this.tokenStart;
let name;
let matcher = null;
let value = null;
let flags = null;
this.eat(types$1v.LeftSquareBracket);
this.skipSC();
name = getAttributeName$1.call(this);
this.skipSC();
if (this.tokenType !== types$1v.RightSquareBracket) {
// avoid case `[name i]`
if (this.tokenType !== types$1v.Ident) {
matcher = getOperator$1.call(this);
this.skipSC();
value = this.tokenType === types$1v.String
? this.String()
: this.Identifier();
this.skipSC();
}
// attribute flags
if (this.tokenType === types$1v.Ident) {
flags = this.consume(types$1v.Ident);
this.skipSC();
}
}
this.eat(types$1v.RightSquareBracket);
return {
type: 'AttributeSelector',
loc: this.getLocation(start, this.tokenStart),
name,
matcher,
value,
flags
};
}
function generate$1n(node) {
this.token(types$1v.Delim, '[');
this.node(node.name);
if (node.matcher !== null) {
this.tokenize(node.matcher);
this.node(node.value);
}
if (node.flags !== null) {
this.token(types$1v.Ident, node.flags);
}
this.token(types$1v.Delim, ']');
}
AttributeSelector$7.generate = generate$1n;
AttributeSelector$7.name = name$1g;
AttributeSelector$7.parse = parse$1n;
AttributeSelector$7.structure = structure$1f;
var Block$5 = {};
const types$1u = types$1K;
const AMPERSAND$6 = 0x0026; // U+0026 AMPERSAND (&)
function consumeRaw$a(startToken) {
return this.Raw(startToken, null, true);
}
function consumeRule$1() {
return this.parseWithFallback(this.Rule, consumeRaw$a);
}
function consumeRawDeclaration$1(startToken) {
return this.Raw(startToken, this.consumeUntilSemicolonIncluded, true);
}
function consumeDeclaration$1() {
if (this.tokenType === types$1u.Semicolon) {
return consumeRawDeclaration$1.call(this, this.tokenIndex);
}
const node = this.parseWithFallback(this.Declaration, consumeRawDeclaration$1);
if (this.tokenType === types$1u.Semicolon) {
this.next();
}
return node;
}
const name$1f = 'Block';
const walkContext$h = 'block';
const structure$1e = {
children: [[
'Atrule',
'Rule',
'Declaration'
]]
};
function parse$1m(isStyleBlock) {
const consumer = isStyleBlock ? consumeDeclaration$1 : consumeRule$1;
const start = this.tokenStart;
let children = this.createList();
this.eat(types$1u.LeftCurlyBracket);
scan:
while (!this.eof) {
switch (this.tokenType) {
case types$1u.RightCurlyBracket:
break scan;
case types$1u.WhiteSpace:
case types$1u.Comment:
this.next();
break;
case types$1u.AtKeyword:
children.push(this.parseWithFallback(this.Atrule.bind(this, isStyleBlock), consumeRaw$a));
break;
default:
if (isStyleBlock && this.isDelim(AMPERSAND$6)) {
children.push(consumeRule$1.call(this));
} else {
children.push(consumer.call(this));
}
}
}
if (!this.eof) {
this.eat(types$1u.RightCurlyBracket);
}
return {
type: 'Block',
loc: this.getLocation(start, this.tokenStart),
children
};
}
function generate$1m(node) {
this.token(types$1u.LeftCurlyBracket, '{');
this.children(node, prev => {
if (prev.type === 'Declaration') {
this.token(types$1u.Semicolon, ';');
}
});
this.token(types$1u.RightCurlyBracket, '}');
}
Block$5.generate = generate$1m;
Block$5.name = name$1f;
Block$5.parse = parse$1m;
Block$5.structure = structure$1e;
Block$5.walkContext = walkContext$h;
var Brackets$5 = {};
const types$1t = types$1K;
const name$1e = 'Brackets';
const structure$1d = {
children: [[]]
};
function parse$1l(readSequence, recognizer) {
const start = this.tokenStart;
let children = null;
this.eat(types$1t.LeftSquareBracket);
children = readSequence.call(this, recognizer);
if (!this.eof) {
this.eat(types$1t.RightSquareBracket);
}
return {
type: 'Brackets',
loc: this.getLocation(start, this.tokenStart),
children
};
}
function generate$1l(node) {
this.token(types$1t.Delim, '[');
this.children(node);
this.token(types$1t.Delim, ']');
}
Brackets$5.generate = generate$1l;
Brackets$5.name = name$1e;
Brackets$5.parse = parse$1l;
Brackets$5.structure = structure$1d;
var CDC$6 = {};
const types$1s = types$1K;
const name$1d = 'CDC';
const structure$1c = [];
function parse$1k() {
const start = this.tokenStart;
this.eat(types$1s.CDC); // -->
return {
type: 'CDC',
loc: this.getLocation(start, this.tokenStart)
};
}
function generate$1k() {
this.token(types$1s.CDC, '-->');
}
CDC$6.generate = generate$1k;
CDC$6.name = name$1d;
CDC$6.parse = parse$1k;
CDC$6.structure = structure$1c;
var CDO$6 = {};
const types$1r = types$1K;
const name$1c = 'CDO';
const structure$1b = [];
function parse$1j() {
const start = this.tokenStart;
this.eat(types$1r.CDO); // <!--
return {
type: 'CDO',
loc: this.getLocation(start, this.tokenStart)
};
}
function generate$1j() {
this.token(types$1r.CDO, '<!--');
}
CDO$6.generate = generate$1j;
CDO$6.name = name$1c;
CDO$6.parse = parse$1j;
CDO$6.structure = structure$1b;
var ClassSelector$5 = {};
const types$1q = types$1K;
const FULLSTOP$5 = 0x002E; // U+002E FULL STOP (.)
// '.' ident
const name$1b = 'ClassSelector';
const structure$1a = {
name: String
};
function parse$1i() {
this.eatDelim(FULLSTOP$5);
return {
type: 'ClassSelector',
loc: this.getLocation(this.tokenStart - 1, this.tokenEnd),
name: this.consume(types$1q.Ident)
};
}
function generate$1i(node) {
this.token(types$1q.Delim, '.');
this.token(types$1q.Ident, node.name);
}
ClassSelector$5.generate = generate$1i;
ClassSelector$5.name = name$1b;
ClassSelector$5.parse = parse$1i;
ClassSelector$5.structure = structure$1a;
var Combinator$5 = {};
const types$1p = types$1K;
const PLUSSIGN$e = 0x002B; // U+002B PLUS SIGN (+)
const SOLIDUS$b = 0x002F; // U+002F SOLIDUS (/)
const GREATERTHANSIGN$4 = 0x003E; // U+003E GREATER-THAN SIGN (>)
const TILDE$4 = 0x007E; // U+007E TILDE (~)
const name$1a = 'Combinator';
const structure$19 = {
name: String
};
// + | > | ~ | /deep/
function parse$1h() {
const start = this.tokenStart;
let name;
switch (this.tokenType) {
case types$1p.WhiteSpace:
name = ' ';
break;
case types$1p.Delim:
switch (this.charCodeAt(this.tokenStart)) {
case GREATERTHANSIGN$4:
case PLUSSIGN$e:
case TILDE$4:
this.next();
break;
case SOLIDUS$b:
this.next();
this.eatIdent('deep');
this.eatDelim(SOLIDUS$b);
break;
default:
this.error('Combinator is expected');
}
name = this.substrToCursor(start);
break;
}
return {
type: 'Combinator',
loc: this.getLocation(start, this.tokenStart),
name
};
}
function generate$1h(node) {
this.tokenize(node.name);
}
Combinator$5.generate = generate$1h;
Combinator$5.name = name$1a;
Combinator$5.parse = parse$1h;
Combinator$5.structure = structure$19;
var Comment$8 = {};
const types$1o = types$1K;
const ASTERISK$b = 0x002A; // U+002A ASTERISK (*)
const SOLIDUS$a = 0x002F; // U+002F SOLIDUS (/)
const name$19 = 'Comment';
const structure$18 = {
value: String
};
function parse$1g() {
const start = this.tokenStart;
let end = this.tokenEnd;
this.eat(types$1o.Comment);
if ((end - start + 2) >= 2 &&
this.charCodeAt(end - 2) === ASTERISK$b &&
this.charCodeAt(end - 1) === SOLIDUS$a) {
end -= 2;
}
return {
type: 'Comment',
loc: this.getLocation(start, this.tokenStart),
value: this.substring(start + 2, end)
};
}
function generate$1g(node) {
this.token(types$1o.Comment, '/*' + node.value + '*/');
}
Comment$8.generate = generate$1g;
Comment$8.name = name$19;
Comment$8.parse = parse$1g;
Comment$8.structure = structure$18;
var Declaration$7 = {};
const names$a = names$c;
const types$1n = types$1K;
const EXCLAMATIONMARK$5 = 0x0021; // U+0021 EXCLAMATION MARK (!)
const NUMBERSIGN$7 = 0x0023; // U+0023 NUMBER SIGN (#)
const DOLLARSIGN$2 = 0x0024; // U+0024 DOLLAR SIGN ($)
const AMPERSAND$5 = 0x0026; // U+0026 AMPERSAND (&)
const ASTERISK$a = 0x002A; // U+002A ASTERISK (*)
const PLUSSIGN$d = 0x002B; // U+002B PLUS SIGN (+)
const SOLIDUS$9 = 0x002F; // U+002F SOLIDUS (/)
function consumeValueRaw$1(startToken) {
return this.Raw(startToken, this.consumeUntilExclamationMarkOrSemicolon, true);
}
function consumeCustomPropertyRaw$1(startToken) {
return this.Raw(startToken, this.consumeUntilExclamationMarkOrSemicolon, false);
}
function consumeValue$1() {
const startValueToken = this.tokenIndex;
const value = this.Value();
if (value.type !== 'Raw' &&
this.eof === false &&
this.tokenType !== types$1n.Semicolon &&
this.isDelim(EXCLAMATIONMARK$5) === false &&
this.isBalanceEdge(startValueToken) === false) {
this.error();
}
return value;
}
const name$18 = 'Declaration';
const walkContext$g = 'declaration';
const structure$17 = {
important: [Boolean, String],
property: String,
value: ['Value', 'Raw']
};
function parse$1f() {
const start = this.tokenStart;
const startToken = this.tokenIndex;
const property = readProperty$2.call(this);
const customProperty = names$a.isCustomProperty(property);
const parseValue = customProperty ? this.parseCustomProperty : this.parseValue;
const consumeRaw = customProperty ? consumeCustomPropertyRaw$1 : consumeValueRaw$1;
let important = false;
let value;
this.skipSC();
this.eat(types$1n.Colon);
const valueStart = this.tokenIndex;
if (!customProperty) {
this.skipSC();
}
if (parseValue) {
value = this.parseWithFallback(consumeValue$1, consumeRaw);
} else {
value = consumeRaw.call(this, this.tokenIndex);
}
if (customProperty && value.type === 'Value' && value.children.isEmpty) {
for (let offset = valueStart - this.tokenIndex; offset <= 0; offset++) {
if (this.lookupType(offset) === types$1n.WhiteSpace) {
value.children.appendData({
type: 'WhiteSpace',
loc: null,
value: ' '
});
break;
}
}
}
if (this.isDelim(EXCLAMATIONMARK$5)) {
important = getImportant$1.call(this);
this.skipSC();
}
// Do not include semicolon to range per spec
// https://drafts.csswg.org/css-syntax/#declaration-diagram
if (this.eof === false &&
this.tokenType !== types$1n.Semicolon &&
this.isBalanceEdge(startToken) === false) {
this.error();
}
return {
type: 'Declaration',
loc: this.getLocation(start, this.tokenStart),
important,
property,
value
};
}
function generate$1f(node) {
this.token(types$1n.Ident, node.property);
this.token(types$1n.Colon, ':');
this.node(node.value);
if (node.important) {
this.token(types$1n.Delim, '!');
this.token(types$1n.Ident, node.important === true ? 'important' : node.important);
}
}
function readProperty$2() {
const start = this.tokenStart;
// hacks
if (this.tokenType === types$1n.Delim) {
switch (this.charCodeAt(this.tokenStart)) {
case ASTERISK$a:
case DOLLARSIGN$2:
case PLUSSIGN$d:
case NUMBERSIGN$7:
case AMPERSAND$5:
this.next();
break;
// TODO: not sure we should support this hack
case SOLIDUS$9:
this.next();
if (this.isDelim(SOLIDUS$9)) {
this.next();
}
break;
}
}
if (this.tokenType === types$1n.Hash) {
this.eat(types$1n.Hash);
} else {
this.eat(types$1n.Ident);
}
return this.substrToCursor(start);
}
// ! ws* important
function getImportant$1() {
this.eat(types$1n.Delim);
this.skipSC();
const important = this.consume(types$1n.Ident);
// store original value in case it differ from `important`
// for better original source restoring and hacks like `!ie` support
return important === 'important' ? true : important;
}
Declaration$7.generate = generate$1f;
Declaration$7.name = name$18;
Declaration$7.parse = parse$1f;
Declaration$7.structure = structure$17;
Declaration$7.walkContext = walkContext$g;
var DeclarationList$5 = {};
const types$1m = types$1K;
const AMPERSAND$4 = 0x0026; // U+0026 AMPERSAND (&)
function consumeRaw$9(startToken) {
return this.Raw(startToken, this.consumeUntilSemicolonIncluded, true);
}
const name$17 = 'DeclarationList';
const structure$16 = {
children: [[
'Declaration',
'Atrule',
'Rule'
]]
};
function parse$1e() {
const children = this.createList();
while (!this.eof) {
switch (this.tokenType) {
case types$1m.WhiteSpace:
case types$1m.Comment:
case types$1m.Semicolon:
this.next();
break;
case types$1m.AtKeyword:
children.push(this.parseWithFallback(this.Atrule.bind(this, true), consumeRaw$9));
break;
default:
if (this.isDelim(AMPERSAND$4)) {
children.push(this.parseWithFallback(this.Rule, consumeRaw$9));
} else {
children.push(this.parseWithFallback(this.Declaration, consumeRaw$9));
}
}
}
return {
type: 'DeclarationList',
loc: this.getLocationFromList(children),
children
};
}
function generate$1e(node) {
this.children(node, prev => {
if (prev.type === 'Declaration') {
this.token(types$1m.Semicolon, ';');
}
});
}
DeclarationList$5.generate = generate$1e;
DeclarationList$5.name = name$17;
DeclarationList$5.parse = parse$1e;
DeclarationList$5.structure = structure$16;
var Dimension$8 = {};
const types$1l = types$1K;
const name$16 = 'Dimension';
const structure$15 = {
value: String,
unit: String
};
function parse$1d() {
const start = this.tokenStart;
const value = this.consumeNumber(types$1l.Dimension);
return {
type: 'Dimension',
loc: this.getLocation(start, this.tokenStart),
value,
unit: this.substring(start + value.length, this.tokenStart)
};
}
function generate$1d(node) {
this.token(types$1l.Dimension, node.value + node.unit);
}
Dimension$8.generate = generate$1d;
Dimension$8.name = name$16;
Dimension$8.parse = parse$1d;
Dimension$8.structure = structure$15;
var _Function$1 = {};
const types$1k = types$1K;
const name$15 = 'Function';
const walkContext$f = 'function';
const structure$14 = {
name: String,
children: [[]]
};
// <function-token> <sequence> )
function parse$1c(readSequence, recognizer) {
const start = this.tokenStart;
const name = this.consumeFunctionName();
const nameLowerCase = name.toLowerCase();
let children;
children = recognizer.hasOwnProperty(nameLowerCase)
? recognizer[nameLowerCase].call(this, recognizer)
: readSequence.call(this, recognizer);
if (!this.eof) {
this.eat(types$1k.RightParenthesis);
}
return {
type: 'Function',
loc: this.getLocation(start, this.tokenStart),
name,
children
};
}
function generate$1c(node) {
this.token(types$1k.Function, node.name + '(');
this.children(node);
this.token(types$1k.RightParenthesis, ')');
}
_Function$1.generate = generate$1c;
_Function$1.name = name$15;
_Function$1.parse = parse$1c;
_Function$1.structure = structure$14;
_Function$1.walkContext = walkContext$f;
var Hash$6 = {};
const types$1j = types$1K;
// '#' ident
const xxx$1 = 'XXX';
const name$14 = 'Hash';
const structure$13 = {
value: String
};
function parse$1b() {
const start = this.tokenStart;
this.eat(types$1j.Hash);
return {
type: 'Hash',
loc: this.getLocation(start, this.tokenStart),
value: this.substrToCursor(start + 1)
};
}
function generate$1b(node) {
this.token(types$1j.Hash, '#' + node.value);
}
Hash$6.generate = generate$1b;
Hash$6.name = name$14;
Hash$6.parse = parse$1b;
Hash$6.structure = structure$13;
Hash$6.xxx = xxx$1;
var Identifier$5 = {};
const types$1i = types$1K;
const name$13 = 'Identifier';
const structure$12 = {
name: String
};
function parse$1a() {
return {
type: 'Identifier',
loc: this.getLocation(this.tokenStart, this.tokenEnd),
name: this.consume(types$1i.Ident)
};
}
function generate$1a(node) {
this.token(types$1i.Ident, node.name);
}
Identifier$5.generate = generate$1a;
Identifier$5.name = name$13;
Identifier$5.parse = parse$1a;
Identifier$5.structure = structure$12;
var IdSelector$5 = {};
const types$1h = types$1K;
const name$12 = 'IdSelector';
const structure$11 = {
name: String
};
function parse$19() {
const start = this.tokenStart;
// TODO: check value is an ident
this.eat(types$1h.Hash);
return {
type: 'IdSelector',
loc: this.getLocation(start, this.tokenStart),
name: this.substrToCursor(start + 1)
};
}
function generate$19(node) {
// Using Delim instead of Hash is a hack to avoid for a whitespace between ident and id-selector
// in safe mode (e.g. "a#id"), because IE11 doesn't allow a sequence <ident-token> <hash-token>
// without a whitespace in values (e.g. "1px solid#000")
this.token(types$1h.Delim, '#' + node.name);
}
IdSelector$5.generate = generate$19;
IdSelector$5.name = name$12;
IdSelector$5.parse = parse$19;
IdSelector$5.structure = structure$11;
var MediaFeature$5 = {};
const types$1g = types$1K;
const name$11 = 'MediaFeature';
const structure$10 = {
name: String,
value: ['Identifier', 'Number', 'Dimension', 'Ratio', null]
};
function parse$18() {
const start = this.tokenStart;
let name;
let value = null;
this.eat(types$1g.LeftParenthesis);
this.skipSC();
name = this.consume(types$1g.Ident);
this.skipSC();
if (this.tokenType !== types$1g.RightParenthesis) {
this.eat(types$1g.Colon);
this.skipSC();
switch (this.tokenType) {
case types$1g.Number:
if (this.lookupNonWSType(1) === types$1g.Delim) {
value = this.Ratio();
} else {
value = this.Number();
}
break;
case types$1g.Dimension:
value = this.Dimension();
break;
case types$1g.Ident:
value = this.Identifier();
break;
default:
this.error('Number, dimension, ratio or identifier is expected');
}
this.skipSC();
}
this.eat(types$1g.RightParenthesis);
return {
type: 'MediaFeature',
loc: this.getLocation(start, this.tokenStart),
name,
value
};
}
function generate$18(node) {
this.token(types$1g.LeftParenthesis, '(');
this.token(types$1g.Ident, node.name);
if (node.value !== null) {
this.token(types$1g.Colon, ':');
this.node(node.value);
}
this.token(types$1g.RightParenthesis, ')');
}
MediaFeature$5.generate = generate$18;
MediaFeature$5.name = name$11;
MediaFeature$5.parse = parse$18;
MediaFeature$5.structure = structure$10;
var MediaQuery$5 = {};
const types$1f = types$1K;
const name$10 = 'MediaQuery';
const structure$$ = {
children: [[
'Identifier',
'MediaFeature',
'WhiteSpace'
]]
};
function parse$17() {
const children = this.createList();
let child = null;
this.skipSC();
scan:
while (!this.eof) {
switch (this.tokenType) {
case types$1f.Comment:
case types$1f.WhiteSpace:
this.next();
continue;
case types$1f.Ident:
child = this.Identifier();
break;
case types$1f.LeftParenthesis:
child = this.MediaFeature();
break;
default:
break scan;
}
children.push(child);
}
if (child === null) {
this.error('Identifier or parenthesis is expected');
}
return {
type: 'MediaQuery',
loc: this.getLocationFromList(children),
children
};
}
function generate$17(node) {
this.children(node);
}
MediaQuery$5.generate = generate$17;
MediaQuery$5.name = name$10;
MediaQuery$5.parse = parse$17;
MediaQuery$5.structure = structure$$;
var MediaQueryList$5 = {};
const types$1e = types$1K;
const name$$ = 'MediaQueryList';
const structure$_ = {
children: [[
'MediaQuery'
]]
};
function parse$16() {
const children = this.createList();
this.skipSC();
while (!this.eof) {
children.push(this.MediaQuery());
if (this.tokenType !== types$1e.Comma) {
break;
}
this.next();
}
return {
type: 'MediaQueryList',
loc: this.getLocationFromList(children),
children
};
}
function generate$16(node) {
this.children(node, () => this.token(types$1e.Comma, ','));
}
MediaQueryList$5.generate = generate$16;
MediaQueryList$5.name = name$$;
MediaQueryList$5.parse = parse$16;
MediaQueryList$5.structure = structure$_;
var NestingSelector$2 = {};
const types$1d = types$1K;
const AMPERSAND$3 = 0x0026; // U+0026 AMPERSAND (&)
const name$_ = 'NestingSelector';
const structure$Z = {
};
function parse$15() {
const start = this.tokenStart;
this.eatDelim(AMPERSAND$3);
return {
type: 'NestingSelector',
loc: this.getLocation(start, this.tokenStart)
};
}
function generate$15() {
this.token(types$1d.Delim, '&');
}
NestingSelector$2.generate = generate$15;
NestingSelector$2.name = name$_;
NestingSelector$2.parse = parse$15;
NestingSelector$2.structure = structure$Z;
var Nth$5 = {};
const types$1c = types$1K;
const name$Z = 'Nth';
const structure$Y = {
nth: ['AnPlusB', 'Identifier'],
selector: ['SelectorList', null]
};
function parse$14() {
this.skipSC();
const start = this.tokenStart;
let end = start;
let selector = null;
let nth;
if (this.lookupValue(0, 'odd') || this.lookupValue(0, 'even')) {
nth = this.Identifier();
} else {
nth = this.AnPlusB();
}
end = this.tokenStart;
this.skipSC();
if (this.lookupValue(0, 'of')) {
this.next();
selector = this.SelectorList();
end = this.tokenStart;
}
return {
type: 'Nth',
loc: this.getLocation(start, end),
nth,
selector
};
}
function generate$14(node) {
this.node(node.nth);
if (node.selector !== null) {
this.token(types$1c.Ident, 'of');
this.node(node.selector);
}
}
Nth$5.generate = generate$14;
Nth$5.name = name$Z;
Nth$5.parse = parse$14;
Nth$5.structure = structure$Y;
var _Number$6 = {};
const types$1b = types$1K;
const name$Y = 'Number';
const structure$X = {
value: String
};
function parse$13() {
return {
type: 'Number',
loc: this.getLocation(this.tokenStart, this.tokenEnd),
value: this.consume(types$1b.Number)
};
}
function generate$13(node) {
this.token(types$1b.Number, node.value);
}
_Number$6.generate = generate$13;
_Number$6.name = name$Y;
_Number$6.parse = parse$13;
_Number$6.structure = structure$X;
var Operator$5 = {};
// '/' | '*' | ',' | ':' | '+' | '-'
const name$X = 'Operator';
const structure$W = {
value: String
};
function parse$12() {
const start = this.tokenStart;
this.next();
return {
type: 'Operator',
loc: this.getLocation(start, this.tokenStart),
value: this.substrToCursor(start)
};
}
function generate$12(node) {
this.tokenize(node.value);
}
Operator$5.generate = generate$12;
Operator$5.name = name$X;
Operator$5.parse = parse$12;
Operator$5.structure = structure$W;
var Parentheses$5 = {};
const types$1a = types$1K;
const name$W = 'Parentheses';
const structure$V = {
children: [[]]
};
function parse$11(readSequence, recognizer) {
const start = this.tokenStart;
let children = null;
this.eat(types$1a.LeftParenthesis);
children = readSequence.call(this, recognizer);
if (!this.eof) {
this.eat(types$1a.RightParenthesis);
}
return {
type: 'Parentheses',
loc: this.getLocation(start, this.tokenStart),
children
};
}
function generate$11(node) {
this.token(types$1a.LeftParenthesis, '(');
this.children(node);
this.token(types$1a.RightParenthesis, ')');
}
Parentheses$5.generate = generate$11;
Parentheses$5.name = name$W;
Parentheses$5.parse = parse$11;
Parentheses$5.structure = structure$V;
var Percentage$8 = {};
const types$19 = types$1K;
const name$V = 'Percentage';
const structure$U = {
value: String
};
function parse$10() {
return {
type: 'Percentage',
loc: this.getLocation(this.tokenStart, this.tokenEnd),
value: this.consumeNumber(types$19.Percentage)
};
}
function generate$10(node) {
this.token(types$19.Percentage, node.value + '%');
}
Percentage$8.generate = generate$10;
Percentage$8.name = name$V;
Percentage$8.parse = parse$10;
Percentage$8.structure = structure$U;
var PseudoClassSelector$5 = {};
const types$18 = types$1K;
const name$U = 'PseudoClassSelector';
const walkContext$e = 'function';
const structure$T = {
name: String,
children: [['Raw'], null]
};
// : [ <ident> | <function-token> <any-value>? ) ]
function parse$$() {
const start = this.tokenStart;
let children = null;
let name;
let nameLowerCase;
this.eat(types$18.Colon);
if (this.tokenType === types$18.Function) {
name = this.consumeFunctionName();
nameLowerCase = name.toLowerCase();
if (hasOwnProperty.call(this.pseudo, nameLowerCase)) {
this.skipSC();
children = this.pseudo[nameLowerCase].call(this);
this.skipSC();
} else {
children = this.createList();
children.push(
this.Raw(this.tokenIndex, null, false)
);
}
this.eat(types$18.RightParenthesis);
} else {
name = this.consume(types$18.Ident);
}
return {
type: 'PseudoClassSelector',
loc: this.getLocation(start, this.tokenStart),
name,
children
};
}
function generate$$(node) {
this.token(types$18.Colon, ':');
if (node.children === null) {
this.token(types$18.Ident, node.name);
} else {
this.token(types$18.Function, node.name + '(');
this.children(node);
this.token(types$18.RightParenthesis, ')');
}
}
PseudoClassSelector$5.generate = generate$$;
PseudoClassSelector$5.name = name$U;
PseudoClassSelector$5.parse = parse$$;
PseudoClassSelector$5.structure = structure$T;
PseudoClassSelector$5.walkContext = walkContext$e;
var PseudoElementSelector$5 = {};
const types$17 = types$1K;
const name$T = 'PseudoElementSelector';
const walkContext$d = 'function';
const structure$S = {
name: String,
children: [['Raw'], null]
};
// :: [ <ident> | <function-token> <any-value>? ) ]
function parse$_() {
const start = this.tokenStart;
let children = null;
let name;
let nameLowerCase;
this.eat(types$17.Colon);
this.eat(types$17.Colon);
if (this.tokenType === types$17.Function) {
name = this.consumeFunctionName();
nameLowerCase = name.toLowerCase();
if (hasOwnProperty.call(this.pseudo, nameLowerCase)) {
this.skipSC();
children = this.pseudo[nameLowerCase].call(this);
this.skipSC();
} else {
children = this.createList();
children.push(
this.Raw(this.tokenIndex, null, false)
);
}
this.eat(types$17.RightParenthesis);
} else {
name = this.consume(types$17.Ident);
}
return {
type: 'PseudoElementSelector',
loc: this.getLocation(start, this.tokenStart),
name,
children
};
}
function generate$_(node) {
this.token(types$17.Colon, ':');
this.token(types$17.Colon, ':');
if (node.children === null) {
this.token(types$17.Ident, node.name);
} else {
this.token(types$17.Function, node.name + '(');
this.children(node);
this.token(types$17.RightParenthesis, ')');
}
}
PseudoElementSelector$5.generate = generate$_;
PseudoElementSelector$5.name = name$T;
PseudoElementSelector$5.parse = parse$_;
PseudoElementSelector$5.structure = structure$S;
PseudoElementSelector$5.walkContext = walkContext$d;
var Ratio$5 = {};
const types$16 = types$1K;
const charCodeDefinitions$h = charCodeDefinitions$p;
const SOLIDUS$8 = 0x002F; // U+002F SOLIDUS (/)
const FULLSTOP$4 = 0x002E; // U+002E FULL STOP (.)
// Terms of <ratio> should be a positive numbers (not zero or negative)
// (see https://drafts.csswg.org/mediaqueries-3/#values)
// However, -o-min-device-pixel-ratio takes fractional values as a ratio's term
// and this is using by various sites. Therefore we relax checking on parse
// to test a term is unsigned number without an exponent part.
// Additional checking may be applied on lexer validation.
function consumeNumber$2() {
this.skipSC();
const value = this.consume(types$16.Number);
for (let i = 0; i < value.length; i++) {
const code = value.charCodeAt(i);
if (!charCodeDefinitions$h.isDigit(code) && code !== FULLSTOP$4) {
this.error('Unsigned number is expected', this.tokenStart - value.length + i);
}
}
if (Number(value) === 0) {
this.error('Zero number is not allowed', this.tokenStart - value.length);
}
return value;
}
const name$S = 'Ratio';
const structure$R = {
left: String,
right: String
};
// <positive-integer> S* '/' S* <positive-integer>
function parse$Z() {
const start = this.tokenStart;
const left = consumeNumber$2.call(this);
let right;
this.skipSC();
this.eatDelim(SOLIDUS$8);
right = consumeNumber$2.call(this);
return {
type: 'Ratio',
loc: this.getLocation(start, this.tokenStart),
left,
right
};
}
function generate$Z(node) {
this.token(types$16.Number, node.left);
this.token(types$16.Delim, '/');
this.token(types$16.Number, node.right);
}
Ratio$5.generate = generate$Z;
Ratio$5.name = name$S;
Ratio$5.parse = parse$Z;
Ratio$5.structure = structure$R;
var Raw$7 = {};
const types$15 = types$1K;
function getOffsetExcludeWS$1() {
if (this.tokenIndex > 0) {
if (this.lookupType(-1) === types$15.WhiteSpace) {
return this.tokenIndex > 1
? this.getTokenStart(this.tokenIndex - 1)
: this.firstCharOffset;
}
}
return this.tokenStart;
}
const name$R = 'Raw';
const structure$Q = {
value: String
};
function parse$Y(startToken, consumeUntil, excludeWhiteSpace) {
const startOffset = this.getTokenStart(startToken);
let endOffset;
this.skipUntilBalanced(startToken, consumeUntil || this.consumeUntilBalanceEnd);
if (excludeWhiteSpace && this.tokenStart > startOffset) {
endOffset = getOffsetExcludeWS$1.call(this);
} else {
endOffset = this.tokenStart;
}
return {
type: 'Raw',
loc: this.getLocation(startOffset, endOffset),
value: this.substring(startOffset, endOffset)
};
}
function generate$Y(node) {
this.tokenize(node.value);
}
Raw$7.generate = generate$Y;
Raw$7.name = name$R;
Raw$7.parse = parse$Y;
Raw$7.structure = structure$Q;
var Rule$7 = {};
const types$14 = types$1K;
function consumeRaw$8(startToken) {
return this.Raw(startToken, this.consumeUntilLeftCurlyBracket, true);
}
function consumePrelude$1() {
const prelude = this.SelectorList();
if (prelude.type !== 'Raw' &&
this.eof === false &&
this.tokenType !== types$14.LeftCurlyBracket) {
this.error();
}
return prelude;
}
const name$Q = 'Rule';
const walkContext$c = 'rule';
const structure$P = {
prelude: ['SelectorList', 'Raw'],
block: ['Block']
};
function parse$X() {
const startToken = this.tokenIndex;
const startOffset = this.tokenStart;
let prelude;
let block;
if (this.parseRulePrelude) {
prelude = this.parseWithFallback(consumePrelude$1, consumeRaw$8);
} else {
prelude = consumeRaw$8.call(this, startToken);
}
block = this.Block(true);
return {
type: 'Rule',
loc: this.getLocation(startOffset, this.tokenStart),
prelude,
block
};
}
function generate$X(node) {
this.node(node.prelude);
this.node(node.block);
}
Rule$7.generate = generate$X;
Rule$7.name = name$Q;
Rule$7.parse = parse$X;
Rule$7.structure = structure$P;
Rule$7.walkContext = walkContext$c;
var Selector$7 = {};
const name$P = 'Selector';
const structure$O = {
children: [[
'TypeSelector',
'IdSelector',
'ClassSelector',
'AttributeSelector',
'PseudoClassSelector',
'PseudoElementSelector',
'Combinator',
'WhiteSpace'
]]
};
function parse$W() {
const children = this.readSequence(this.scope.Selector);
// nothing were consumed
if (this.getFirstListNode(children) === null) {
this.error('Selector is expected');
}
return {
type: 'Selector',
loc: this.getLocationFromList(children),
children
};
}
function generate$W(node) {
this.children(node);
}
Selector$7.generate = generate$W;
Selector$7.name = name$P;
Selector$7.parse = parse$W;
Selector$7.structure = structure$O;
var SelectorList$5 = {};
const types$13 = types$1K;
const name$O = 'SelectorList';
const walkContext$b = 'selector';
const structure$N = {
children: [[
'Selector',
'Raw'
]]
};
function parse$V() {
const children = this.createList();
while (!this.eof) {
children.push(this.Selector());
if (this.tokenType === types$13.Comma) {
this.next();
continue;
}
break;
}
return {
type: 'SelectorList',
loc: this.getLocationFromList(children),
children
};
}
function generate$V(node) {
this.children(node, () => this.token(types$13.Comma, ','));
}
SelectorList$5.generate = generate$V;
SelectorList$5.name = name$O;
SelectorList$5.parse = parse$V;
SelectorList$5.structure = structure$N;
SelectorList$5.walkContext = walkContext$b;
var _String$1 = {};
var string$7 = {};
const charCodeDefinitions$g = charCodeDefinitions$p;
const utils$n = utils$u;
const REVERSE_SOLIDUS$5 = 0x005c; // U+005C REVERSE SOLIDUS (\)
const QUOTATION_MARK$3 = 0x0022; // "
const APOSTROPHE$4 = 0x0027; // '
function decode$5(str) {
const len = str.length;
const firstChar = str.charCodeAt(0);
const start = firstChar === QUOTATION_MARK$3 || firstChar === APOSTROPHE$4 ? 1 : 0;
const end = start === 1 && len > 1 && str.charCodeAt(len - 1) === firstChar ? len - 2 : len - 1;
let decoded = '';
for (let i = start; i <= end; i++) {
let code = str.charCodeAt(i);
if (code === REVERSE_SOLIDUS$5) {
// special case at the ending
if (i === end) {
// if the next input code point is EOF, do nothing
// otherwise include last quote as escaped
if (i !== len - 1) {
decoded = str.substr(i + 1);
}
break;
}
code = str.charCodeAt(++i);
// consume escaped
if (charCodeDefinitions$g.isValidEscape(REVERSE_SOLIDUS$5, code)) {
const escapeStart = i - 1;
const escapeEnd = utils$n.consumeEscaped(str, escapeStart);
i = escapeEnd - 1;
decoded += utils$n.decodeEscaped(str.substring(escapeStart + 1, escapeEnd));
} else {
// \r\n
if (code === 0x000d && str.charCodeAt(i + 1) === 0x000a) {
i++;
}
}
} else {
decoded += str[i];
}
}
return decoded;
}
// https://drafts.csswg.org/cssom/#serialize-a-string
// § 2.1. Common Serializing Idioms
function encode$5(str, apostrophe) {
const quote = apostrophe ? '\'' : '"';
const quoteCode = apostrophe ? APOSTROPHE$4 : QUOTATION_MARK$3;
let encoded = '';
let wsBeforeHexIsNeeded = false;
for (let i = 0; i < str.length; i++) {
const code = str.charCodeAt(i);
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER (U+FFFD).
if (code === 0x0000) {
encoded += '\uFFFD';
continue;
}
// If the character is in the range [\1-\1f] (U+0001 to U+001F) or is U+007F,
// the character escaped as code point.
// Note: Do not compare with 0x0001 since 0x0000 is precessed before
if (code <= 0x001f || code === 0x007F) {
encoded += '\\' + code.toString(16);
wsBeforeHexIsNeeded = true;
continue;
}
// If the character is '"' (U+0022) or "\" (U+005C), the escaped character.
if (code === quoteCode || code === REVERSE_SOLIDUS$5) {
encoded += '\\' + str.charAt(i);
wsBeforeHexIsNeeded = false;
} else {
if (wsBeforeHexIsNeeded && (charCodeDefinitions$g.isHexDigit(code) || charCodeDefinitions$g.isWhiteSpace(code))) {
encoded += ' ';
}
// Otherwise, the character itself.
encoded += str.charAt(i);
wsBeforeHexIsNeeded = false;
}
}
return quote + encoded + quote;
}
string$7.decode = decode$5;
string$7.encode = encode$5;
const string$6 = string$7;
const types$12 = types$1K;
const name$N = 'String';
const structure$M = {
value: String
};
function parse$U() {
return {
type: 'String',
loc: this.getLocation(this.tokenStart, this.tokenEnd),
value: string$6.decode(this.consume(types$12.String))
};
}
function generate$U(node) {
this.token(types$12.String, string$6.encode(node.value));
}
_String$1.generate = generate$U;
_String$1.name = name$N;
_String$1.parse = parse$U;
_String$1.structure = structure$M;
var StyleSheet$5 = {};
const types$11 = types$1K;
const EXCLAMATIONMARK$4 = 0x0021; // U+0021 EXCLAMATION MARK (!)
function consumeRaw$7(startToken) {
return this.Raw(startToken, null, false);
}
const name$M = 'StyleSheet';
const walkContext$a = 'stylesheet';
const structure$L = {
children: [[
'Comment',
'CDO',
'CDC',
'Atrule',
'Rule',
'Raw'
]]
};
function parse$T() {
const start = this.tokenStart;
const children = this.createList();
let child;
while (!this.eof) {
switch (this.tokenType) {
case types$11.WhiteSpace:
this.next();
continue;
case types$11.Comment:
// ignore comments except exclamation comments (i.e. /*! .. */) on top level
if (this.charCodeAt(this.tokenStart + 2) !== EXCLAMATIONMARK$4) {
this.next();
continue;
}
child = this.Comment();
break;
case types$11.CDO: // <!--
child = this.CDO();
break;
case types$11.CDC: // -->
child = this.CDC();
break;
// CSS Syntax Module Level 3
// §2.2 Error handling
// At the "top level" of a stylesheet, an <at-keyword-token> starts an at-rule.
case types$11.AtKeyword:
child = this.parseWithFallback(this.Atrule, consumeRaw$7);
break;
// Anything else starts a qualified rule ...
default:
child = this.parseWithFallback(this.Rule, consumeRaw$7);
}
children.push(child);
}
return {
type: 'StyleSheet',
loc: this.getLocation(start, this.tokenStart),
children
};
}
function generate$T(node) {
this.children(node);
}
StyleSheet$5.generate = generate$T;
StyleSheet$5.name = name$M;
StyleSheet$5.parse = parse$T;
StyleSheet$5.structure = structure$L;
StyleSheet$5.walkContext = walkContext$a;
var TypeSelector$7 = {};
const types$10 = types$1K;
const ASTERISK$9 = 0x002A; // U+002A ASTERISK (*)
const VERTICALLINE$5 = 0x007C; // U+007C VERTICAL LINE (|)
function eatIdentifierOrAsterisk$1() {
if (this.tokenType !== types$10.Ident &&
this.isDelim(ASTERISK$9) === false) {
this.error('Identifier or asterisk is expected');
}
this.next();
}
const name$L = 'TypeSelector';
const structure$K = {
name: String
};
// ident
// ident|ident
// ident|*
// *
// *|ident
// *|*
// |ident
// |*
function parse$S() {
const start = this.tokenStart;
if (this.isDelim(VERTICALLINE$5)) {
this.next();
eatIdentifierOrAsterisk$1.call(this);
} else {
eatIdentifierOrAsterisk$1.call(this);
if (this.isDelim(VERTICALLINE$5)) {
this.next();
eatIdentifierOrAsterisk$1.call(this);
}
}
return {
type: 'TypeSelector',
loc: this.getLocation(start, this.tokenStart),
name: this.substrToCursor(start)
};
}
function generate$S(node) {
this.tokenize(node.name);
}
TypeSelector$7.generate = generate$S;
TypeSelector$7.name = name$L;
TypeSelector$7.parse = parse$S;
TypeSelector$7.structure = structure$K;
var UnicodeRange$5 = {};
const types$$ = types$1K;
const charCodeDefinitions$f = charCodeDefinitions$p;
const PLUSSIGN$c = 0x002B; // U+002B PLUS SIGN (+)
const HYPHENMINUS$8 = 0x002D; // U+002D HYPHEN-MINUS (-)
const QUESTIONMARK$3 = 0x003F; // U+003F QUESTION MARK (?)
function eatHexSequence$1(offset, allowDash) {
let len = 0;
for (let pos = this.tokenStart + offset; pos < this.tokenEnd; pos++) {
const code = this.charCodeAt(pos);
if (code === HYPHENMINUS$8 && allowDash && len !== 0) {
eatHexSequence$1.call(this, offset + len + 1, false);
return -1;
}
if (!charCodeDefinitions$f.isHexDigit(code)) {
this.error(
allowDash && len !== 0
? 'Hyphen minus' + (len < 6 ? ' or hex digit' : '') + ' is expected'
: (len < 6 ? 'Hex digit is expected' : 'Unexpected input'),
pos
);
}
if (++len > 6) {
this.error('Too many hex digits', pos);
} }
this.next();
return len;
}
function eatQuestionMarkSequence$1(max) {
let count = 0;
while (this.isDelim(QUESTIONMARK$3)) {
if (++count > max) {
this.error('Too many question marks');
}
this.next();
}
}
function startsWith$2(code) {
if (this.charCodeAt(this.tokenStart) !== code) {
this.error((code === PLUSSIGN$c ? 'Plus sign' : 'Hyphen minus') + ' is expected');
}
}
// https://drafts.csswg.org/css-syntax/#urange
// Informally, the <urange> production has three forms:
// U+0001
// Defines a range consisting of a single code point, in this case the code point "1".
// U+0001-00ff
// Defines a range of codepoints between the first and the second value, in this case
// the range between "1" and "ff" (255 in decimal) inclusive.
// U+00??
// Defines a range of codepoints where the "?" characters range over all hex digits,
// in this case defining the same as the value U+0000-00ff.
// In each form, a maximum of 6 digits is allowed for each hexadecimal number (if you treat "?" as a hexadecimal digit).
//
// <urange> =
// u '+' <ident-token> '?'* |
// u <dimension-token> '?'* |
// u <number-token> '?'* |
// u <number-token> <dimension-token> |
// u <number-token> <number-token> |
// u '+' '?'+
function scanUnicodeRange$1() {
let hexLength = 0;
switch (this.tokenType) {
case types$$.Number:
// u <number-token> '?'*
// u <number-token> <dimension-token>
// u <number-token> <number-token>
hexLength = eatHexSequence$1.call(this, 1, true);
if (this.isDelim(QUESTIONMARK$3)) {
eatQuestionMarkSequence$1.call(this, 6 - hexLength);
break;
}
if (this.tokenType === types$$.Dimension ||
this.tokenType === types$$.Number) {
startsWith$2.call(this, HYPHENMINUS$8);
eatHexSequence$1.call(this, 1, false);
break;
}
break;
case types$$.Dimension:
// u <dimension-token> '?'*
hexLength = eatHexSequence$1.call(this, 1, true);
if (hexLength > 0) {
eatQuestionMarkSequence$1.call(this, 6 - hexLength);
}
break;
default:
// u '+' <ident-token> '?'*
// u '+' '?'+
this.eatDelim(PLUSSIGN$c);
if (this.tokenType === types$$.Ident) {
hexLength = eatHexSequence$1.call(this, 0, true);
if (hexLength > 0) {
eatQuestionMarkSequence$1.call(this, 6 - hexLength);
}
break;
}
if (this.isDelim(QUESTIONMARK$3)) {
this.next();
eatQuestionMarkSequence$1.call(this, 5);
break;
}
this.error('Hex digit or question mark is expected');
}
}
const name$K = 'UnicodeRange';
const structure$J = {
value: String
};
function parse$R() {
const start = this.tokenStart;
// U or u
this.eatIdent('u');
scanUnicodeRange$1.call(this);
return {
type: 'UnicodeRange',
loc: this.getLocation(start, this.tokenStart),
value: this.substrToCursor(start)
};
}
function generate$R(node) {
this.tokenize(node.value);
}
UnicodeRange$5.generate = generate$R;
UnicodeRange$5.name = name$K;
UnicodeRange$5.parse = parse$R;
UnicodeRange$5.structure = structure$J;
var Url$8 = {};
var url$5 = {};
const charCodeDefinitions$e = charCodeDefinitions$p;
const utils$m = utils$u;
const SPACE$5 = 0x0020; // U+0020 SPACE
const REVERSE_SOLIDUS$4 = 0x005c; // U+005C REVERSE SOLIDUS (\)
const QUOTATION_MARK$2 = 0x0022; // "
const APOSTROPHE$3 = 0x0027; // '
const LEFTPARENTHESIS$3 = 0x0028; // U+0028 LEFT PARENTHESIS (()
const RIGHTPARENTHESIS$3 = 0x0029; // U+0029 RIGHT PARENTHESIS ())
function decode$4(str) {
const len = str.length;
let start = 4; // length of "url("
let end = str.charCodeAt(len - 1) === RIGHTPARENTHESIS$3 ? len - 2 : len - 1;
let decoded = '';
while (start < end && charCodeDefinitions$e.isWhiteSpace(str.charCodeAt(start))) {
start++;
}
while (start < end && charCodeDefinitions$e.isWhiteSpace(str.charCodeAt(end))) {
end--;
}
for (let i = start; i <= end; i++) {
let code = str.charCodeAt(i);
if (code === REVERSE_SOLIDUS$4) {
// special case at the ending
if (i === end) {
// if the next input code point is EOF, do nothing
// otherwise include last left parenthesis as escaped
if (i !== len - 1) {
decoded = str.substr(i + 1);
}
break;
}
code = str.charCodeAt(++i);
// consume escaped
if (charCodeDefinitions$e.isValidEscape(REVERSE_SOLIDUS$4, code)) {
const escapeStart = i - 1;
const escapeEnd = utils$m.consumeEscaped(str, escapeStart);
i = escapeEnd - 1;
decoded += utils$m.decodeEscaped(str.substring(escapeStart + 1, escapeEnd));
} else {
// \r\n
if (code === 0x000d && str.charCodeAt(i + 1) === 0x000a) {
i++;
}
}
} else {
decoded += str[i];
}
}
return decoded;
}
function encode$4(str) {
let encoded = '';
let wsBeforeHexIsNeeded = false;
for (let i = 0; i < str.length; i++) {
const code = str.charCodeAt(i);
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER (U+FFFD).
if (code === 0x0000) {
encoded += '\uFFFD';
continue;
}
// If the character is in the range [\1-\1f] (U+0001 to U+001F) or is U+007F,
// the character escaped as code point.
// Note: Do not compare with 0x0001 since 0x0000 is precessed before
if (code <= 0x001f || code === 0x007F) {
encoded += '\\' + code.toString(16);
wsBeforeHexIsNeeded = true;
continue;
}
if (code === SPACE$5 ||
code === REVERSE_SOLIDUS$4 ||
code === QUOTATION_MARK$2 ||
code === APOSTROPHE$3 ||
code === LEFTPARENTHESIS$3 ||
code === RIGHTPARENTHESIS$3) {
encoded += '\\' + str.charAt(i);
wsBeforeHexIsNeeded = false;
} else {
if (wsBeforeHexIsNeeded && charCodeDefinitions$e.isHexDigit(code)) {
encoded += ' ';
}
encoded += str.charAt(i);
wsBeforeHexIsNeeded = false;
}
}
return 'url(' + encoded + ')';
}
url$5.decode = decode$4;
url$5.encode = encode$4;
const url$4 = url$5;
const string$5 = string$7;
const types$_ = types$1K;
const name$J = 'Url';
const structure$I = {
value: String
};
// <url-token> | <function-token> <string> )
function parse$Q() {
const start = this.tokenStart;
let value;
switch (this.tokenType) {
case types$_.Url:
value = url$4.decode(this.consume(types$_.Url));
break;
case types$_.Function:
if (!this.cmpStr(this.tokenStart, this.tokenEnd, 'url(')) {
this.error('Function name must be `url`');
}
this.eat(types$_.Function);
this.skipSC();
value = string$5.decode(this.consume(types$_.String));
this.skipSC();
if (!this.eof) {
this.eat(types$_.RightParenthesis);
}
break;
default:
this.error('Url or Function is expected');
}
return {
type: 'Url',
loc: this.getLocation(start, this.tokenStart),
value
};
}
function generate$Q(node) {
this.token(types$_.Url, url$4.encode(node.value));
}
Url$8.generate = generate$Q;
Url$8.name = name$J;
Url$8.parse = parse$Q;
Url$8.structure = structure$I;
var Value$7 = {};
const name$I = 'Value';
const structure$H = {
children: [[]]
};
function parse$P() {
const start = this.tokenStart;
const children = this.readSequence(this.scope.Value);
return {
type: 'Value',
loc: this.getLocation(start, this.tokenStart),
children
};
}
function generate$P(node) {
this.children(node);
}
Value$7.generate = generate$P;
Value$7.name = name$I;
Value$7.parse = parse$P;
Value$7.structure = structure$H;
var WhiteSpace$8 = {};
const types$Z = types$1K;
const SPACE$4 = Object.freeze({
type: 'WhiteSpace',
loc: null,
value: ' '
});
const name$H = 'WhiteSpace';
const structure$G = {
value: String
};
function parse$O() {
this.eat(types$Z.WhiteSpace);
return SPACE$4;
// return {
// type: 'WhiteSpace',
// loc: this.getLocation(this.tokenStart, this.tokenEnd),
// value: this.consume(WHITESPACE)
// };
}
function generate$O(node) {
this.token(types$Z.WhiteSpace, node.value);
}
WhiteSpace$8.generate = generate$O;
WhiteSpace$8.name = name$H;
WhiteSpace$8.parse = parse$O;
WhiteSpace$8.structure = structure$G;
const AnPlusB$4 = AnPlusB$5;
const Atrule$8 = Atrule$9;
const AtrulePrelude$4 = AtrulePrelude$5;
const AttributeSelector$6 = AttributeSelector$7;
const Block$4 = Block$5;
const Brackets$4 = Brackets$5;
const CDC$5 = CDC$6;
const CDO$5 = CDO$6;
const ClassSelector$4 = ClassSelector$5;
const Combinator$4 = Combinator$5;
const Comment$7 = Comment$8;
const Declaration$6 = Declaration$7;
const DeclarationList$4 = DeclarationList$5;
const Dimension$7 = Dimension$8;
const Function$4 = _Function$1;
const Hash$5 = Hash$6;
const Identifier$4 = Identifier$5;
const IdSelector$4 = IdSelector$5;
const MediaFeature$4 = MediaFeature$5;
const MediaQuery$4 = MediaQuery$5;
const MediaQueryList$4 = MediaQueryList$5;
const NestingSelector$1 = NestingSelector$2;
const Nth$4 = Nth$5;
const Number$1$2 = _Number$6;
const Operator$4 = Operator$5;
const Parentheses$4 = Parentheses$5;
const Percentage$7 = Percentage$8;
const PseudoClassSelector$4 = PseudoClassSelector$5;
const PseudoElementSelector$4 = PseudoElementSelector$5;
const Ratio$4 = Ratio$5;
const Raw$6 = Raw$7;
const Rule$6 = Rule$7;
const Selector$6 = Selector$7;
const SelectorList$4 = SelectorList$5;
const String$1$2 = _String$1;
const StyleSheet$4 = StyleSheet$5;
const TypeSelector$6 = TypeSelector$7;
const UnicodeRange$4 = UnicodeRange$5;
const Url$7 = Url$8;
const Value$6 = Value$7;
const WhiteSpace$7 = WhiteSpace$8;
node$1.AnPlusB = AnPlusB$4;
node$1.Atrule = Atrule$8;
node$1.AtrulePrelude = AtrulePrelude$4;
node$1.AttributeSelector = AttributeSelector$6;
node$1.Block = Block$4;
node$1.Brackets = Brackets$4;
node$1.CDC = CDC$5;
node$1.CDO = CDO$5;
node$1.ClassSelector = ClassSelector$4;
node$1.Combinator = Combinator$4;
node$1.Comment = Comment$7;
node$1.Declaration = Declaration$6;
node$1.DeclarationList = DeclarationList$4;
node$1.Dimension = Dimension$7;
node$1.Function = Function$4;
node$1.Hash = Hash$5;
node$1.Identifier = Identifier$4;
node$1.IdSelector = IdSelector$4;
node$1.MediaFeature = MediaFeature$4;
node$1.MediaQuery = MediaQuery$4;
node$1.MediaQueryList = MediaQueryList$4;
node$1.NestingSelector = NestingSelector$1;
node$1.Nth = Nth$4;
node$1.Number = Number$1$2;
node$1.Operator = Operator$4;
node$1.Parentheses = Parentheses$4;
node$1.Percentage = Percentage$7;
node$1.PseudoClassSelector = PseudoClassSelector$4;
node$1.PseudoElementSelector = PseudoElementSelector$4;
node$1.Ratio = Ratio$4;
node$1.Raw = Raw$6;
node$1.Rule = Rule$6;
node$1.Selector = Selector$6;
node$1.SelectorList = SelectorList$4;
node$1.String = String$1$2;
node$1.StyleSheet = StyleSheet$4;
node$1.TypeSelector = TypeSelector$6;
node$1.UnicodeRange = UnicodeRange$4;
node$1.Url = Url$7;
node$1.Value = Value$6;
node$1.WhiteSpace = WhiteSpace$7;
const data$2 = data$3;
const index$f = node$1;
const lexerConfig$1 = {
generic: true,
...data$2,
node: index$f
};
var lexer$6 = lexerConfig$1;
var scope$1 = {};
const types$Y = types$1K;
const NUMBERSIGN$6 = 0x0023; // U+0023 NUMBER SIGN (#)
const ASTERISK$8 = 0x002A; // U+002A ASTERISK (*)
const PLUSSIGN$b = 0x002B; // U+002B PLUS SIGN (+)
const HYPHENMINUS$7 = 0x002D; // U+002D HYPHEN-MINUS (-)
const SOLIDUS$7 = 0x002F; // U+002F SOLIDUS (/)
const U$2 = 0x0075; // U+0075 LATIN SMALL LETTER U (u)
function defaultRecognizer$1(context) {
switch (this.tokenType) {
case types$Y.Hash:
return this.Hash();
case types$Y.Comma:
return this.Operator();
case types$Y.LeftParenthesis:
return this.Parentheses(this.readSequence, context.recognizer);
case types$Y.LeftSquareBracket:
return this.Brackets(this.readSequence, context.recognizer);
case types$Y.String:
return this.String();
case types$Y.Dimension:
return this.Dimension();
case types$Y.Percentage:
return this.Percentage();
case types$Y.Number:
return this.Number();
case types$Y.Function:
return this.cmpStr(this.tokenStart, this.tokenEnd, 'url(')
? this.Url()
: this.Function(this.readSequence, context.recognizer);
case types$Y.Url:
return this.Url();
case types$Y.Ident:
// check for unicode range, it should start with u+ or U+
if (this.cmpChar(this.tokenStart, U$2) &&
this.cmpChar(this.tokenStart + 1, PLUSSIGN$b)) {
return this.UnicodeRange();
} else {
return this.Identifier();
}
case types$Y.Delim: {
const code = this.charCodeAt(this.tokenStart);
if (code === SOLIDUS$7 ||
code === ASTERISK$8 ||
code === PLUSSIGN$b ||
code === HYPHENMINUS$7) {
return this.Operator(); // TODO: replace with Delim
}
// TODO: produce a node with Delim node type
if (code === NUMBERSIGN$6) {
this.error('Hex or identifier is expected', this.tokenStart + 1);
}
break;
}
}
}
var _default$5 = defaultRecognizer$1;
const _default$4 = _default$5;
const atrulePrelude$3 = {
getNode: _default$4
};
var atrulePrelude_1$1 = atrulePrelude$3;
const types$X = types$1K;
const NUMBERSIGN$5 = 0x0023; // U+0023 NUMBER SIGN (#)
const AMPERSAND$2 = 0x0026; // U+0026 AMPERSAND (&)
const ASTERISK$7 = 0x002A; // U+002A ASTERISK (*)
const PLUSSIGN$a = 0x002B; // U+002B PLUS SIGN (+)
const SOLIDUS$6 = 0x002F; // U+002F SOLIDUS (/)
const FULLSTOP$3 = 0x002E; // U+002E FULL STOP (.)
const GREATERTHANSIGN$3 = 0x003E; // U+003E GREATER-THAN SIGN (>)
const VERTICALLINE$4 = 0x007C; // U+007C VERTICAL LINE (|)
const TILDE$3 = 0x007E; // U+007E TILDE (~)
function onWhiteSpace$1(next, children) {
if (children.last !== null && children.last.type !== 'Combinator' &&
next !== null && next.type !== 'Combinator') {
children.push({ // FIXME: this.Combinator() should be used instead
type: 'Combinator',
loc: null,
name: ' '
});
}
}
function getNode$1() {
switch (this.tokenType) {
case types$X.LeftSquareBracket:
return this.AttributeSelector();
case types$X.Hash:
return this.IdSelector();
case types$X.Colon:
if (this.lookupType(1) === types$X.Colon) {
return this.PseudoElementSelector();
} else {
return this.PseudoClassSelector();
}
case types$X.Ident:
return this.TypeSelector();
case types$X.Number:
case types$X.Percentage:
return this.Percentage();
case types$X.Dimension:
// throws when .123ident
if (this.charCodeAt(this.tokenStart) === FULLSTOP$3) {
this.error('Identifier is expected', this.tokenStart + 1);
}
break;
case types$X.Delim: {
const code = this.charCodeAt(this.tokenStart);
switch (code) {
case PLUSSIGN$a:
case GREATERTHANSIGN$3:
case TILDE$3:
case SOLIDUS$6: // /deep/
return this.Combinator();
case FULLSTOP$3:
return this.ClassSelector();
case ASTERISK$7:
case VERTICALLINE$4:
return this.TypeSelector();
case NUMBERSIGN$5:
return this.IdSelector();
case AMPERSAND$2:
return this.NestingSelector();
}
break;
}
}
}
const Selector$5 = {
onWhiteSpace: onWhiteSpace$1,
getNode: getNode$1
};
var selector$5 = Selector$5;
// legacy IE function
// expression( <any-value> )
function expressionFn$1() {
return this.createSingleNodeList(
this.Raw(this.tokenIndex, null, false)
);
}
var expression$3 = expressionFn$1;
const types$W = types$1K;
// var( <ident> , <value>? )
function varFn$1() {
const children = this.createList();
this.skipSC();
// NOTE: Don't check more than a first argument is an ident, rest checks are for lexer
children.push(this.Identifier());
this.skipSC();
if (this.tokenType === types$W.Comma) {
children.push(this.Operator());
const startIndex = this.tokenIndex;
const value = this.parseCustomProperty
? this.Value(null)
: this.Raw(this.tokenIndex, this.consumeUntilExclamationMarkOrSemicolon, false);
if (value.type === 'Value' && value.children.isEmpty) {
for (let offset = startIndex - this.tokenIndex; offset <= 0; offset++) {
if (this.lookupType(offset) === types$W.WhiteSpace) {
value.children.appendData({
type: 'WhiteSpace',
loc: null,
value: ' '
});
break;
}
}
}
children.push(value);
}
return children;
}
var _var$3 = varFn$1;
const _default$3 = _default$5;
const expression$2 = expression$3;
const _var$2 = _var$3;
function isPlusMinusOperator$1(node) {
return (
node !== null &&
node.type === 'Operator' &&
(node.value[node.value.length - 1] === '-' || node.value[node.value.length - 1] === '+')
);
}
const value$3 = {
getNode: _default$3,
onWhiteSpace(next, children) {
if (isPlusMinusOperator$1(next)) {
next.value = ' ' + next.value;
}
if (isPlusMinusOperator$1(children.last)) {
children.last.value += ' ';
}
},
'expression': expression$2,
'var': _var$2
};
var value_1$1 = value$3;
const atrulePrelude$2 = atrulePrelude_1$1;
const selector$4 = selector$5;
const value$2 = value_1$1;
scope$1.AtrulePrelude = atrulePrelude$2;
scope$1.Selector = selector$4;
scope$1.Value = value$2;
const fontFace$3 = {
parse: {
prelude: null,
block() {
return this.Block(true);
}
}
};
var fontFace_1$1 = fontFace$3;
const types$V = types$1K;
const importAtrule$1 = {
parse: {
prelude() {
const children = this.createList();
this.skipSC();
switch (this.tokenType) {
case types$V.String:
children.push(this.String());
break;
case types$V.Url:
case types$V.Function:
children.push(this.Url());
break;
default:
this.error('String or url() is expected');
}
if (this.lookupNonWSType(0) === types$V.Ident ||
this.lookupNonWSType(0) === types$V.LeftParenthesis) {
children.push(this.MediaQueryList());
}
return children;
},
block: null
}
};
var _import$3 = importAtrule$1;
const media$3 = {
parse: {
prelude() {
return this.createSingleNodeList(
this.MediaQueryList()
);
},
block(isStyleBlock = false) {
return this.Block(isStyleBlock);
}
}
};
var media_1$1 = media$3;
const nest$1 = {
parse: {
prelude() {
return this.createSingleNodeList(
this.SelectorList()
);
},
block() {
return this.Block(true);
}
}
};
var nest_1 = nest$1;
const page$3 = {
parse: {
prelude() {
return this.createSingleNodeList(
this.SelectorList()
);
},
block() {
return this.Block(true);
}
}
};
var page_1$1 = page$3;
const types$U = types$1K;
function consumeRaw$6() {
return this.createSingleNodeList(
this.Raw(this.tokenIndex, null, false)
);
}
function parentheses$1() {
this.skipSC();
if (this.tokenType === types$U.Ident &&
this.lookupNonWSType(1) === types$U.Colon) {
return this.createSingleNodeList(
this.Declaration()
);
}
return readSequence$2.call(this);
}
function readSequence$2() {
const children = this.createList();
let child;
this.skipSC();
scan:
while (!this.eof) {
switch (this.tokenType) {
case types$U.Comment:
case types$U.WhiteSpace:
this.next();
continue;
case types$U.Function:
child = this.Function(consumeRaw$6, this.scope.AtrulePrelude);
break;
case types$U.Ident:
child = this.Identifier();
break;
case types$U.LeftParenthesis:
child = this.Parentheses(parentheses$1, this.scope.AtrulePrelude);
break;
default:
break scan;
}
children.push(child);
}
return children;
}
const supports$3 = {
parse: {
prelude() {
const children = readSequence$2.call(this);
if (this.getFirstListNode(children) === null) {
this.error('Condition is expected');
}
return children;
},
block(isStyleBlock = false) {
return this.Block(isStyleBlock);
}
}
};
var supports_1$1 = supports$3;
const fontFace$2 = fontFace_1$1;
const _import$2 = _import$3;
const media$2 = media_1$1;
const nest = nest_1;
const page$2 = page_1$1;
const supports$2 = supports_1$1;
const atrule$1 = {
'font-face': fontFace$2,
'import': _import$2,
media: media$2,
nest,
page: page$2,
supports: supports$2
};
var atrule_1$1 = atrule$1;
const selectorList$1 = {
parse() {
return this.createSingleNodeList(
this.SelectorList()
);
}
};
const selector$3 = {
parse() {
return this.createSingleNodeList(
this.Selector()
);
}
};
const identList$1 = {
parse() {
return this.createSingleNodeList(
this.Identifier()
);
}
};
const nth$2 = {
parse() {
return this.createSingleNodeList(
this.Nth()
);
}
};
const pseudo$1 = {
'dir': identList$1,
'has': selectorList$1,
'lang': identList$1,
'matches': selectorList$1,
'is': selectorList$1,
'-moz-any': selectorList$1,
'-webkit-any': selectorList$1,
'where': selectorList$1,
'not': selectorList$1,
'nth-child': nth$2,
'nth-last-child': nth$2,
'nth-last-of-type': nth$2,
'nth-of-type': nth$2,
'slotted': selector$3,
'host': selector$3,
'host-context': selector$3
};
var pseudo_1$1 = pseudo$1;
var indexParse$3 = {};
const AnPlusB$3 = AnPlusB$5;
const Atrule$7 = Atrule$9;
const AtrulePrelude$3 = AtrulePrelude$5;
const AttributeSelector$5 = AttributeSelector$7;
const Block$3 = Block$5;
const Brackets$3 = Brackets$5;
const CDC$4 = CDC$6;
const CDO$4 = CDO$6;
const ClassSelector$3 = ClassSelector$5;
const Combinator$3 = Combinator$5;
const Comment$6 = Comment$8;
const Declaration$5 = Declaration$7;
const DeclarationList$3 = DeclarationList$5;
const Dimension$6 = Dimension$8;
const Function$3 = _Function$1;
const Hash$4 = Hash$6;
const Identifier$3 = Identifier$5;
const IdSelector$3 = IdSelector$5;
const MediaFeature$3 = MediaFeature$5;
const MediaQuery$3 = MediaQuery$5;
const MediaQueryList$3 = MediaQueryList$5;
const NestingSelector = NestingSelector$2;
const Nth$3 = Nth$5;
const Number$4 = _Number$6;
const Operator$3 = Operator$5;
const Parentheses$3 = Parentheses$5;
const Percentage$6 = Percentage$8;
const PseudoClassSelector$3 = PseudoClassSelector$5;
const PseudoElementSelector$3 = PseudoElementSelector$5;
const Ratio$3 = Ratio$5;
const Raw$5 = Raw$7;
const Rule$5 = Rule$7;
const Selector$4 = Selector$7;
const SelectorList$3 = SelectorList$5;
const String$3 = _String$1;
const StyleSheet$3 = StyleSheet$5;
const TypeSelector$5 = TypeSelector$7;
const UnicodeRange$3 = UnicodeRange$5;
const Url$6 = Url$8;
const Value$5 = Value$7;
const WhiteSpace$6 = WhiteSpace$8;
indexParse$3.AnPlusB = AnPlusB$3.parse;
indexParse$3.Atrule = Atrule$7.parse;
indexParse$3.AtrulePrelude = AtrulePrelude$3.parse;
indexParse$3.AttributeSelector = AttributeSelector$5.parse;
indexParse$3.Block = Block$3.parse;
indexParse$3.Brackets = Brackets$3.parse;
indexParse$3.CDC = CDC$4.parse;
indexParse$3.CDO = CDO$4.parse;
indexParse$3.ClassSelector = ClassSelector$3.parse;
indexParse$3.Combinator = Combinator$3.parse;
indexParse$3.Comment = Comment$6.parse;
indexParse$3.Declaration = Declaration$5.parse;
indexParse$3.DeclarationList = DeclarationList$3.parse;
indexParse$3.Dimension = Dimension$6.parse;
indexParse$3.Function = Function$3.parse;
indexParse$3.Hash = Hash$4.parse;
indexParse$3.Identifier = Identifier$3.parse;
indexParse$3.IdSelector = IdSelector$3.parse;
indexParse$3.MediaFeature = MediaFeature$3.parse;
indexParse$3.MediaQuery = MediaQuery$3.parse;
indexParse$3.MediaQueryList = MediaQueryList$3.parse;
indexParse$3.NestingSelector = NestingSelector.parse;
indexParse$3.Nth = Nth$3.parse;
indexParse$3.Number = Number$4.parse;
indexParse$3.Operator = Operator$3.parse;
indexParse$3.Parentheses = Parentheses$3.parse;
indexParse$3.Percentage = Percentage$6.parse;
indexParse$3.PseudoClassSelector = PseudoClassSelector$3.parse;
indexParse$3.PseudoElementSelector = PseudoElementSelector$3.parse;
indexParse$3.Ratio = Ratio$3.parse;
indexParse$3.Raw = Raw$5.parse;
indexParse$3.Rule = Rule$5.parse;
indexParse$3.Selector = Selector$4.parse;
indexParse$3.SelectorList = SelectorList$3.parse;
indexParse$3.String = String$3.parse;
indexParse$3.StyleSheet = StyleSheet$3.parse;
indexParse$3.TypeSelector = TypeSelector$5.parse;
indexParse$3.UnicodeRange = UnicodeRange$3.parse;
indexParse$3.Url = Url$6.parse;
indexParse$3.Value = Value$5.parse;
indexParse$3.WhiteSpace = WhiteSpace$6.parse;
const index$e = scope$1;
const index$1$4 = atrule_1$1;
const index$2$2 = pseudo_1$1;
const indexParse$2 = indexParse$3;
const config$3 = {
parseContext: {
default: 'StyleSheet',
stylesheet: 'StyleSheet',
atrule: 'Atrule',
atrulePrelude(options) {
return this.AtrulePrelude(options.atrule ? String(options.atrule) : null);
},
mediaQueryList: 'MediaQueryList',
mediaQuery: 'MediaQuery',
rule: 'Rule',
selectorList: 'SelectorList',
selector: 'Selector',
block() {
return this.Block(true);
},
declarationList: 'DeclarationList',
declaration: 'Declaration',
value: 'Value'
},
scope: index$e,
atrule: index$1$4,
pseudo: index$2$2,
node: indexParse$2
};
var parser$3 = config$3;
const index$d = node$1;
const config$2 = {
node: index$d
};
var walker$3 = config$2;
const create$9 = create_1$1;
const lexer$5 = lexer$6;
const parser$2 = parser$3;
const walker$2 = walker$3;
const syntax$3 = create$9({
...lexer$5,
...parser$2,
...walker$2
});
var syntax_1$1 = syntax$3;
var version$b = {};
const name$G = "css-tree";
const version$a = "2.3.1";
const description$2 = "A tool set for CSS: fast detailed parser (CSS → AST), walker (AST traversal), generator (AST → CSS) and lexer (validation and matching) based on specs and browser implementations";
const author$2 = "Roman Dvornov <rdvornov@gmail.com> (https://github.com/lahmatiy)";
const license$2 = "MIT";
const repository$2 = "csstree/csstree";
const keywords$3 = [
"css",
"ast",
"tokenizer",
"parser",
"walker",
"lexer",
"generator",
"utils",
"syntax",
"validation"
];
const type$2 = "module";
const module$2 = "./lib/index.js";
const main$2 = "./cjs/index.cjs";
const exports$2 = {
".": {
"import": "./lib/index.js",
require: "./cjs/index.cjs"
},
"./dist/*": "./dist/*.js",
"./package.json": "./package.json",
"./tokenizer": {
"import": "./lib/tokenizer/index.js",
require: "./cjs/tokenizer/index.cjs"
},
"./parser": {
"import": "./lib/parser/index.js",
require: "./cjs/parser/index.cjs"
},
"./selector-parser": {
"import": "./lib/parser/parse-selector.js",
require: "./cjs/parser/parse-selector.cjs"
},
"./generator": {
"import": "./lib/generator/index.js",
require: "./cjs/generator/index.cjs"
},
"./walker": {
"import": "./lib/walker/index.js",
require: "./cjs/walker/index.cjs"
},
"./convertor": {
"import": "./lib/convertor/index.js",
require: "./cjs/convertor/index.cjs"
},
"./lexer": {
"import": "./lib/lexer/index.js",
require: "./cjs/lexer/index.cjs"
},
"./definition-syntax": {
"import": "./lib/definition-syntax/index.js",
require: "./cjs/definition-syntax/index.cjs"
},
"./definition-syntax-data": {
"import": "./lib/data.js",
require: "./cjs/data.cjs"
},
"./definition-syntax-data-patch": {
"import": "./lib/data-patch.js",
require: "./cjs/data-patch.cjs"
},
"./utils": {
"import": "./lib/utils/index.js",
require: "./cjs/utils/index.cjs"
}
};
const browser$2 = {
"./cjs/data.cjs": "./dist/data.cjs",
"./cjs/version.cjs": "./dist/version.cjs",
"./lib/data.js": "./dist/data.js",
"./lib/version.js": "./dist/version.js"
};
const unpkg$2 = "dist/csstree.esm.js";
const jsdelivr$2 = "dist/csstree.esm.js";
const scripts$2 = {
watch: "npm run build -- --watch",
build: "npm run bundle && npm run esm-to-cjs --",
"build-and-test": "npm run build && npm run test:dist && npm run test:cjs",
bundle: "node scripts/bundle",
"bundle-and-test": "npm run bundle && npm run test:dist",
"esm-to-cjs": "node scripts/esm-to-cjs.cjs",
"esm-to-cjs-and-test": "npm run esm-to-cjs && npm run test:cjs",
lint: "eslint lib scripts && node scripts/review-syntax-patch --lint && node scripts/update-docs --lint",
"lint-and-test": "npm run lint && npm test",
"update:docs": "node scripts/update-docs",
"review:syntax-patch": "node scripts/review-syntax-patch",
test: "mocha lib/__tests --reporter ${REPORTER:-progress}",
"test:cjs": "mocha cjs/__tests --reporter ${REPORTER:-progress}",
"test:dist": "mocha dist/__tests --reporter ${REPORTER:-progress}",
coverage: "c8 --exclude lib/__tests --reporter=lcovonly npm test",
prepublishOnly: "npm run lint-and-test && npm run build-and-test",
hydrogen: "node --trace-hydrogen --trace-phase=Z --trace-deopt --code-comments --hydrogen-track-positions --redirect-code-traces --redirect-code-traces-to=code.asm --trace_hydrogen_file=code.cfg --print-opt-code bin/parse --stat -o /dev/null"
};
const dependencies$2 = {
"mdn-data": "2.0.30",
"source-map-js": "^1.0.1"
};
const devDependencies$2 = {
c8: "^7.12.0",
clap: "^2.0.1",
esbuild: "^0.14.53",
eslint: "^8.4.1",
"json-to-ast": "^2.1.0",
mocha: "^9.2.2",
rollup: "^2.68.0"
};
const engines$2 = {
node: "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
};
const files$2 = [
"data",
"dist",
"cjs",
"!cjs/__tests",
"lib",
"!lib/__tests"
];
const require$$0$3 = {
name: name$G,
version: version$a,
description: description$2,
author: author$2,
license: license$2,
repository: repository$2,
keywords: keywords$3,
type: type$2,
module: module$2,
main: main$2,
exports: exports$2,
browser: browser$2,
unpkg: unpkg$2,
jsdelivr: jsdelivr$2,
scripts: scripts$2,
dependencies: dependencies$2,
devDependencies: devDependencies$2,
engines: engines$2,
files: files$2
};
const { version: version$9 } = require$$0$3;
version$b.version = version$9;
var definitionSyntax$1 = {};
const SyntaxError$6 = _SyntaxError$2;
const generate$N = generate$1u;
const parse$N = parse$1u;
const walk$7 = walk$a;
definitionSyntax$1.SyntaxError = SyntaxError$6.SyntaxError;
definitionSyntax$1.generate = generate$N.generate;
definitionSyntax$1.parse = parse$N.parse;
definitionSyntax$1.walk = walk$7.walk;
var clone$5 = {};
const List$9 = List$f;
function clone$4(node) {
const result = {};
for (const key in node) {
let value = node[key];
if (value) {
if (Array.isArray(value) || value instanceof List$9.List) {
value = value.map(clone$4);
} else if (value.constructor === Object) {
value = clone$4(value);
}
}
result[key] = value;
}
return result;
}
clone$5.clone = clone$4;
var ident$3 = {};
const charCodeDefinitions$d = charCodeDefinitions$p;
const utils$l = utils$u;
const REVERSE_SOLIDUS$3 = 0x005c; // U+005C REVERSE SOLIDUS (\)
function decode$3(str) {
const end = str.length - 1;
let decoded = '';
for (let i = 0; i < str.length; i++) {
let code = str.charCodeAt(i);
if (code === REVERSE_SOLIDUS$3) {
// special case at the ending
if (i === end) {
// if the next input code point is EOF, do nothing
break;
}
code = str.charCodeAt(++i);
// consume escaped
if (charCodeDefinitions$d.isValidEscape(REVERSE_SOLIDUS$3, code)) {
const escapeStart = i - 1;
const escapeEnd = utils$l.consumeEscaped(str, escapeStart);
i = escapeEnd - 1;
decoded += utils$l.decodeEscaped(str.substring(escapeStart + 1, escapeEnd));
} else {
// \r\n
if (code === 0x000d && str.charCodeAt(i + 1) === 0x000a) {
i++;
}
}
} else {
decoded += str[i];
}
}
return decoded;
}
// https://drafts.csswg.org/cssom/#serialize-an-identifier
// § 2.1. Common Serializing Idioms
function encode$3(str) {
let encoded = '';
// If the character is the first character and is a "-" (U+002D),
// and there is no second character, then the escaped character.
// Note: That's means a single dash string "-" return as escaped dash,
// so move the condition out of the main loop
if (str.length === 1 && str.charCodeAt(0) === 0x002D) {
return '\\-';
}
// To serialize an identifier means to create a string represented
// by the concatenation of, for each character of the identifier:
for (let i = 0; i < str.length; i++) {
const code = str.charCodeAt(i);
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER (U+FFFD).
if (code === 0x0000) {
encoded += '\uFFFD';
continue;
}
if (
// If the character is in the range [\1-\1f] (U+0001 to U+001F) or is U+007F ...
// Note: Do not compare with 0x0001 since 0x0000 is precessed before
code <= 0x001F || code === 0x007F ||
// [or] ... is in the range [0-9] (U+0030 to U+0039),
(code >= 0x0030 && code <= 0x0039 && (
// If the character is the first character ...
i === 0 ||
// If the character is the second character ... and the first character is a "-" (U+002D)
i === 1 && str.charCodeAt(0) === 0x002D
))
) {
// ... then the character escaped as code point.
encoded += '\\' + code.toString(16) + ' ';
continue;
}
// If the character is not handled by one of the above rules and is greater
// than or equal to U+0080, is "-" (U+002D) or "_" (U+005F), or is in one
// of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to U+005A),
// or \[a-z] (U+0061 to U+007A), then the character itself.
if (charCodeDefinitions$d.isName(code)) {
encoded += str.charAt(i);
} else {
// Otherwise, the escaped character.
encoded += '\\' + str.charAt(i);
}
}
return encoded;
}
ident$3.decode = decode$3;
ident$3.encode = encode$3;
const index$1$3 = syntax_1$1;
const version$8 = version$b;
const create$8 = create_1$1;
const List$8 = List$f;
const Lexer$4 = Lexer$7;
const index$c = definitionSyntax$1;
const clone$3 = clone$5;
const names$1$1 = names$c;
const ident$2 = ident$3;
const string$4 = string$7;
const url$3 = url$5;
const types$T = types$1K;
const names$9 = names$g;
const TokenStream$5 = TokenStream$9;
const {
tokenize: tokenize$3,
parse: parse$M,
generate: generate$M,
lexer: lexer$4,
createLexer: createLexer$1,
walk: walk$6,
find: find$2,
findLast: findLast$2,
findAll: findAll$2,
toPlainObject: toPlainObject$2,
fromPlainObject: fromPlainObject$2,
fork: fork$1
} = index$1$3;
cjs$2.version = version$8.version;
cjs$2.createSyntax = create$8;
cjs$2.List = List$8.List;
cjs$2.Lexer = Lexer$4.Lexer;
cjs$2.definitionSyntax = index$c;
cjs$2.clone = clone$3.clone;
cjs$2.isCustomProperty = names$1$1.isCustomProperty;
cjs$2.keyword = names$1$1.keyword;
cjs$2.property = names$1$1.property;
cjs$2.vendorPrefix = names$1$1.vendorPrefix;
cjs$2.ident = ident$2;
cjs$2.string = string$4;
cjs$2.url = url$3;
cjs$2.tokenTypes = types$T;
cjs$2.tokenNames = names$9;
cjs$2.TokenStream = TokenStream$5.TokenStream;
cjs$2.createLexer = createLexer$1;
cjs$2.find = find$2;
cjs$2.findAll = findAll$2;
cjs$2.findLast = findLast$2;
cjs$2.fork = fork$1;
cjs$2.fromPlainObject = fromPlainObject$2;
cjs$2.generate = generate$M;
cjs$2.lexer = lexer$4;
cjs$2.parse = parse$M;
cjs$2.toPlainObject = toPlainObject$2;
cjs$2.tokenize = tokenize$3;
cjs$2.walk = walk$6;
var cjs$1 = {};
var version$7 = {};
const name$F = "csso";
const version$6 = "5.0.5";
const description$1 = "CSS minifier with structural optimisations";
const author$1 = "Sergey Kryzhanovsky <skryzhanovsky@ya.ru> (https://github.com/afelix)";
const maintainers = [
{
name: "Roman Dvornov",
email: "rdvornov@gmail.com",
"github-username": "lahmatiy"
}
];
const repository$1 = "css/csso";
const license$1 = "MIT";
const keywords$2 = [
"css",
"compress",
"minifier",
"minify",
"optimise",
"optimisation",
"csstree"
];
const type$1 = "module";
const unpkg$1 = "dist/csso.esm.js";
const jsdelivr$1 = "dist/csso.esm.js";
const browser$1 = {
"./cjs/version.cjs": "./dist/version.cjs",
"./lib/version.js": "./dist/version.js"
};
const main$1 = "./cjs/index.cjs";
const module$1 = "./lib/index.js";
const exports$1 = {
".": {
"import": "./lib/index.js",
require: "./cjs/index.cjs"
},
"./syntax": {
"import": "./lib/syntax.js",
require: "./cjs/syntax.cjs"
},
"./dist/*": "./dist/*.js",
"./package.json": "./package.json"
};
const scripts$1 = {
test: "mocha test --reporter ${REPORTER:-progress}",
"test:cjs": "mocha cjs-test --reporter ${REPORTER:-progress}",
"test:dist": "mocha dist/test --reporter ${REPORTER:-progress}",
lint: "eslint lib scripts test",
"lint-and-test": "npm run lint && npm test",
build: "npm run bundle && npm run esm-to-cjs",
"build-and-test": "npm run build && npm run test:dist && npm run test:cjs",
bundle: "node scripts/bundle",
"bundle-and-test": "npm run bundle && npm run test:dist",
"esm-to-cjs": "node scripts/esm-to-cjs.cjs",
"esm-to-cjs-and-test": "npm run esm-to-cjs && npm run test:cjs",
coverage: "c8 --reporter=lcovonly npm test",
prepublishOnly: "npm run lint-and-test && npm run build-and-test",
hydrogen: "node --trace-hydrogen --trace-phase=Z --trace-deopt --code-comments --hydrogen-track-positions --redirect-code-traces --redirect-code-traces-to=code.asm --trace_hydrogen_file=code.cfg --print-opt-code bin/csso --stat -o /dev/null"
};
const dependencies$1 = {
"css-tree": "~2.2.0"
};
const devDependencies$1 = {
c8: "^7.10.0",
esbuild: "^0.14.54",
eslint: "^7.24.0",
mocha: "^9.2.2",
rollup: "^2.60.2",
"source-map-js": "^1.0.1"
};
const engines$1 = {
node: "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
npm: ">=7.0.0"
};
const files$1 = [
"dist",
"!dist/test",
"cjs",
"lib"
];
const require$$0$2 = {
name: name$F,
version: version$6,
description: description$1,
author: author$1,
maintainers: maintainers,
repository: repository$1,
license: license$1,
keywords: keywords$2,
type: type$1,
unpkg: unpkg$1,
jsdelivr: jsdelivr$1,
browser: browser$1,
main: main$1,
module: module$1,
exports: exports$1,
scripts: scripts$1,
dependencies: dependencies$1,
devDependencies: devDependencies$1,
engines: engines$1,
files: files$1
};
const { version: version$5 } = require$$0$2;
version$7.version = version$5;
var syntax$2 = {};
var cjs = {};
var tokenizer$2 = {};
var types$S = {};
// CSS Syntax Module Level 3
// https://www.w3.org/TR/css-syntax-3/
const EOF$1 = 0; // <EOF-token>
const Ident = 1; // <ident-token>
const Function$2 = 2; // <function-token>
const AtKeyword = 3; // <at-keyword-token>
const Hash$3 = 4; // <hash-token>
const String$2 = 5; // <string-token>
const BadString = 6; // <bad-string-token>
const Url$5 = 7; // <url-token>
const BadUrl = 8; // <bad-url-token>
const Delim = 9; // <delim-token>
const Number$3 = 10; // <number-token>
const Percentage$5 = 11; // <percentage-token>
const Dimension$5 = 12; // <dimension-token>
const WhiteSpace$5 = 13; // <whitespace-token>
const CDO$3 = 14; // <CDO-token>
const CDC$3 = 15; // <CDC-token>
const Colon = 16; // <colon-token> :
const Semicolon = 17; // <semicolon-token> ;
const Comma = 18; // <comma-token> ,
const LeftSquareBracket = 19; // <[-token>
const RightSquareBracket = 20; // <]-token>
const LeftParenthesis = 21; // <(-token>
const RightParenthesis = 22; // <)-token>
const LeftCurlyBracket = 23; // <{-token>
const RightCurlyBracket = 24; // <}-token>
const Comment$5 = 25;
types$S.AtKeyword = AtKeyword;
types$S.BadString = BadString;
types$S.BadUrl = BadUrl;
types$S.CDC = CDC$3;
types$S.CDO = CDO$3;
types$S.Colon = Colon;
types$S.Comma = Comma;
types$S.Comment = Comment$5;
types$S.Delim = Delim;
types$S.Dimension = Dimension$5;
types$S.EOF = EOF$1;
types$S.Function = Function$2;
types$S.Hash = Hash$3;
types$S.Ident = Ident;
types$S.LeftCurlyBracket = LeftCurlyBracket;
types$S.LeftParenthesis = LeftParenthesis;
types$S.LeftSquareBracket = LeftSquareBracket;
types$S.Number = Number$3;
types$S.Percentage = Percentage$5;
types$S.RightCurlyBracket = RightCurlyBracket;
types$S.RightParenthesis = RightParenthesis;
types$S.RightSquareBracket = RightSquareBracket;
types$S.Semicolon = Semicolon;
types$S.String = String$2;
types$S.Url = Url$5;
types$S.WhiteSpace = WhiteSpace$5;
var charCodeDefinitions$c = {};
const EOF = 0;
// https://drafts.csswg.org/css-syntax-3/
// § 4.2. Definitions
// digit
// A code point between U+0030 DIGIT ZERO (0) and U+0039 DIGIT NINE (9).
function isDigit$1(code) {
return code >= 0x0030 && code <= 0x0039;
}
// hex digit
// A digit, or a code point between U+0041 LATIN CAPITAL LETTER A (A) and U+0046 LATIN CAPITAL LETTER F (F),
// or a code point between U+0061 LATIN SMALL LETTER A (a) and U+0066 LATIN SMALL LETTER F (f).
function isHexDigit(code) {
return (
isDigit$1(code) || // 0 .. 9
(code >= 0x0041 && code <= 0x0046) || // A .. F
(code >= 0x0061 && code <= 0x0066) // a .. f
);
}
// uppercase letter
// A code point between U+0041 LATIN CAPITAL LETTER A (A) and U+005A LATIN CAPITAL LETTER Z (Z).
function isUppercaseLetter(code) {
return code >= 0x0041 && code <= 0x005A;
}
// lowercase letter
// A code point between U+0061 LATIN SMALL LETTER A (a) and U+007A LATIN SMALL LETTER Z (z).
function isLowercaseLetter(code) {
return code >= 0x0061 && code <= 0x007A;
}
// letter
// An uppercase letter or a lowercase letter.
function isLetter(code) {
return isUppercaseLetter(code) || isLowercaseLetter(code);
}
// non-ASCII code point
// A code point with a value equal to or greater than U+0080 <control>.
function isNonAscii(code) {
return code >= 0x0080;
}
// name-start code point
// A letter, a non-ASCII code point, or U+005F LOW LINE (_).
function isNameStart(code) {
return isLetter(code) || isNonAscii(code) || code === 0x005F;
}
// name code point
// A name-start code point, a digit, or U+002D HYPHEN-MINUS (-).
function isName(code) {
return isNameStart(code) || isDigit$1(code) || code === 0x002D;
}
// non-printable code point
// A code point between U+0000 NULL and U+0008 BACKSPACE, or U+000B LINE TABULATION,
// or a code point between U+000E SHIFT OUT and U+001F INFORMATION SEPARATOR ONE, or U+007F DELETE.
function isNonPrintable(code) {
return (
(code >= 0x0000 && code <= 0x0008) ||
(code === 0x000B) ||
(code >= 0x000E && code <= 0x001F) ||
(code === 0x007F)
);
}
// newline
// U+000A LINE FEED. Note that U+000D CARRIAGE RETURN and U+000C FORM FEED are not included in this definition,
// as they are converted to U+000A LINE FEED during preprocessing.
// TODO: we doesn't do a preprocessing, so check a code point for U+000D CARRIAGE RETURN and U+000C FORM FEED
function isNewline(code) {
return code === 0x000A || code === 0x000D || code === 0x000C;
}
// whitespace
// A newline, U+0009 CHARACTER TABULATION, or U+0020 SPACE.
function isWhiteSpace(code) {
return isNewline(code) || code === 0x0020 || code === 0x0009;
}
// § 4.3.8. Check if two code points are a valid escape
function isValidEscape(first, second) {
// If the first code point is not U+005C REVERSE SOLIDUS (\), return false.
if (first !== 0x005C) {
return false;
}
// Otherwise, if the second code point is a newline or EOF, return false.
if (isNewline(second) || second === EOF) {
return false;
}
// Otherwise, return true.
return true;
}
// § 4.3.9. Check if three code points would start an identifier
function isIdentifierStart(first, second, third) {
// Look at the first code point:
// U+002D HYPHEN-MINUS
if (first === 0x002D) {
// If the second code point is a name-start code point or a U+002D HYPHEN-MINUS,
// or the second and third code points are a valid escape, return true. Otherwise, return false.
return (
isNameStart(second) ||
second === 0x002D ||
isValidEscape(second, third)
);
}
// name-start code point
if (isNameStart(first)) {
// Return true.
return true;
}
// U+005C REVERSE SOLIDUS (\)
if (first === 0x005C) {
// If the first and second code points are a valid escape, return true. Otherwise, return false.
return isValidEscape(first, second);
}
// anything else
// Return false.
return false;
}
// § 4.3.10. Check if three code points would start a number
function isNumberStart(first, second, third) {
// Look at the first code point:
// U+002B PLUS SIGN (+)
// U+002D HYPHEN-MINUS (-)
if (first === 0x002B || first === 0x002D) {
// If the second code point is a digit, return true.
if (isDigit$1(second)) {
return 2;
}
// Otherwise, if the second code point is a U+002E FULL STOP (.)
// and the third code point is a digit, return true.
// Otherwise, return false.
return second === 0x002E && isDigit$1(third) ? 3 : 0;
}
// U+002E FULL STOP (.)
if (first === 0x002E) {
// If the second code point is a digit, return true. Otherwise, return false.
return isDigit$1(second) ? 2 : 0;
}
// digit
if (isDigit$1(first)) {
// Return true.
return 1;
}
// anything else
// Return false.
return 0;
}
//
// Misc
//
// detect BOM (https://en.wikipedia.org/wiki/Byte_order_mark)
function isBOM(code) {
// UTF-16BE
if (code === 0xFEFF) {
return 1;
}
// UTF-16LE
if (code === 0xFFFE) {
return 1;
}
return 0;
}
// Fast code category
// Only ASCII code points has a special meaning, that's why we define a maps for 0..127 codes only
const CATEGORY = new Array(0x80);
const EofCategory = 0x80;
const WhiteSpaceCategory = 0x82;
const DigitCategory = 0x83;
const NameStartCategory = 0x84;
const NonPrintableCategory = 0x85;
for (let i = 0; i < CATEGORY.length; i++) {
CATEGORY[i] =
isWhiteSpace(i) && WhiteSpaceCategory ||
isDigit$1(i) && DigitCategory ||
isNameStart(i) && NameStartCategory ||
isNonPrintable(i) && NonPrintableCategory ||
i || EofCategory;
}
function charCodeCategory(code) {
return code < 0x80 ? CATEGORY[code] : NameStartCategory;
}
charCodeDefinitions$c.DigitCategory = DigitCategory;
charCodeDefinitions$c.EofCategory = EofCategory;
charCodeDefinitions$c.NameStartCategory = NameStartCategory;
charCodeDefinitions$c.NonPrintableCategory = NonPrintableCategory;
charCodeDefinitions$c.WhiteSpaceCategory = WhiteSpaceCategory;
charCodeDefinitions$c.charCodeCategory = charCodeCategory;
charCodeDefinitions$c.isBOM = isBOM;
charCodeDefinitions$c.isDigit = isDigit$1;
charCodeDefinitions$c.isHexDigit = isHexDigit;
charCodeDefinitions$c.isIdentifierStart = isIdentifierStart;
charCodeDefinitions$c.isLetter = isLetter;
charCodeDefinitions$c.isLowercaseLetter = isLowercaseLetter;
charCodeDefinitions$c.isName = isName;
charCodeDefinitions$c.isNameStart = isNameStart;
charCodeDefinitions$c.isNewline = isNewline;
charCodeDefinitions$c.isNonAscii = isNonAscii;
charCodeDefinitions$c.isNonPrintable = isNonPrintable;
charCodeDefinitions$c.isNumberStart = isNumberStart;
charCodeDefinitions$c.isUppercaseLetter = isUppercaseLetter;
charCodeDefinitions$c.isValidEscape = isValidEscape;
charCodeDefinitions$c.isWhiteSpace = isWhiteSpace;
var utils$k = {};
const charCodeDefinitions$b = charCodeDefinitions$c;
function getCharCode(source, offset) {
return offset < source.length ? source.charCodeAt(offset) : 0;
}
function getNewlineLength(source, offset, code) {
if (code === 13 /* \r */ && getCharCode(source, offset + 1) === 10 /* \n */) {
return 2;
}
return 1;
}
function cmpChar(testStr, offset, referenceCode) {
let code = testStr.charCodeAt(offset);
// code.toLowerCase() for A..Z
if (charCodeDefinitions$b.isUppercaseLetter(code)) {
code = code | 32;
}
return code === referenceCode;
}
function cmpStr(testStr, start, end, referenceStr) {
if (end - start !== referenceStr.length) {
return false;
}
if (start < 0 || end > testStr.length) {
return false;
}
for (let i = start; i < end; i++) {
const referenceCode = referenceStr.charCodeAt(i - start);
let testCode = testStr.charCodeAt(i);
// testCode.toLowerCase() for A..Z
if (charCodeDefinitions$b.isUppercaseLetter(testCode)) {
testCode = testCode | 32;
}
if (testCode !== referenceCode) {
return false;
}
}
return true;
}
function findWhiteSpaceStart(source, offset) {
for (; offset >= 0; offset--) {
if (!charCodeDefinitions$b.isWhiteSpace(source.charCodeAt(offset))) {
break;
}
}
return offset + 1;
}
function findWhiteSpaceEnd(source, offset) {
for (; offset < source.length; offset++) {
if (!charCodeDefinitions$b.isWhiteSpace(source.charCodeAt(offset))) {
break;
}
}
return offset;
}
function findDecimalNumberEnd(source, offset) {
for (; offset < source.length; offset++) {
if (!charCodeDefinitions$b.isDigit(source.charCodeAt(offset))) {
break;
}
}
return offset;
}
// § 4.3.7. Consume an escaped code point
function consumeEscaped(source, offset) {
// It assumes that the U+005C REVERSE SOLIDUS (\) has already been consumed and
// that the next input code point has already been verified to be part of a valid escape.
offset += 2;
// hex digit
if (charCodeDefinitions$b.isHexDigit(getCharCode(source, offset - 1))) {
// Consume as many hex digits as possible, but no more than 5.
// Note that this means 1-6 hex digits have been consumed in total.
for (const maxOffset = Math.min(source.length, offset + 5); offset < maxOffset; offset++) {
if (!charCodeDefinitions$b.isHexDigit(getCharCode(source, offset))) {
break;
}
}
// If the next input code point is whitespace, consume it as well.
const code = getCharCode(source, offset);
if (charCodeDefinitions$b.isWhiteSpace(code)) {
offset += getNewlineLength(source, offset, code);
}
}
return offset;
}
// §4.3.11. Consume a name
// Note: This algorithm does not do the verification of the first few code points that are necessary
// to ensure the returned code points would constitute an <ident-token>. If that is the intended use,
// ensure that the stream starts with an identifier before calling this algorithm.
function consumeName(source, offset) {
// Let result initially be an empty string.
// Repeatedly consume the next input code point from the stream:
for (; offset < source.length; offset++) {
const code = source.charCodeAt(offset);
// name code point
if (charCodeDefinitions$b.isName(code)) {
// Append the code point to result.
continue;
}
// the stream starts with a valid escape
if (charCodeDefinitions$b.isValidEscape(code, getCharCode(source, offset + 1))) {
// Consume an escaped code point. Append the returned code point to result.
offset = consumeEscaped(source, offset) - 1;
continue;
}
// anything else
// Reconsume the current input code point. Return result.
break;
}
return offset;
}
// §4.3.12. Consume a number
function consumeNumber$1(source, offset) {
let code = source.charCodeAt(offset);
// 2. If the next input code point is U+002B PLUS SIGN (+) or U+002D HYPHEN-MINUS (-),
// consume it and append it to repr.
if (code === 0x002B || code === 0x002D) {
code = source.charCodeAt(offset += 1);
}
// 3. While the next input code point is a digit, consume it and append it to repr.
if (charCodeDefinitions$b.isDigit(code)) {
offset = findDecimalNumberEnd(source, offset + 1);
code = source.charCodeAt(offset);
}
// 4. If the next 2 input code points are U+002E FULL STOP (.) followed by a digit, then:
if (code === 0x002E && charCodeDefinitions$b.isDigit(source.charCodeAt(offset + 1))) {
// 4.1 Consume them.
// 4.2 Append them to repr.
offset += 2;
// 4.3 Set type to "number".
// TODO
// 4.4 While the next input code point is a digit, consume it and append it to repr.
offset = findDecimalNumberEnd(source, offset);
}
// 5. If the next 2 or 3 input code points are U+0045 LATIN CAPITAL LETTER E (E)
// or U+0065 LATIN SMALL LETTER E (e), ... , followed by a digit, then:
if (cmpChar(source, offset, 101 /* e */)) {
let sign = 0;
code = source.charCodeAt(offset + 1);
// ... optionally followed by U+002D HYPHEN-MINUS (-) or U+002B PLUS SIGN (+) ...
if (code === 0x002D || code === 0x002B) {
sign = 1;
code = source.charCodeAt(offset + 2);
}
// ... followed by a digit
if (charCodeDefinitions$b.isDigit(code)) {
// 5.1 Consume them.
// 5.2 Append them to repr.
// 5.3 Set type to "number".
// TODO
// 5.4 While the next input code point is a digit, consume it and append it to repr.
offset = findDecimalNumberEnd(source, offset + 1 + sign + 1);
}
}
return offset;
}
// § 4.3.14. Consume the remnants of a bad url
// ... its sole use is to consume enough of the input stream to reach a recovery point
// where normal tokenizing can resume.
function consumeBadUrlRemnants(source, offset) {
// Repeatedly consume the next input code point from the stream:
for (; offset < source.length; offset++) {
const code = source.charCodeAt(offset);
// U+0029 RIGHT PARENTHESIS ())
// EOF
if (code === 0x0029) {
// Return.
offset++;
break;
}
if (charCodeDefinitions$b.isValidEscape(code, getCharCode(source, offset + 1))) {
// Consume an escaped code point.
// Note: This allows an escaped right parenthesis ("\)") to be encountered
// without ending the <bad-url-token>. This is otherwise identical to
// the "anything else" clause.
offset = consumeEscaped(source, offset);
}
}
return offset;
}
// § 4.3.7. Consume an escaped code point
// Note: This algorithm assumes that escaped is valid without leading U+005C REVERSE SOLIDUS (\)
function decodeEscaped(escaped) {
// Single char escaped that's not a hex digit
if (escaped.length === 1 && !charCodeDefinitions$b.isHexDigit(escaped.charCodeAt(0))) {
return escaped[0];
}
// Interpret the hex digits as a hexadecimal number.
let code = parseInt(escaped, 16);
if (
(code === 0) || // If this number is zero,
(code >= 0xD800 && code <= 0xDFFF) || // or is for a surrogate,
(code > 0x10FFFF) // or is greater than the maximum allowed code point
) {
// ... return U+FFFD REPLACEMENT CHARACTER
code = 0xFFFD;
}
// Otherwise, return the code point with that value.
return String.fromCodePoint(code);
}
utils$k.cmpChar = cmpChar;
utils$k.cmpStr = cmpStr;
utils$k.consumeBadUrlRemnants = consumeBadUrlRemnants;
utils$k.consumeEscaped = consumeEscaped;
utils$k.consumeName = consumeName;
utils$k.consumeNumber = consumeNumber$1;
utils$k.decodeEscaped = decodeEscaped;
utils$k.findDecimalNumberEnd = findDecimalNumberEnd;
utils$k.findWhiteSpaceEnd = findWhiteSpaceEnd;
utils$k.findWhiteSpaceStart = findWhiteSpaceStart;
utils$k.getNewlineLength = getNewlineLength;
const tokenNames = [
'EOF-token',
'ident-token',
'function-token',
'at-keyword-token',
'hash-token',
'string-token',
'bad-string-token',
'url-token',
'bad-url-token',
'delim-token',
'number-token',
'percentage-token',
'dimension-token',
'whitespace-token',
'CDO-token',
'CDC-token',
'colon-token',
'semicolon-token',
'comma-token',
'[-token',
']-token',
'(-token',
')-token',
'{-token',
'}-token'
];
var names$8 = tokenNames;
var OffsetToLocation$3 = {};
var adoptBuffer$3 = {};
const MIN_SIZE = 16 * 1024;
function adoptBuffer$2(buffer = null, size) {
if (buffer === null || buffer.length < size) {
return new Uint32Array(Math.max(size + 1024, MIN_SIZE));
}
return buffer;
}
adoptBuffer$3.adoptBuffer = adoptBuffer$2;
const adoptBuffer$1 = adoptBuffer$3;
const charCodeDefinitions$a = charCodeDefinitions$c;
const N$4 = 10;
const F$2 = 12;
const R$2 = 13;
function computeLinesAndColumns(host) {
const source = host.source;
const sourceLength = source.length;
const startOffset = source.length > 0 ? charCodeDefinitions$a.isBOM(source.charCodeAt(0)) : 0;
const lines = adoptBuffer$1.adoptBuffer(host.lines, sourceLength);
const columns = adoptBuffer$1.adoptBuffer(host.columns, sourceLength);
let line = host.startLine;
let column = host.startColumn;
for (let i = startOffset; i < sourceLength; i++) {
const code = source.charCodeAt(i);
lines[i] = line;
columns[i] = column++;
if (code === N$4 || code === R$2 || code === F$2) {
if (code === R$2 && i + 1 < sourceLength && source.charCodeAt(i + 1) === N$4) {
i++;
lines[i] = line;
columns[i] = column;
}
line++;
column = 1;
}
}
lines[sourceLength] = line;
columns[sourceLength] = column;
host.lines = lines;
host.columns = columns;
host.computed = true;
}
let OffsetToLocation$2 = class OffsetToLocation {
constructor() {
this.lines = null;
this.columns = null;
this.computed = false;
}
setSource(source, startOffset = 0, startLine = 1, startColumn = 1) {
this.source = source;
this.startOffset = startOffset;
this.startLine = startLine;
this.startColumn = startColumn;
this.computed = false;
}
getLocation(offset, filename) {
if (!this.computed) {
computeLinesAndColumns(this);
}
return {
source: filename,
offset: this.startOffset + offset,
line: this.lines[offset],
column: this.columns[offset]
};
}
getLocationRange(start, end, filename) {
if (!this.computed) {
computeLinesAndColumns(this);
}
return {
source: filename,
start: {
offset: this.startOffset + start,
line: this.lines[start],
column: this.columns[start]
},
end: {
offset: this.startOffset + end,
line: this.lines[end],
column: this.columns[end]
}
};
}
};
OffsetToLocation$3.OffsetToLocation = OffsetToLocation$2;
var TokenStream$4 = {};
const adoptBuffer = adoptBuffer$3;
const utils$j = utils$k;
const names$7 = names$8;
const types$R = types$S;
const OFFSET_MASK = 0x00FFFFFF;
const TYPE_SHIFT = 24;
const balancePair$1 = new Map([
[types$R.Function, types$R.RightParenthesis],
[types$R.LeftParenthesis, types$R.RightParenthesis],
[types$R.LeftSquareBracket, types$R.RightSquareBracket],
[types$R.LeftCurlyBracket, types$R.RightCurlyBracket]
]);
let TokenStream$3 = class TokenStream {
constructor(source, tokenize) {
this.setSource(source, tokenize);
}
reset() {
this.eof = false;
this.tokenIndex = -1;
this.tokenType = 0;
this.tokenStart = this.firstCharOffset;
this.tokenEnd = this.firstCharOffset;
}
setSource(source = '', tokenize = () => {}) {
source = String(source || '');
const sourceLength = source.length;
const offsetAndType = adoptBuffer.adoptBuffer(this.offsetAndType, source.length + 1); // +1 because of eof-token
const balance = adoptBuffer.adoptBuffer(this.balance, source.length + 1);
let tokenCount = 0;
let balanceCloseType = 0;
let balanceStart = 0;
let firstCharOffset = -1;
// capture buffers
this.offsetAndType = null;
this.balance = null;
tokenize(source, (type, start, end) => {
switch (type) {
default:
balance[tokenCount] = sourceLength;
break;
case balanceCloseType: {
let balancePrev = balanceStart & OFFSET_MASK;
balanceStart = balance[balancePrev];
balanceCloseType = balanceStart >> TYPE_SHIFT;
balance[tokenCount] = balancePrev;
balance[balancePrev++] = tokenCount;
for (; balancePrev < tokenCount; balancePrev++) {
if (balance[balancePrev] === sourceLength) {
balance[balancePrev] = tokenCount;
}
}
break;
}
case types$R.LeftParenthesis:
case types$R.Function:
case types$R.LeftSquareBracket:
case types$R.LeftCurlyBracket:
balance[tokenCount] = balanceStart;
balanceCloseType = balancePair$1.get(type);
balanceStart = (balanceCloseType << TYPE_SHIFT) | tokenCount;
break;
}
offsetAndType[tokenCount++] = (type << TYPE_SHIFT) | end;
if (firstCharOffset === -1) {
firstCharOffset = start;
}
});
// finalize buffers
offsetAndType[tokenCount] = (types$R.EOF << TYPE_SHIFT) | sourceLength; // <EOF-token>
balance[tokenCount] = sourceLength;
balance[sourceLength] = sourceLength; // prevents false positive balance match with any token
while (balanceStart !== 0) {
const balancePrev = balanceStart & OFFSET_MASK;
balanceStart = balance[balancePrev];
balance[balancePrev] = sourceLength;
}
this.source = source;
this.firstCharOffset = firstCharOffset === -1 ? 0 : firstCharOffset;
this.tokenCount = tokenCount;
this.offsetAndType = offsetAndType;
this.balance = balance;
this.reset();
this.next();
}
lookupType(offset) {
offset += this.tokenIndex;
if (offset < this.tokenCount) {
return this.offsetAndType[offset] >> TYPE_SHIFT;
}
return types$R.EOF;
}
lookupOffset(offset) {
offset += this.tokenIndex;
if (offset < this.tokenCount) {
return this.offsetAndType[offset - 1] & OFFSET_MASK;
}
return this.source.length;
}
lookupValue(offset, referenceStr) {
offset += this.tokenIndex;
if (offset < this.tokenCount) {
return utils$j.cmpStr(
this.source,
this.offsetAndType[offset - 1] & OFFSET_MASK,
this.offsetAndType[offset] & OFFSET_MASK,
referenceStr
);
}
return false;
}
getTokenStart(tokenIndex) {
if (tokenIndex === this.tokenIndex) {
return this.tokenStart;
}
if (tokenIndex > 0) {
return tokenIndex < this.tokenCount
? this.offsetAndType[tokenIndex - 1] & OFFSET_MASK
: this.offsetAndType[this.tokenCount] & OFFSET_MASK;
}
return this.firstCharOffset;
}
substrToCursor(start) {
return this.source.substring(start, this.tokenStart);
}
isBalanceEdge(pos) {
return this.balance[this.tokenIndex] < pos;
}
isDelim(code, offset) {
if (offset) {
return (
this.lookupType(offset) === types$R.Delim &&
this.source.charCodeAt(this.lookupOffset(offset)) === code
);
}
return (
this.tokenType === types$R.Delim &&
this.source.charCodeAt(this.tokenStart) === code
);
}
skip(tokenCount) {
let next = this.tokenIndex + tokenCount;
if (next < this.tokenCount) {
this.tokenIndex = next;
this.tokenStart = this.offsetAndType[next - 1] & OFFSET_MASK;
next = this.offsetAndType[next];
this.tokenType = next >> TYPE_SHIFT;
this.tokenEnd = next & OFFSET_MASK;
} else {
this.tokenIndex = this.tokenCount;
this.next();
}
}
next() {
let next = this.tokenIndex + 1;
if (next < this.tokenCount) {
this.tokenIndex = next;
this.tokenStart = this.tokenEnd;
next = this.offsetAndType[next];
this.tokenType = next >> TYPE_SHIFT;
this.tokenEnd = next & OFFSET_MASK;
} else {
this.eof = true;
this.tokenIndex = this.tokenCount;
this.tokenType = types$R.EOF;
this.tokenStart = this.tokenEnd = this.source.length;
}
}
skipSC() {
while (this.tokenType === types$R.WhiteSpace || this.tokenType === types$R.Comment) {
this.next();
}
}
skipUntilBalanced(startToken, stopConsume) {
let cursor = startToken;
let balanceEnd;
let offset;
loop:
for (; cursor < this.tokenCount; cursor++) {
balanceEnd = this.balance[cursor];
// stop scanning on balance edge that points to offset before start token
if (balanceEnd < startToken) {
break loop;
}
offset = cursor > 0 ? this.offsetAndType[cursor - 1] & OFFSET_MASK : this.firstCharOffset;
// check stop condition
switch (stopConsume(this.source.charCodeAt(offset))) {
case 1: // just stop
break loop;
case 2: // stop & included
cursor++;
break loop;
default:
// fast forward to the end of balanced block
if (this.balance[balanceEnd] === cursor) {
cursor = balanceEnd;
}
}
}
this.skip(cursor - this.tokenIndex);
}
forEachToken(fn) {
for (let i = 0, offset = this.firstCharOffset; i < this.tokenCount; i++) {
const start = offset;
const item = this.offsetAndType[i];
const end = item & OFFSET_MASK;
const type = item >> TYPE_SHIFT;
offset = end;
fn(type, start, end, i);
}
}
dump() {
const tokens = new Array(this.tokenCount);
this.forEachToken((type, start, end, index) => {
tokens[index] = {
idx: index,
type: names$7[type],
chunk: this.source.substring(start, end),
balance: this.balance[index]
};
});
return tokens;
}
};
TokenStream$4.TokenStream = TokenStream$3;
const types$Q = types$S;
const charCodeDefinitions$9 = charCodeDefinitions$c;
const utils$i = utils$k;
const names$6 = names$8;
const OffsetToLocation$1 = OffsetToLocation$3;
const TokenStream$2 = TokenStream$4;
function tokenize$2(source, onToken) {
function getCharCode(offset) {
return offset < sourceLength ? source.charCodeAt(offset) : 0;
}
// § 4.3.3. Consume a numeric token
function consumeNumericToken() {
// Consume a number and let number be the result.
offset = utils$i.consumeNumber(source, offset);
// If the next 3 input code points would start an identifier, then:
if (charCodeDefinitions$9.isIdentifierStart(getCharCode(offset), getCharCode(offset + 1), getCharCode(offset + 2))) {
// Create a <dimension-token> with the same value and type flag as number, and a unit set initially to the empty string.
// Consume a name. Set the <dimension-token>s unit to the returned value.
// Return the <dimension-token>.
type = types$Q.Dimension;
offset = utils$i.consumeName(source, offset);
return;
}
// Otherwise, if the next input code point is U+0025 PERCENTAGE SIGN (%), consume it.
if (getCharCode(offset) === 0x0025) {
// Create a <percentage-token> with the same value as number, and return it.
type = types$Q.Percentage;
offset++;
return;
}
// Otherwise, create a <number-token> with the same value and type flag as number, and return it.
type = types$Q.Number;
}
// § 4.3.4. Consume an ident-like token
function consumeIdentLikeToken() {
const nameStartOffset = offset;
// Consume a name, and let string be the result.
offset = utils$i.consumeName(source, offset);
// If strings value is an ASCII case-insensitive match for "url",
// and the next input code point is U+0028 LEFT PARENTHESIS ((), consume it.
if (utils$i.cmpStr(source, nameStartOffset, offset, 'url') && getCharCode(offset) === 0x0028) {
// While the next two input code points are whitespace, consume the next input code point.
offset = utils$i.findWhiteSpaceEnd(source, offset + 1);
// If the next one or two input code points are U+0022 QUOTATION MARK ("), U+0027 APOSTROPHE ('),
// or whitespace followed by U+0022 QUOTATION MARK (") or U+0027 APOSTROPHE ('),
// then create a <function-token> with its value set to string and return it.
if (getCharCode(offset) === 0x0022 ||
getCharCode(offset) === 0x0027) {
type = types$Q.Function;
offset = nameStartOffset + 4;
return;
}
// Otherwise, consume a url token, and return it.
consumeUrlToken();
return;
}
// Otherwise, if the next input code point is U+0028 LEFT PARENTHESIS ((), consume it.
// Create a <function-token> with its value set to string and return it.
if (getCharCode(offset) === 0x0028) {
type = types$Q.Function;
offset++;
return;
}
// Otherwise, create an <ident-token> with its value set to string and return it.
type = types$Q.Ident;
}
// § 4.3.5. Consume a string token
function consumeStringToken(endingCodePoint) {
// This algorithm may be called with an ending code point, which denotes the code point
// that ends the string. If an ending code point is not specified,
// the current input code point is used.
if (!endingCodePoint) {
endingCodePoint = getCharCode(offset++);
}
// Initially create a <string-token> with its value set to the empty string.
type = types$Q.String;
// Repeatedly consume the next input code point from the stream:
for (; offset < source.length; offset++) {
const code = source.charCodeAt(offset);
switch (charCodeDefinitions$9.charCodeCategory(code)) {
// ending code point
case endingCodePoint:
// Return the <string-token>.
offset++;
return;
// EOF
// case EofCategory:
// This is a parse error. Return the <string-token>.
// return;
// newline
case charCodeDefinitions$9.WhiteSpaceCategory:
if (charCodeDefinitions$9.isNewline(code)) {
// This is a parse error. Reconsume the current input code point,
// create a <bad-string-token>, and return it.
offset += utils$i.getNewlineLength(source, offset, code);
type = types$Q.BadString;
return;
}
break;
// U+005C REVERSE SOLIDUS (\)
case 0x005C:
// If the next input code point is EOF, do nothing.
if (offset === source.length - 1) {
break;
}
const nextCode = getCharCode(offset + 1);
// Otherwise, if the next input code point is a newline, consume it.
if (charCodeDefinitions$9.isNewline(nextCode)) {
offset += utils$i.getNewlineLength(source, offset + 1, nextCode);
} else if (charCodeDefinitions$9.isValidEscape(code, nextCode)) {
// Otherwise, (the stream starts with a valid escape) consume
// an escaped code point and append the returned code point to
// the <string-token>s value.
offset = utils$i.consumeEscaped(source, offset) - 1;
}
break;
// anything else
// Append the current input code point to the <string-token>s value.
}
}
}
// § 4.3.6. Consume a url token
// Note: This algorithm assumes that the initial "url(" has already been consumed.
// This algorithm also assumes that its being called to consume an "unquoted" value, like url(foo).
// A quoted value, like url("foo"), is parsed as a <function-token>. Consume an ident-like token
// automatically handles this distinction; this algorithm shouldnt be called directly otherwise.
function consumeUrlToken() {
// Initially create a <url-token> with its value set to the empty string.
type = types$Q.Url;
// Consume as much whitespace as possible.
offset = utils$i.findWhiteSpaceEnd(source, offset);
// Repeatedly consume the next input code point from the stream:
for (; offset < source.length; offset++) {
const code = source.charCodeAt(offset);
switch (charCodeDefinitions$9.charCodeCategory(code)) {
// U+0029 RIGHT PARENTHESIS ())
case 0x0029:
// Return the <url-token>.
offset++;
return;
// EOF
// case EofCategory:
// This is a parse error. Return the <url-token>.
// return;
// whitespace
case charCodeDefinitions$9.WhiteSpaceCategory:
// Consume as much whitespace as possible.
offset = utils$i.findWhiteSpaceEnd(source, offset);
// If the next input code point is U+0029 RIGHT PARENTHESIS ()) or EOF,
// consume it and return the <url-token>
// (if EOF was encountered, this is a parse error);
if (getCharCode(offset) === 0x0029 || offset >= source.length) {
if (offset < source.length) {
offset++;
}
return;
}
// otherwise, consume the remnants of a bad url, create a <bad-url-token>,
// and return it.
offset = utils$i.consumeBadUrlRemnants(source, offset);
type = types$Q.BadUrl;
return;
// U+0022 QUOTATION MARK (")
// U+0027 APOSTROPHE (')
// U+0028 LEFT PARENTHESIS (()
// non-printable code point
case 0x0022:
case 0x0027:
case 0x0028:
case charCodeDefinitions$9.NonPrintableCategory:
// This is a parse error. Consume the remnants of a bad url,
// create a <bad-url-token>, and return it.
offset = utils$i.consumeBadUrlRemnants(source, offset);
type = types$Q.BadUrl;
return;
// U+005C REVERSE SOLIDUS (\)
case 0x005C:
// If the stream starts with a valid escape, consume an escaped code point and
// append the returned code point to the <url-token>s value.
if (charCodeDefinitions$9.isValidEscape(code, getCharCode(offset + 1))) {
offset = utils$i.consumeEscaped(source, offset) - 1;
break;
}
// Otherwise, this is a parse error. Consume the remnants of a bad url,
// create a <bad-url-token>, and return it.
offset = utils$i.consumeBadUrlRemnants(source, offset);
type = types$Q.BadUrl;
return;
// anything else
// Append the current input code point to the <url-token>s value.
}
}
}
// ensure source is a string
source = String(source || '');
const sourceLength = source.length;
let start = charCodeDefinitions$9.isBOM(getCharCode(0));
let offset = start;
let type;
// https://drafts.csswg.org/css-syntax-3/#consume-token
// § 4.3.1. Consume a token
while (offset < sourceLength) {
const code = source.charCodeAt(offset);
switch (charCodeDefinitions$9.charCodeCategory(code)) {
// whitespace
case charCodeDefinitions$9.WhiteSpaceCategory:
// Consume as much whitespace as possible. Return a <whitespace-token>.
type = types$Q.WhiteSpace;
offset = utils$i.findWhiteSpaceEnd(source, offset + 1);
break;
// U+0022 QUOTATION MARK (")
case 0x0022:
// Consume a string token and return it.
consumeStringToken();
break;
// U+0023 NUMBER SIGN (#)
case 0x0023:
// If the next input code point is a name code point or the next two input code points are a valid escape, then:
if (charCodeDefinitions$9.isName(getCharCode(offset + 1)) || charCodeDefinitions$9.isValidEscape(getCharCode(offset + 1), getCharCode(offset + 2))) {
// Create a <hash-token>.
type = types$Q.Hash;
// If the next 3 input code points would start an identifier, set the <hash-token>s type flag to "id".
// if (isIdentifierStart(getCharCode(offset + 1), getCharCode(offset + 2), getCharCode(offset + 3))) {
// // TODO: set id flag
// }
// Consume a name, and set the <hash-token>s value to the returned string.
offset = utils$i.consumeName(source, offset + 1);
// Return the <hash-token>.
} else {
// Otherwise, return a <delim-token> with its value set to the current input code point.
type = types$Q.Delim;
offset++;
}
break;
// U+0027 APOSTROPHE (')
case 0x0027:
// Consume a string token and return it.
consumeStringToken();
break;
// U+0028 LEFT PARENTHESIS (()
case 0x0028:
// Return a <(-token>.
type = types$Q.LeftParenthesis;
offset++;
break;
// U+0029 RIGHT PARENTHESIS ())
case 0x0029:
// Return a <)-token>.
type = types$Q.RightParenthesis;
offset++;
break;
// U+002B PLUS SIGN (+)
case 0x002B:
// If the input stream starts with a number, ...
if (charCodeDefinitions$9.isNumberStart(code, getCharCode(offset + 1), getCharCode(offset + 2))) {
// ... reconsume the current input code point, consume a numeric token, and return it.
consumeNumericToken();
} else {
// Otherwise, return a <delim-token> with its value set to the current input code point.
type = types$Q.Delim;
offset++;
}
break;
// U+002C COMMA (,)
case 0x002C:
// Return a <comma-token>.
type = types$Q.Comma;
offset++;
break;
// U+002D HYPHEN-MINUS (-)
case 0x002D:
// If the input stream starts with a number, reconsume the current input code point, consume a numeric token, and return it.
if (charCodeDefinitions$9.isNumberStart(code, getCharCode(offset + 1), getCharCode(offset + 2))) {
consumeNumericToken();
} else {
// Otherwise, if the next 2 input code points are U+002D HYPHEN-MINUS U+003E GREATER-THAN SIGN (->), consume them and return a <CDC-token>.
if (getCharCode(offset + 1) === 0x002D &&
getCharCode(offset + 2) === 0x003E) {
type = types$Q.CDC;
offset = offset + 3;
} else {
// Otherwise, if the input stream starts with an identifier, ...
if (charCodeDefinitions$9.isIdentifierStart(code, getCharCode(offset + 1), getCharCode(offset + 2))) {
// ... reconsume the current input code point, consume an ident-like token, and return it.
consumeIdentLikeToken();
} else {
// Otherwise, return a <delim-token> with its value set to the current input code point.
type = types$Q.Delim;
offset++;
}
}
}
break;
// U+002E FULL STOP (.)
case 0x002E:
// If the input stream starts with a number, ...
if (charCodeDefinitions$9.isNumberStart(code, getCharCode(offset + 1), getCharCode(offset + 2))) {
// ... reconsume the current input code point, consume a numeric token, and return it.
consumeNumericToken();
} else {
// Otherwise, return a <delim-token> with its value set to the current input code point.
type = types$Q.Delim;
offset++;
}
break;
// U+002F SOLIDUS (/)
case 0x002F:
// If the next two input code point are U+002F SOLIDUS (/) followed by a U+002A ASTERISK (*),
if (getCharCode(offset + 1) === 0x002A) {
// ... consume them and all following code points up to and including the first U+002A ASTERISK (*)
// followed by a U+002F SOLIDUS (/), or up to an EOF code point.
type = types$Q.Comment;
offset = source.indexOf('*/', offset + 2);
offset = offset === -1 ? source.length : offset + 2;
} else {
type = types$Q.Delim;
offset++;
}
break;
// U+003A COLON (:)
case 0x003A:
// Return a <colon-token>.
type = types$Q.Colon;
offset++;
break;
// U+003B SEMICOLON (;)
case 0x003B:
// Return a <semicolon-token>.
type = types$Q.Semicolon;
offset++;
break;
// U+003C LESS-THAN SIGN (<)
case 0x003C:
// If the next 3 input code points are U+0021 EXCLAMATION MARK U+002D HYPHEN-MINUS U+002D HYPHEN-MINUS (!--), ...
if (getCharCode(offset + 1) === 0x0021 &&
getCharCode(offset + 2) === 0x002D &&
getCharCode(offset + 3) === 0x002D) {
// ... consume them and return a <CDO-token>.
type = types$Q.CDO;
offset = offset + 4;
} else {
// Otherwise, return a <delim-token> with its value set to the current input code point.
type = types$Q.Delim;
offset++;
}
break;
// U+0040 COMMERCIAL AT (@)
case 0x0040:
// If the next 3 input code points would start an identifier, ...
if (charCodeDefinitions$9.isIdentifierStart(getCharCode(offset + 1), getCharCode(offset + 2), getCharCode(offset + 3))) {
// ... consume a name, create an <at-keyword-token> with its value set to the returned value, and return it.
type = types$Q.AtKeyword;
offset = utils$i.consumeName(source, offset + 1);
} else {
// Otherwise, return a <delim-token> with its value set to the current input code point.
type = types$Q.Delim;
offset++;
}
break;
// U+005B LEFT SQUARE BRACKET ([)
case 0x005B:
// Return a <[-token>.
type = types$Q.LeftSquareBracket;
offset++;
break;
// U+005C REVERSE SOLIDUS (\)
case 0x005C:
// If the input stream starts with a valid escape, ...
if (charCodeDefinitions$9.isValidEscape(code, getCharCode(offset + 1))) {
// ... reconsume the current input code point, consume an ident-like token, and return it.
consumeIdentLikeToken();
} else {
// Otherwise, this is a parse error. Return a <delim-token> with its value set to the current input code point.
type = types$Q.Delim;
offset++;
}
break;
// U+005D RIGHT SQUARE BRACKET (])
case 0x005D:
// Return a <]-token>.
type = types$Q.RightSquareBracket;
offset++;
break;
// U+007B LEFT CURLY BRACKET ({)
case 0x007B:
// Return a <{-token>.
type = types$Q.LeftCurlyBracket;
offset++;
break;
// U+007D RIGHT CURLY BRACKET (})
case 0x007D:
// Return a <}-token>.
type = types$Q.RightCurlyBracket;
offset++;
break;
// digit
case charCodeDefinitions$9.DigitCategory:
// Reconsume the current input code point, consume a numeric token, and return it.
consumeNumericToken();
break;
// name-start code point
case charCodeDefinitions$9.NameStartCategory:
// Reconsume the current input code point, consume an ident-like token, and return it.
consumeIdentLikeToken();
break;
// EOF
// case EofCategory:
// Return an <EOF-token>.
// break;
// anything else
default:
// Return a <delim-token> with its value set to the current input code point.
type = types$Q.Delim;
offset++;
}
// put token to stream
onToken(type, start, start = offset);
}
}
tokenizer$2.AtKeyword = types$Q.AtKeyword;
tokenizer$2.BadString = types$Q.BadString;
tokenizer$2.BadUrl = types$Q.BadUrl;
tokenizer$2.CDC = types$Q.CDC;
tokenizer$2.CDO = types$Q.CDO;
tokenizer$2.Colon = types$Q.Colon;
tokenizer$2.Comma = types$Q.Comma;
tokenizer$2.Comment = types$Q.Comment;
tokenizer$2.Delim = types$Q.Delim;
tokenizer$2.Dimension = types$Q.Dimension;
tokenizer$2.EOF = types$Q.EOF;
tokenizer$2.Function = types$Q.Function;
tokenizer$2.Hash = types$Q.Hash;
tokenizer$2.Ident = types$Q.Ident;
tokenizer$2.LeftCurlyBracket = types$Q.LeftCurlyBracket;
tokenizer$2.LeftParenthesis = types$Q.LeftParenthesis;
tokenizer$2.LeftSquareBracket = types$Q.LeftSquareBracket;
tokenizer$2.Number = types$Q.Number;
tokenizer$2.Percentage = types$Q.Percentage;
tokenizer$2.RightCurlyBracket = types$Q.RightCurlyBracket;
tokenizer$2.RightParenthesis = types$Q.RightParenthesis;
tokenizer$2.RightSquareBracket = types$Q.RightSquareBracket;
tokenizer$2.Semicolon = types$Q.Semicolon;
tokenizer$2.String = types$Q.String;
tokenizer$2.Url = types$Q.Url;
tokenizer$2.WhiteSpace = types$Q.WhiteSpace;
tokenizer$2.tokenTypes = types$Q;
tokenizer$2.DigitCategory = charCodeDefinitions$9.DigitCategory;
tokenizer$2.EofCategory = charCodeDefinitions$9.EofCategory;
tokenizer$2.NameStartCategory = charCodeDefinitions$9.NameStartCategory;
tokenizer$2.NonPrintableCategory = charCodeDefinitions$9.NonPrintableCategory;
tokenizer$2.WhiteSpaceCategory = charCodeDefinitions$9.WhiteSpaceCategory;
tokenizer$2.charCodeCategory = charCodeDefinitions$9.charCodeCategory;
tokenizer$2.isBOM = charCodeDefinitions$9.isBOM;
tokenizer$2.isDigit = charCodeDefinitions$9.isDigit;
tokenizer$2.isHexDigit = charCodeDefinitions$9.isHexDigit;
tokenizer$2.isIdentifierStart = charCodeDefinitions$9.isIdentifierStart;
tokenizer$2.isLetter = charCodeDefinitions$9.isLetter;
tokenizer$2.isLowercaseLetter = charCodeDefinitions$9.isLowercaseLetter;
tokenizer$2.isName = charCodeDefinitions$9.isName;
tokenizer$2.isNameStart = charCodeDefinitions$9.isNameStart;
tokenizer$2.isNewline = charCodeDefinitions$9.isNewline;
tokenizer$2.isNonAscii = charCodeDefinitions$9.isNonAscii;
tokenizer$2.isNonPrintable = charCodeDefinitions$9.isNonPrintable;
tokenizer$2.isNumberStart = charCodeDefinitions$9.isNumberStart;
tokenizer$2.isUppercaseLetter = charCodeDefinitions$9.isUppercaseLetter;
tokenizer$2.isValidEscape = charCodeDefinitions$9.isValidEscape;
tokenizer$2.isWhiteSpace = charCodeDefinitions$9.isWhiteSpace;
tokenizer$2.cmpChar = utils$i.cmpChar;
tokenizer$2.cmpStr = utils$i.cmpStr;
tokenizer$2.consumeBadUrlRemnants = utils$i.consumeBadUrlRemnants;
tokenizer$2.consumeEscaped = utils$i.consumeEscaped;
tokenizer$2.consumeName = utils$i.consumeName;
tokenizer$2.consumeNumber = utils$i.consumeNumber;
tokenizer$2.decodeEscaped = utils$i.decodeEscaped;
tokenizer$2.findDecimalNumberEnd = utils$i.findDecimalNumberEnd;
tokenizer$2.findWhiteSpaceEnd = utils$i.findWhiteSpaceEnd;
tokenizer$2.findWhiteSpaceStart = utils$i.findWhiteSpaceStart;
tokenizer$2.getNewlineLength = utils$i.getNewlineLength;
tokenizer$2.tokenNames = names$6;
tokenizer$2.OffsetToLocation = OffsetToLocation$1.OffsetToLocation;
tokenizer$2.TokenStream = TokenStream$2.TokenStream;
tokenizer$2.tokenize = tokenize$2;
var create$7 = {};
var List$7 = {};
//
// list
// ┌──────┐
// ┌──────────────┼─head │
// │ │ tail─┼──────────────┐
// │ └──────┘ │
// ▼ ▼
// item item item item
// ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
// null ◀──┼─prev │◀───┼─prev │◀───┼─prev │◀───┼─prev │
// │ next─┼───▶│ next─┼───▶│ next─┼───▶│ next─┼──▶ null
// ├──────┤ ├──────┤ ├──────┤ ├──────┤
// │ data │ │ data │ │ data │ │ data │
// └──────┘ └──────┘ └──────┘ └──────┘
//
let releasedCursors = null;
let List$6 = class List {
static createItem(data) {
return {
prev: null,
next: null,
data
};
}
constructor() {
this.head = null;
this.tail = null;
this.cursor = null;
}
createItem(data) {
return List.createItem(data);
}
// cursor helpers
allocateCursor(prev, next) {
let cursor;
if (releasedCursors !== null) {
cursor = releasedCursors;
releasedCursors = releasedCursors.cursor;
cursor.prev = prev;
cursor.next = next;
cursor.cursor = this.cursor;
} else {
cursor = {
prev,
next,
cursor: this.cursor
};
}
this.cursor = cursor;
return cursor;
}
releaseCursor() {
const { cursor } = this;
this.cursor = cursor.cursor;
cursor.prev = null;
cursor.next = null;
cursor.cursor = releasedCursors;
releasedCursors = cursor;
}
updateCursors(prevOld, prevNew, nextOld, nextNew) {
let { cursor } = this;
while (cursor !== null) {
if (cursor.prev === prevOld) {
cursor.prev = prevNew;
}
if (cursor.next === nextOld) {
cursor.next = nextNew;
}
cursor = cursor.cursor;
}
}
*[Symbol.iterator]() {
for (let cursor = this.head; cursor !== null; cursor = cursor.next) {
yield cursor.data;
}
}
// getters
get size() {
let size = 0;
for (let cursor = this.head; cursor !== null; cursor = cursor.next) {
size++;
}
return size;
}
get isEmpty() {
return this.head === null;
}
get first() {
return this.head && this.head.data;
}
get last() {
return this.tail && this.tail.data;
}
// convertors
fromArray(array) {
let cursor = null;
this.head = null;
for (let data of array) {
const item = List.createItem(data);
if (cursor !== null) {
cursor.next = item;
} else {
this.head = item;
}
item.prev = cursor;
cursor = item;
}
this.tail = cursor;
return this;
}
toArray() {
return [...this];
}
toJSON() {
return [...this];
}
// array-like methods
forEach(fn, thisArg = this) {
// push cursor
const cursor = this.allocateCursor(null, this.head);
while (cursor.next !== null) {
const item = cursor.next;
cursor.next = item.next;
fn.call(thisArg, item.data, item, this);
}
// pop cursor
this.releaseCursor();
}
forEachRight(fn, thisArg = this) {
// push cursor
const cursor = this.allocateCursor(this.tail, null);
while (cursor.prev !== null) {
const item = cursor.prev;
cursor.prev = item.prev;
fn.call(thisArg, item.data, item, this);
}
// pop cursor
this.releaseCursor();
}
reduce(fn, initialValue, thisArg = this) {
// push cursor
let cursor = this.allocateCursor(null, this.head);
let acc = initialValue;
let item;
while (cursor.next !== null) {
item = cursor.next;
cursor.next = item.next;
acc = fn.call(thisArg, acc, item.data, item, this);
}
// pop cursor
this.releaseCursor();
return acc;
}
reduceRight(fn, initialValue, thisArg = this) {
// push cursor
let cursor = this.allocateCursor(this.tail, null);
let acc = initialValue;
let item;
while (cursor.prev !== null) {
item = cursor.prev;
cursor.prev = item.prev;
acc = fn.call(thisArg, acc, item.data, item, this);
}
// pop cursor
this.releaseCursor();
return acc;
}
some(fn, thisArg = this) {
for (let cursor = this.head; cursor !== null; cursor = cursor.next) {
if (fn.call(thisArg, cursor.data, cursor, this)) {
return true;
}
}
return false;
}
map(fn, thisArg = this) {
const result = new List();
for (let cursor = this.head; cursor !== null; cursor = cursor.next) {
result.appendData(fn.call(thisArg, cursor.data, cursor, this));
}
return result;
}
filter(fn, thisArg = this) {
const result = new List();
for (let cursor = this.head; cursor !== null; cursor = cursor.next) {
if (fn.call(thisArg, cursor.data, cursor, this)) {
result.appendData(cursor.data);
}
}
return result;
}
nextUntil(start, fn, thisArg = this) {
if (start === null) {
return;
}
// push cursor
const cursor = this.allocateCursor(null, start);
while (cursor.next !== null) {
const item = cursor.next;
cursor.next = item.next;
if (fn.call(thisArg, item.data, item, this)) {
break;
}
}
// pop cursor
this.releaseCursor();
}
prevUntil(start, fn, thisArg = this) {
if (start === null) {
return;
}
// push cursor
const cursor = this.allocateCursor(start, null);
while (cursor.prev !== null) {
const item = cursor.prev;
cursor.prev = item.prev;
if (fn.call(thisArg, item.data, item, this)) {
break;
}
}
// pop cursor
this.releaseCursor();
}
// mutation
clear() {
this.head = null;
this.tail = null;
}
copy() {
const result = new List();
for (let data of this) {
result.appendData(data);
}
return result;
}
prepend(item) {
// head
// ^
// item
this.updateCursors(null, item, this.head, item);
// insert to the beginning of the list
if (this.head !== null) {
// new item <- first item
this.head.prev = item;
// new item -> first item
item.next = this.head;
} else {
// if list has no head, then it also has no tail
// in this case tail points to the new item
this.tail = item;
}
// head always points to new item
this.head = item;
return this;
}
prependData(data) {
return this.prepend(List.createItem(data));
}
append(item) {
return this.insert(item);
}
appendData(data) {
return this.insert(List.createItem(data));
}
insert(item, before = null) {
if (before !== null) {
// prev before
// ^
// item
this.updateCursors(before.prev, item, before, item);
if (before.prev === null) {
// insert to the beginning of list
if (this.head !== before) {
throw new Error('before doesn\'t belong to list');
}
// since head points to before therefore list doesn't empty
// no need to check tail
this.head = item;
before.prev = item;
item.next = before;
this.updateCursors(null, item);
} else {
// insert between two items
before.prev.next = item;
item.prev = before.prev;
before.prev = item;
item.next = before;
}
} else {
// tail
// ^
// item
this.updateCursors(this.tail, item, null, item);
// insert to the ending of the list
if (this.tail !== null) {
// last item -> new item
this.tail.next = item;
// last item <- new item
item.prev = this.tail;
} else {
// if list has no tail, then it also has no head
// in this case head points to new item
this.head = item;
}
// tail always points to new item
this.tail = item;
}
return this;
}
insertData(data, before) {
return this.insert(List.createItem(data), before);
}
remove(item) {
// item
// ^
// prev next
this.updateCursors(item, item.prev, item, item.next);
if (item.prev !== null) {
item.prev.next = item.next;
} else {
if (this.head !== item) {
throw new Error('item doesn\'t belong to list');
}
this.head = item.next;
}
if (item.next !== null) {
item.next.prev = item.prev;
} else {
if (this.tail !== item) {
throw new Error('item doesn\'t belong to list');
}
this.tail = item.prev;
}
item.prev = null;
item.next = null;
return item;
}
push(data) {
this.insert(List.createItem(data));
}
pop() {
return this.tail !== null ? this.remove(this.tail) : null;
}
unshift(data) {
this.prepend(List.createItem(data));
}
shift() {
return this.head !== null ? this.remove(this.head) : null;
}
prependList(list) {
return this.insertList(list, this.head);
}
appendList(list) {
return this.insertList(list);
}
insertList(list, before) {
// ignore empty lists
if (list.head === null) {
return this;
}
if (before !== undefined && before !== null) {
this.updateCursors(before.prev, list.tail, before, list.head);
// insert in the middle of dist list
if (before.prev !== null) {
// before.prev <-> list.head
before.prev.next = list.head;
list.head.prev = before.prev;
} else {
this.head = list.head;
}
before.prev = list.tail;
list.tail.next = before;
} else {
this.updateCursors(this.tail, list.tail, null, list.head);
// insert to end of the list
if (this.tail !== null) {
// if destination list has a tail, then it also has a head,
// but head doesn't change
// dest tail -> source head
this.tail.next = list.head;
// dest tail <- source head
list.head.prev = this.tail;
} else {
// if list has no a tail, then it also has no a head
// in this case points head to new item
this.head = list.head;
}
// tail always start point to new item
this.tail = list.tail;
}
list.head = null;
list.tail = null;
return this;
}
replace(oldItem, newItemOrList) {
if ('head' in newItemOrList) {
this.insertList(newItemOrList, oldItem);
} else {
this.insert(newItemOrList, oldItem);
}
this.remove(oldItem);
}
};
List$7.List = List$6;
var _SyntaxError$1 = {};
var createCustomError$4 = {};
function createCustomError$3(name, message) {
// use Object.create(), because some VMs prevent setting line/column otherwise
// (iOS Safari 10 even throws an exception)
const error = Object.create(SyntaxError.prototype);
const errorStack = new Error();
return Object.assign(error, {
name,
message,
get stack() {
return (errorStack.stack || '').replace(/^(.+\n){1,3}/, `${name}: ${message}\n`);
}
});
}
createCustomError$4.createCustomError = createCustomError$3;
const createCustomError$2 = createCustomError$4;
const MAX_LINE_LENGTH = 100;
const OFFSET_CORRECTION = 60;
const TAB_REPLACEMENT = ' ';
function sourceFragment({ source, line, column }, extraLines) {
function processLines(start, end) {
return lines
.slice(start, end)
.map((line, idx) =>
String(start + idx + 1).padStart(maxNumLength) + ' |' + line
).join('\n');
}
const lines = source.split(/\r\n?|\n|\f/);
const startLine = Math.max(1, line - extraLines) - 1;
const endLine = Math.min(line + extraLines, lines.length + 1);
const maxNumLength = Math.max(4, String(endLine).length) + 1;
let cutLeft = 0;
// column correction according to replaced tab before column
column += (TAB_REPLACEMENT.length - 1) * (lines[line - 1].substr(0, column - 1).match(/\t/g) || []).length;
if (column > MAX_LINE_LENGTH) {
cutLeft = column - OFFSET_CORRECTION + 3;
column = OFFSET_CORRECTION - 2;
}
for (let i = startLine; i <= endLine; i++) {
if (i >= 0 && i < lines.length) {
lines[i] = lines[i].replace(/\t/g, TAB_REPLACEMENT);
lines[i] =
(cutLeft > 0 && lines[i].length > cutLeft ? '\u2026' : '') +
lines[i].substr(cutLeft, MAX_LINE_LENGTH - 2) +
(lines[i].length > cutLeft + MAX_LINE_LENGTH - 1 ? '\u2026' : '');
}
}
return [
processLines(startLine, line),
new Array(column + maxNumLength + 2).join('-') + '^',
processLines(line, endLine)
].filter(Boolean).join('\n');
}
function SyntaxError$5(message, source, offset, line, column) {
const error = Object.assign(createCustomError$2.createCustomError('SyntaxError', message), {
source,
offset,
line,
column,
sourceFragment(extraLines) {
return sourceFragment({ source, line, column }, isNaN(extraLines) ? 0 : extraLines);
},
get formattedMessage() {
return (
`Parse error: ${message}\n` +
sourceFragment({ source, line, column }, 2)
);
}
});
return error;
}
_SyntaxError$1.SyntaxError = SyntaxError$5;
var sequence$1 = {};
const types$P = types$S;
function readSequence$1(recognizer) {
const children = this.createList();
let space = false;
const context = {
recognizer
};
while (!this.eof) {
switch (this.tokenType) {
case types$P.Comment:
this.next();
continue;
case types$P.WhiteSpace:
space = true;
this.next();
continue;
}
let child = recognizer.getNode.call(this, context);
if (child === undefined) {
break;
}
if (space) {
if (recognizer.onWhiteSpace) {
recognizer.onWhiteSpace.call(this, child, children, context);
}
space = false;
}
children.push(child);
}
if (space && recognizer.onWhiteSpace) {
recognizer.onWhiteSpace.call(this, null, children, context);
}
return children;
}
sequence$1.readSequence = readSequence$1;
const List$5 = List$7;
const SyntaxError$4 = _SyntaxError$1;
const index$b = tokenizer$2;
const sequence = sequence$1;
const OffsetToLocation = OffsetToLocation$3;
const TokenStream$1 = TokenStream$4;
const utils$h = utils$k;
const types$O = types$S;
const names$5 = names$8;
const NOOP = () => {};
const EXCLAMATIONMARK$3 = 0x0021; // U+0021 EXCLAMATION MARK (!)
const NUMBERSIGN$4 = 0x0023; // U+0023 NUMBER SIGN (#)
const SEMICOLON = 0x003B; // U+003B SEMICOLON (;)
const LEFTCURLYBRACKET$1 = 0x007B; // U+007B LEFT CURLY BRACKET ({)
const NULL = 0;
function createParseContext(name) {
return function() {
return this[name]();
};
}
function fetchParseValues(dict) {
const result = Object.create(null);
for (const name in dict) {
const item = dict[name];
const fn = item.parse || item;
if (fn) {
result[name] = fn;
}
}
return result;
}
function processConfig(config) {
const parseConfig = {
context: Object.create(null),
scope: Object.assign(Object.create(null), config.scope),
atrule: fetchParseValues(config.atrule),
pseudo: fetchParseValues(config.pseudo),
node: fetchParseValues(config.node)
};
for (const name in config.parseContext) {
switch (typeof config.parseContext[name]) {
case 'function':
parseConfig.context[name] = config.parseContext[name];
break;
case 'string':
parseConfig.context[name] = createParseContext(config.parseContext[name]);
break;
}
}
return {
config: parseConfig,
...parseConfig,
...parseConfig.node
};
}
function createParser(config) {
let source = '';
let filename = '<unknown>';
let needPositions = false;
let onParseError = NOOP;
let onParseErrorThrow = false;
const locationMap = new OffsetToLocation.OffsetToLocation();
const parser = Object.assign(new TokenStream$1.TokenStream(), processConfig(config || {}), {
parseAtrulePrelude: true,
parseRulePrelude: true,
parseValue: true,
parseCustomProperty: false,
readSequence: sequence.readSequence,
consumeUntilBalanceEnd: () => 0,
consumeUntilLeftCurlyBracket(code) {
return code === LEFTCURLYBRACKET$1 ? 1 : 0;
},
consumeUntilLeftCurlyBracketOrSemicolon(code) {
return code === LEFTCURLYBRACKET$1 || code === SEMICOLON ? 1 : 0;
},
consumeUntilExclamationMarkOrSemicolon(code) {
return code === EXCLAMATIONMARK$3 || code === SEMICOLON ? 1 : 0;
},
consumeUntilSemicolonIncluded(code) {
return code === SEMICOLON ? 2 : 0;
},
createList() {
return new List$5.List();
},
createSingleNodeList(node) {
return new List$5.List().appendData(node);
},
getFirstListNode(list) {
return list && list.first;
},
getLastListNode(list) {
return list && list.last;
},
parseWithFallback(consumer, fallback) {
const startToken = this.tokenIndex;
try {
return consumer.call(this);
} catch (e) {
if (onParseErrorThrow) {
throw e;
}
const fallbackNode = fallback.call(this, startToken);
onParseErrorThrow = true;
onParseError(e, fallbackNode);
onParseErrorThrow = false;
return fallbackNode;
}
},
lookupNonWSType(offset) {
let type;
do {
type = this.lookupType(offset++);
if (type !== types$O.WhiteSpace) {
return type;
}
} while (type !== NULL);
return NULL;
},
charCodeAt(offset) {
return offset >= 0 && offset < source.length ? source.charCodeAt(offset) : 0;
},
substring(offsetStart, offsetEnd) {
return source.substring(offsetStart, offsetEnd);
},
substrToCursor(start) {
return this.source.substring(start, this.tokenStart);
},
cmpChar(offset, charCode) {
return utils$h.cmpChar(source, offset, charCode);
},
cmpStr(offsetStart, offsetEnd, str) {
return utils$h.cmpStr(source, offsetStart, offsetEnd, str);
},
consume(tokenType) {
const start = this.tokenStart;
this.eat(tokenType);
return this.substrToCursor(start);
},
consumeFunctionName() {
const name = source.substring(this.tokenStart, this.tokenEnd - 1);
this.eat(types$O.Function);
return name;
},
consumeNumber(type) {
const number = source.substring(this.tokenStart, utils$h.consumeNumber(source, this.tokenStart));
this.eat(type);
return number;
},
eat(tokenType) {
if (this.tokenType !== tokenType) {
const tokenName = names$5[tokenType].slice(0, -6).replace(/-/g, ' ').replace(/^./, m => m.toUpperCase());
let message = `${/[[\](){}]/.test(tokenName) ? `"${tokenName}"` : tokenName} is expected`;
let offset = this.tokenStart;
// tweak message and offset
switch (tokenType) {
case types$O.Ident:
// when identifier is expected but there is a function or url
if (this.tokenType === types$O.Function || this.tokenType === types$O.Url) {
offset = this.tokenEnd - 1;
message = 'Identifier is expected but function found';
} else {
message = 'Identifier is expected';
}
break;
case types$O.Hash:
if (this.isDelim(NUMBERSIGN$4)) {
this.next();
offset++;
message = 'Name is expected';
}
break;
case types$O.Percentage:
if (this.tokenType === types$O.Number) {
offset = this.tokenEnd;
message = 'Percent sign is expected';
}
break;
}
this.error(message, offset);
}
this.next();
},
eatIdent(name) {
if (this.tokenType !== types$O.Ident || this.lookupValue(0, name) === false) {
this.error(`Identifier "${name}" is expected`);
}
this.next();
},
eatDelim(code) {
if (!this.isDelim(code)) {
this.error(`Delim "${String.fromCharCode(code)}" is expected`);
}
this.next();
},
getLocation(start, end) {
if (needPositions) {
return locationMap.getLocationRange(
start,
end,
filename
);
}
return null;
},
getLocationFromList(list) {
if (needPositions) {
const head = this.getFirstListNode(list);
const tail = this.getLastListNode(list);
return locationMap.getLocationRange(
head !== null ? head.loc.start.offset - locationMap.startOffset : this.tokenStart,
tail !== null ? tail.loc.end.offset - locationMap.startOffset : this.tokenStart,
filename
);
}
return null;
},
error(message, offset) {
const location = typeof offset !== 'undefined' && offset < source.length
? locationMap.getLocation(offset)
: this.eof
? locationMap.getLocation(utils$h.findWhiteSpaceStart(source, source.length - 1))
: locationMap.getLocation(this.tokenStart);
throw new SyntaxError$4.SyntaxError(
message || 'Unexpected input',
source,
location.offset,
location.line,
location.column
);
}
});
const parse = function(source_, options) {
source = source_;
options = options || {};
parser.setSource(source, index$b.tokenize);
locationMap.setSource(
source,
options.offset,
options.line,
options.column
);
filename = options.filename || '<unknown>';
needPositions = Boolean(options.positions);
onParseError = typeof options.onParseError === 'function' ? options.onParseError : NOOP;
onParseErrorThrow = false;
parser.parseAtrulePrelude = 'parseAtrulePrelude' in options ? Boolean(options.parseAtrulePrelude) : true;
parser.parseRulePrelude = 'parseRulePrelude' in options ? Boolean(options.parseRulePrelude) : true;
parser.parseValue = 'parseValue' in options ? Boolean(options.parseValue) : true;
parser.parseCustomProperty = 'parseCustomProperty' in options ? Boolean(options.parseCustomProperty) : false;
const { context = 'default', onComment } = options;
if (context in parser.context === false) {
throw new Error('Unknown context `' + context + '`');
}
if (typeof onComment === 'function') {
parser.forEachToken((type, start, end) => {
if (type === types$O.Comment) {
const loc = parser.getLocation(start, end);
const value = utils$h.cmpStr(source, end - 2, end, '*/')
? source.slice(start + 2, end - 2)
: source.slice(start + 2, end);
onComment(value, loc);
}
});
}
const ast = parser.context[context].call(parser, options);
if (!parser.eof) {
parser.error();
}
return ast;
};
return Object.assign(parse, {
SyntaxError: SyntaxError$4.SyntaxError,
config: parser.config
});
}
create$7.createParser = createParser;
var create$6 = {};
var sourceMap$1 = {};
const sourceMapGenerator_js = require$$0$9;
const trackNodes = new Set(['Atrule', 'Selector', 'Declaration']);
function generateSourceMap(handlers) {
const map = new sourceMapGenerator_js.SourceMapGenerator();
const generated = {
line: 1,
column: 0
};
const original = {
line: 0, // should be zero to add first mapping
column: 0
};
const activatedGenerated = {
line: 1,
column: 0
};
const activatedMapping = {
generated: activatedGenerated
};
let line = 1;
let column = 0;
let sourceMappingActive = false;
const origHandlersNode = handlers.node;
handlers.node = function(node) {
if (node.loc && node.loc.start && trackNodes.has(node.type)) {
const nodeLine = node.loc.start.line;
const nodeColumn = node.loc.start.column - 1;
if (original.line !== nodeLine ||
original.column !== nodeColumn) {
original.line = nodeLine;
original.column = nodeColumn;
generated.line = line;
generated.column = column;
if (sourceMappingActive) {
sourceMappingActive = false;
if (generated.line !== activatedGenerated.line ||
generated.column !== activatedGenerated.column) {
map.addMapping(activatedMapping);
}
}
sourceMappingActive = true;
map.addMapping({
source: node.loc.source,
original,
generated
});
}
}
origHandlersNode.call(this, node);
if (sourceMappingActive && trackNodes.has(node.type)) {
activatedGenerated.line = line;
activatedGenerated.column = column;
}
};
const origHandlersEmit = handlers.emit;
handlers.emit = function(value, type, auto) {
for (let i = 0; i < value.length; i++) {
if (value.charCodeAt(i) === 10) { // \n
line++;
column = 0;
} else {
column++;
}
}
origHandlersEmit(value, type, auto);
};
const origHandlersResult = handlers.result;
handlers.result = function() {
if (sourceMappingActive) {
map.addMapping(activatedMapping);
}
return {
css: origHandlersResult(),
map
};
};
return handlers;
}
sourceMap$1.generateSourceMap = generateSourceMap;
var tokenBefore$1 = {};
const types$N = types$S;
const PLUSSIGN$9 = 0x002B; // U+002B PLUS SIGN (+)
const HYPHENMINUS$6 = 0x002D; // U+002D HYPHEN-MINUS (-)
const code = (type, value) => {
if (type === types$N.Delim) {
type = value;
}
if (typeof type === 'string') {
const charCode = type.charCodeAt(0);
return charCode > 0x7F ? 0x8000 : charCode << 8;
}
return type;
};
// https://www.w3.org/TR/css-syntax-3/#serialization
// The only requirement for serialization is that it must "round-trip" with parsing,
// that is, parsing the stylesheet must produce the same data structures as parsing,
// serializing, and parsing again, except for consecutive <whitespace-token>s,
// which may be collapsed into a single token.
const specPairs = [
[types$N.Ident, types$N.Ident],
[types$N.Ident, types$N.Function],
[types$N.Ident, types$N.Url],
[types$N.Ident, types$N.BadUrl],
[types$N.Ident, '-'],
[types$N.Ident, types$N.Number],
[types$N.Ident, types$N.Percentage],
[types$N.Ident, types$N.Dimension],
[types$N.Ident, types$N.CDC],
[types$N.Ident, types$N.LeftParenthesis],
[types$N.AtKeyword, types$N.Ident],
[types$N.AtKeyword, types$N.Function],
[types$N.AtKeyword, types$N.Url],
[types$N.AtKeyword, types$N.BadUrl],
[types$N.AtKeyword, '-'],
[types$N.AtKeyword, types$N.Number],
[types$N.AtKeyword, types$N.Percentage],
[types$N.AtKeyword, types$N.Dimension],
[types$N.AtKeyword, types$N.CDC],
[types$N.Hash, types$N.Ident],
[types$N.Hash, types$N.Function],
[types$N.Hash, types$N.Url],
[types$N.Hash, types$N.BadUrl],
[types$N.Hash, '-'],
[types$N.Hash, types$N.Number],
[types$N.Hash, types$N.Percentage],
[types$N.Hash, types$N.Dimension],
[types$N.Hash, types$N.CDC],
[types$N.Dimension, types$N.Ident],
[types$N.Dimension, types$N.Function],
[types$N.Dimension, types$N.Url],
[types$N.Dimension, types$N.BadUrl],
[types$N.Dimension, '-'],
[types$N.Dimension, types$N.Number],
[types$N.Dimension, types$N.Percentage],
[types$N.Dimension, types$N.Dimension],
[types$N.Dimension, types$N.CDC],
['#', types$N.Ident],
['#', types$N.Function],
['#', types$N.Url],
['#', types$N.BadUrl],
['#', '-'],
['#', types$N.Number],
['#', types$N.Percentage],
['#', types$N.Dimension],
['#', types$N.CDC], // https://github.com/w3c/csswg-drafts/pull/6874
['-', types$N.Ident],
['-', types$N.Function],
['-', types$N.Url],
['-', types$N.BadUrl],
['-', '-'],
['-', types$N.Number],
['-', types$N.Percentage],
['-', types$N.Dimension],
['-', types$N.CDC], // https://github.com/w3c/csswg-drafts/pull/6874
[types$N.Number, types$N.Ident],
[types$N.Number, types$N.Function],
[types$N.Number, types$N.Url],
[types$N.Number, types$N.BadUrl],
[types$N.Number, types$N.Number],
[types$N.Number, types$N.Percentage],
[types$N.Number, types$N.Dimension],
[types$N.Number, '%'],
[types$N.Number, types$N.CDC], // https://github.com/w3c/csswg-drafts/pull/6874
['@', types$N.Ident],
['@', types$N.Function],
['@', types$N.Url],
['@', types$N.BadUrl],
['@', '-'],
['@', types$N.CDC], // https://github.com/w3c/csswg-drafts/pull/6874
['.', types$N.Number],
['.', types$N.Percentage],
['.', types$N.Dimension],
['+', types$N.Number],
['+', types$N.Percentage],
['+', types$N.Dimension],
['/', '*']
];
// validate with scripts/generate-safe
const safePairs = specPairs.concat([
[types$N.Ident, types$N.Hash],
[types$N.Dimension, types$N.Hash],
[types$N.Hash, types$N.Hash],
[types$N.AtKeyword, types$N.LeftParenthesis],
[types$N.AtKeyword, types$N.String],
[types$N.AtKeyword, types$N.Colon],
[types$N.Percentage, types$N.Percentage],
[types$N.Percentage, types$N.Dimension],
[types$N.Percentage, types$N.Function],
[types$N.Percentage, '-'],
[types$N.RightParenthesis, types$N.Ident],
[types$N.RightParenthesis, types$N.Function],
[types$N.RightParenthesis, types$N.Percentage],
[types$N.RightParenthesis, types$N.Dimension],
[types$N.RightParenthesis, types$N.Hash],
[types$N.RightParenthesis, '-']
]);
function createMap(pairs) {
const isWhiteSpaceRequired = new Set(
pairs.map(([prev, next]) => (code(prev) << 16 | code(next)))
);
return function(prevCode, type, value) {
const nextCode = code(type, value);
const nextCharCode = value.charCodeAt(0);
const emitWs =
(nextCharCode === HYPHENMINUS$6 &&
type !== types$N.Ident &&
type !== types$N.Function &&
type !== types$N.CDC) ||
(nextCharCode === PLUSSIGN$9)
? isWhiteSpaceRequired.has(prevCode << 16 | nextCharCode << 8)
: isWhiteSpaceRequired.has(prevCode << 16 | nextCode);
if (emitWs) {
this.emit(' ', types$N.WhiteSpace, true);
}
return nextCode;
};
}
const spec = createMap(specPairs);
const safe = createMap(safePairs);
tokenBefore$1.safe = safe;
tokenBefore$1.spec = spec;
const index$a = tokenizer$2;
const sourceMap = sourceMap$1;
const tokenBefore = tokenBefore$1;
const types$M = types$S;
const REVERSESOLIDUS = 0x005c; // U+005C REVERSE SOLIDUS (\)
function processChildren(node, delimeter) {
if (typeof delimeter === 'function') {
let prev = null;
node.children.forEach(node => {
if (prev !== null) {
delimeter.call(this, prev);
}
this.node(node);
prev = node;
});
return;
}
node.children.forEach(this.node, this);
}
function processChunk(chunk) {
index$a.tokenize(chunk, (type, start, end) => {
this.token(type, chunk.slice(start, end));
});
}
function createGenerator(config) {
const types$1 = new Map();
for (let name in config.node) {
const item = config.node[name];
const fn = item.generate || item;
if (typeof fn === 'function') {
types$1.set(name, item.generate || item);
}
}
return function(node, options) {
let buffer = '';
let prevCode = 0;
let handlers = {
node(node) {
if (types$1.has(node.type)) {
types$1.get(node.type).call(publicApi, node);
} else {
throw new Error('Unknown node type: ' + node.type);
}
},
tokenBefore: tokenBefore.safe,
token(type, value) {
prevCode = this.tokenBefore(prevCode, type, value);
this.emit(value, type, false);
if (type === types$M.Delim && value.charCodeAt(0) === REVERSESOLIDUS) {
this.emit('\n', types$M.WhiteSpace, true);
}
},
emit(value) {
buffer += value;
},
result() {
return buffer;
}
};
if (options) {
if (typeof options.decorator === 'function') {
handlers = options.decorator(handlers);
}
if (options.sourceMap) {
handlers = sourceMap.generateSourceMap(handlers);
}
if (options.mode in tokenBefore) {
handlers.tokenBefore = tokenBefore[options.mode];
}
}
const publicApi = {
node: (node) => handlers.node(node),
children: processChildren,
token: (type, value) => handlers.token(type, value),
tokenize: processChunk
};
handlers.node(node);
return handlers.result();
};
}
create$6.createGenerator = createGenerator;
var create$5 = {};
const List$4 = List$7;
function createConvertor(walk) {
return {
fromPlainObject(ast) {
walk(ast, {
enter(node) {
if (node.children && node.children instanceof List$4.List === false) {
node.children = new List$4.List().fromArray(node.children);
}
}
});
return ast;
},
toPlainObject(ast) {
walk(ast, {
leave(node) {
if (node.children && node.children instanceof List$4.List) {
node.children = node.children.toArray();
}
}
});
return ast;
}
};
}
create$5.createConvertor = createConvertor;
var create$4 = {};
const { hasOwnProperty: hasOwnProperty$8 } = Object.prototype;
const noop$2 = function() {};
function ensureFunction$1(value) {
return typeof value === 'function' ? value : noop$2;
}
function invokeForType(fn, type) {
return function(node, item, list) {
if (node.type === type) {
fn.call(this, node, item, list);
}
};
}
function getWalkersFromStructure(name, nodeType) {
const structure = nodeType.structure;
const walkers = [];
for (const key in structure) {
if (hasOwnProperty$8.call(structure, key) === false) {
continue;
}
let fieldTypes = structure[key];
const walker = {
name: key,
type: false,
nullable: false
};
if (!Array.isArray(fieldTypes)) {
fieldTypes = [fieldTypes];
}
for (const fieldType of fieldTypes) {
if (fieldType === null) {
walker.nullable = true;
} else if (typeof fieldType === 'string') {
walker.type = 'node';
} else if (Array.isArray(fieldType)) {
walker.type = 'list';
}
}
if (walker.type) {
walkers.push(walker);
}
}
if (walkers.length) {
return {
context: nodeType.walkContext,
fields: walkers
};
}
return null;
}
function getTypesFromConfig(config) {
const types = {};
for (const name in config.node) {
if (hasOwnProperty$8.call(config.node, name)) {
const nodeType = config.node[name];
if (!nodeType.structure) {
throw new Error('Missed `structure` field in `' + name + '` node type definition');
}
types[name] = getWalkersFromStructure(name, nodeType);
}
}
return types;
}
function createTypeIterator(config, reverse) {
const fields = config.fields.slice();
const contextName = config.context;
const useContext = typeof contextName === 'string';
if (reverse) {
fields.reverse();
}
return function(node, context, walk, walkReducer) {
let prevContextValue;
if (useContext) {
prevContextValue = context[contextName];
context[contextName] = node;
}
for (const field of fields) {
const ref = node[field.name];
if (!field.nullable || ref) {
if (field.type === 'list') {
const breakWalk = reverse
? ref.reduceRight(walkReducer, false)
: ref.reduce(walkReducer, false);
if (breakWalk) {
return true;
}
} else if (walk(ref)) {
return true;
}
}
}
if (useContext) {
context[contextName] = prevContextValue;
}
};
}
function createFastTraveralMap({
StyleSheet,
Atrule,
Rule,
Block,
DeclarationList
}) {
return {
Atrule: {
StyleSheet,
Atrule,
Rule,
Block
},
Rule: {
StyleSheet,
Atrule,
Rule,
Block
},
Declaration: {
StyleSheet,
Atrule,
Rule,
Block,
DeclarationList
}
};
}
function createWalker(config) {
const types = getTypesFromConfig(config);
const iteratorsNatural = {};
const iteratorsReverse = {};
const breakWalk = Symbol('break-walk');
const skipNode = Symbol('skip-node');
for (const name in types) {
if (hasOwnProperty$8.call(types, name) && types[name] !== null) {
iteratorsNatural[name] = createTypeIterator(types[name], false);
iteratorsReverse[name] = createTypeIterator(types[name], true);
}
}
const fastTraversalIteratorsNatural = createFastTraveralMap(iteratorsNatural);
const fastTraversalIteratorsReverse = createFastTraveralMap(iteratorsReverse);
const walk = function(root, options) {
function walkNode(node, item, list) {
const enterRet = enter.call(context, node, item, list);
if (enterRet === breakWalk) {
return true;
}
if (enterRet === skipNode) {
return false;
}
if (iterators.hasOwnProperty(node.type)) {
if (iterators[node.type](node, context, walkNode, walkReducer)) {
return true;
}
}
if (leave.call(context, node, item, list) === breakWalk) {
return true;
}
return false;
}
let enter = noop$2;
let leave = noop$2;
let iterators = iteratorsNatural;
let walkReducer = (ret, data, item, list) => ret || walkNode(data, item, list);
const context = {
break: breakWalk,
skip: skipNode,
root,
stylesheet: null,
atrule: null,
atrulePrelude: null,
rule: null,
selector: null,
block: null,
declaration: null,
function: null
};
if (typeof options === 'function') {
enter = options;
} else if (options) {
enter = ensureFunction$1(options.enter);
leave = ensureFunction$1(options.leave);
if (options.reverse) {
iterators = iteratorsReverse;
}
if (options.visit) {
if (fastTraversalIteratorsNatural.hasOwnProperty(options.visit)) {
iterators = options.reverse
? fastTraversalIteratorsReverse[options.visit]
: fastTraversalIteratorsNatural[options.visit];
} else if (!types.hasOwnProperty(options.visit)) {
throw new Error('Bad value `' + options.visit + '` for `visit` option (should be: ' + Object.keys(types).sort().join(', ') + ')');
}
enter = invokeForType(enter, options.visit);
leave = invokeForType(leave, options.visit);
}
}
if (enter === noop$2 && leave === noop$2) {
throw new Error('Neither `enter` nor `leave` walker handler is set or both aren\'t a function');
}
walkNode(root);
};
walk.break = breakWalk;
walk.skip = skipNode;
walk.find = function(ast, fn) {
let found = null;
walk(ast, function(node, item, list) {
if (fn.call(this, node, item, list)) {
found = node;
return breakWalk;
}
});
return found;
};
walk.findLast = function(ast, fn) {
let found = null;
walk(ast, {
reverse: true,
enter(node, item, list) {
if (fn.call(this, node, item, list)) {
found = node;
return breakWalk;
}
}
});
return found;
};
walk.findAll = function(ast, fn) {
const found = [];
walk(ast, function(node, item, list) {
if (fn.call(this, node, item, list)) {
found.push(node);
}
});
return found;
};
return walk;
}
create$4.createWalker = createWalker;
var Lexer$3 = {};
var error$2 = {};
var generate$L = {};
function noop$1(value) {
return value;
}
function generateMultiplier(multiplier) {
const { min, max, comma } = multiplier;
if (min === 0 && max === 0) {
return comma ? '#?' : '*';
}
if (min === 0 && max === 1) {
return '?';
}
if (min === 1 && max === 0) {
return comma ? '#' : '+';
}
if (min === 1 && max === 1) {
return '';
}
return (
(comma ? '#' : '') +
(min === max
? '{' + min + '}'
: '{' + min + ',' + (max !== 0 ? max : '') + '}'
)
);
}
function generateTypeOpts(node) {
switch (node.type) {
case 'Range':
return (
' [' +
(node.min === null ? '-∞' : node.min) +
',' +
(node.max === null ? '∞' : node.max) +
']'
);
default:
throw new Error('Unknown node type `' + node.type + '`');
}
}
function generateSequence(node, decorate, forceBraces, compact) {
const combinator = node.combinator === ' ' || compact ? node.combinator : ' ' + node.combinator + ' ';
const result = node.terms
.map(term => internalGenerate(term, decorate, forceBraces, compact))
.join(combinator);
if (node.explicit || forceBraces) {
return (compact || result[0] === ',' ? '[' : '[ ') + result + (compact ? ']' : ' ]');
}
return result;
}
function internalGenerate(node, decorate, forceBraces, compact) {
let result;
switch (node.type) {
case 'Group':
result =
generateSequence(node, decorate, forceBraces, compact) +
(node.disallowEmpty ? '!' : '');
break;
case 'Multiplier':
// return since node is a composition
return (
internalGenerate(node.term, decorate, forceBraces, compact) +
decorate(generateMultiplier(node), node)
);
case 'Type':
result = '<' + node.name + (node.opts ? decorate(generateTypeOpts(node.opts), node.opts) : '') + '>';
break;
case 'Property':
result = '<\'' + node.name + '\'>';
break;
case 'Keyword':
result = node.name;
break;
case 'AtKeyword':
result = '@' + node.name;
break;
case 'Function':
result = node.name + '(';
break;
case 'String':
case 'Token':
result = node.value;
break;
case 'Comma':
result = ',';
break;
default:
throw new Error('Unknown node type `' + node.type + '`');
}
return decorate(result, node);
}
function generate$K(node, options) {
let decorate = noop$1;
let forceBraces = false;
let compact = false;
if (typeof options === 'function') {
decorate = options;
} else if (options) {
forceBraces = Boolean(options.forceBraces);
compact = Boolean(options.compact);
if (typeof options.decorate === 'function') {
decorate = options.decorate;
}
}
return internalGenerate(node, decorate, forceBraces, compact);
}
generate$L.generate = generate$K;
const createCustomError$1 = createCustomError$4;
const generate$J = generate$L;
const defaultLoc = { offset: 0, line: 1, column: 1 };
function locateMismatch(matchResult, node) {
const tokens = matchResult.tokens;
const longestMatch = matchResult.longestMatch;
const mismatchNode = longestMatch < tokens.length ? tokens[longestMatch].node || null : null;
const badNode = mismatchNode !== node ? mismatchNode : null;
let mismatchOffset = 0;
let mismatchLength = 0;
let entries = 0;
let css = '';
let start;
let end;
for (let i = 0; i < tokens.length; i++) {
const token = tokens[i].value;
if (i === longestMatch) {
mismatchLength = token.length;
mismatchOffset = css.length;
}
if (badNode !== null && tokens[i].node === badNode) {
if (i <= longestMatch) {
entries++;
} else {
entries = 0;
}
}
css += token;
}
if (longestMatch === tokens.length || entries > 1) { // last
start = fromLoc(badNode || node, 'end') || buildLoc(defaultLoc, css);
end = buildLoc(start);
} else {
start = fromLoc(badNode, 'start') ||
buildLoc(fromLoc(node, 'start') || defaultLoc, css.slice(0, mismatchOffset));
end = fromLoc(badNode, 'end') ||
buildLoc(start, css.substr(mismatchOffset, mismatchLength));
}
return {
css,
mismatchOffset,
mismatchLength,
start,
end
};
}
function fromLoc(node, point) {
const value = node && node.loc && node.loc[point];
if (value) {
return 'line' in value ? buildLoc(value) : value;
}
return null;
}
function buildLoc({ offset, line, column }, extra) {
const loc = {
offset,
line,
column
};
if (extra) {
const lines = extra.split(/\n|\r\n?|\f/);
loc.offset += extra.length;
loc.line += lines.length - 1;
loc.column = lines.length === 1 ? loc.column + extra.length : lines.pop().length + 1;
}
return loc;
}
const SyntaxReferenceError = function(type, referenceName) {
const error = createCustomError$1.createCustomError(
'SyntaxReferenceError',
type + (referenceName ? ' `' + referenceName + '`' : '')
);
error.reference = referenceName;
return error;
};
const SyntaxMatchError = function(message, syntax, node, matchResult) {
const error = createCustomError$1.createCustomError('SyntaxMatchError', message);
const {
css,
mismatchOffset,
mismatchLength,
start,
end
} = locateMismatch(matchResult, node);
error.rawMessage = message;
error.syntax = syntax ? generate$J.generate(syntax) : '<generic>';
error.css = css;
error.mismatchOffset = mismatchOffset;
error.mismatchLength = mismatchLength;
error.message = message + '\n' +
' syntax: ' + error.syntax + '\n' +
' value: ' + (css || '<empty string>') + '\n' +
' --------' + new Array(error.mismatchOffset + 1).join('-') + '^';
Object.assign(error, start);
error.loc = {
source: (node && node.loc && node.loc.source) || '<unknown>',
start,
end
};
return error;
};
error$2.SyntaxMatchError = SyntaxMatchError;
error$2.SyntaxReferenceError = SyntaxReferenceError;
var names$4 = {};
const keywords$1 = new Map();
const properties$1 = new Map();
const HYPHENMINUS$5 = 45; // '-'.charCodeAt()
const keyword = getKeywordDescriptor;
const property = getPropertyDescriptor;
const vendorPrefix = getVendorPrefix;
function isCustomProperty(str, offset) {
offset = offset || 0;
return str.length - offset >= 2 &&
str.charCodeAt(offset) === HYPHENMINUS$5 &&
str.charCodeAt(offset + 1) === HYPHENMINUS$5;
}
function getVendorPrefix(str, offset) {
offset = offset || 0;
// verdor prefix should be at least 3 chars length
if (str.length - offset >= 3) {
// vendor prefix starts with hyper minus following non-hyper minus
if (str.charCodeAt(offset) === HYPHENMINUS$5 &&
str.charCodeAt(offset + 1) !== HYPHENMINUS$5) {
// vendor prefix should contain a hyper minus at the ending
const secondDashIndex = str.indexOf('-', offset + 2);
if (secondDashIndex !== -1) {
return str.substring(offset, secondDashIndex + 1);
}
}
}
return '';
}
function getKeywordDescriptor(keyword) {
if (keywords$1.has(keyword)) {
return keywords$1.get(keyword);
}
const name = keyword.toLowerCase();
let descriptor = keywords$1.get(name);
if (descriptor === undefined) {
const custom = isCustomProperty(name, 0);
const vendor = !custom ? getVendorPrefix(name, 0) : '';
descriptor = Object.freeze({
basename: name.substr(vendor.length),
name,
prefix: vendor,
vendor,
custom
});
}
keywords$1.set(keyword, descriptor);
return descriptor;
}
function getPropertyDescriptor(property) {
if (properties$1.has(property)) {
return properties$1.get(property);
}
let name = property;
let hack = property[0];
if (hack === '/') {
hack = property[1] === '/' ? '//' : '/';
} else if (hack !== '_' &&
hack !== '*' &&
hack !== '$' &&
hack !== '#' &&
hack !== '+' &&
hack !== '&') {
hack = '';
}
const custom = isCustomProperty(name, hack.length);
// re-use result when possible (the same as for lower case)
if (!custom) {
name = name.toLowerCase();
if (properties$1.has(name)) {
const descriptor = properties$1.get(name);
properties$1.set(property, descriptor);
return descriptor;
}
}
const vendor = !custom ? getVendorPrefix(name, hack.length) : '';
const prefix = name.substr(0, hack.length + vendor.length);
const descriptor = Object.freeze({
basename: name.substr(prefix.length),
name: name.substr(hack.length),
hack,
vendor,
prefix,
custom
});
properties$1.set(property, descriptor);
return descriptor;
}
names$4.isCustomProperty = isCustomProperty;
names$4.keyword = keyword;
names$4.property = property;
names$4.vendorPrefix = vendorPrefix;
var genericConst$2 = {};
// https://drafts.csswg.org/css-cascade-5/
const cssWideKeywords = [
'initial',
'inherit',
'unset',
'revert',
'revert-layer'
];
genericConst$2.cssWideKeywords = cssWideKeywords;
const charCodeDefinitions$8 = charCodeDefinitions$c;
const types$L = types$S;
const utils$g = utils$k;
const PLUSSIGN$8 = 0x002B; // U+002B PLUS SIGN (+)
const HYPHENMINUS$4 = 0x002D; // U+002D HYPHEN-MINUS (-)
const N$3 = 0x006E; // U+006E LATIN SMALL LETTER N (n)
const DISALLOW_SIGN$1 = true;
const ALLOW_SIGN$1 = false;
function isDelim$1(token, code) {
return token !== null && token.type === types$L.Delim && token.value.charCodeAt(0) === code;
}
function skipSC(token, offset, getNextToken) {
while (token !== null && (token.type === types$L.WhiteSpace || token.type === types$L.Comment)) {
token = getNextToken(++offset);
}
return offset;
}
function checkInteger$1(token, valueOffset, disallowSign, offset) {
if (!token) {
return 0;
}
const code = token.value.charCodeAt(valueOffset);
if (code === PLUSSIGN$8 || code === HYPHENMINUS$4) {
if (disallowSign) {
// Number sign is not allowed
return 0;
}
valueOffset++;
}
for (; valueOffset < token.value.length; valueOffset++) {
if (!charCodeDefinitions$8.isDigit(token.value.charCodeAt(valueOffset))) {
// Integer is expected
return 0;
}
}
return offset + 1;
}
// ... <signed-integer>
// ... ['+' | '-'] <signless-integer>
function consumeB$1(token, offset_, getNextToken) {
let sign = false;
let offset = skipSC(token, offset_, getNextToken);
token = getNextToken(offset);
if (token === null) {
return offset_;
}
if (token.type !== types$L.Number) {
if (isDelim$1(token, PLUSSIGN$8) || isDelim$1(token, HYPHENMINUS$4)) {
sign = true;
offset = skipSC(getNextToken(++offset), offset, getNextToken);
token = getNextToken(offset);
if (token === null || token.type !== types$L.Number) {
return 0;
}
} else {
return offset_;
}
}
if (!sign) {
const code = token.value.charCodeAt(0);
if (code !== PLUSSIGN$8 && code !== HYPHENMINUS$4) {
// Number sign is expected
return 0;
}
}
return checkInteger$1(token, sign ? 0 : 1, sign, offset);
}
// An+B microsyntax https://www.w3.org/TR/css-syntax-3/#anb
function anPlusB(token, getNextToken) {
/* eslint-disable brace-style*/
let offset = 0;
if (!token) {
return 0;
}
// <integer>
if (token.type === types$L.Number) {
return checkInteger$1(token, 0, ALLOW_SIGN$1, offset); // b
}
// -n
// -n <signed-integer>
// -n ['+' | '-'] <signless-integer>
// -n- <signless-integer>
// <dashndashdigit-ident>
else if (token.type === types$L.Ident && token.value.charCodeAt(0) === HYPHENMINUS$4) {
// expect 1st char is N
if (!utils$g.cmpChar(token.value, 1, N$3)) {
return 0;
}
switch (token.value.length) {
// -n
// -n <signed-integer>
// -n ['+' | '-'] <signless-integer>
case 2:
return consumeB$1(getNextToken(++offset), offset, getNextToken);
// -n- <signless-integer>
case 3:
if (token.value.charCodeAt(2) !== HYPHENMINUS$4) {
return 0;
}
offset = skipSC(getNextToken(++offset), offset, getNextToken);
token = getNextToken(offset);
return checkInteger$1(token, 0, DISALLOW_SIGN$1, offset);
// <dashndashdigit-ident>
default:
if (token.value.charCodeAt(2) !== HYPHENMINUS$4) {
return 0;
}
return checkInteger$1(token, 3, DISALLOW_SIGN$1, offset);
}
}
// '+'? n
// '+'? n <signed-integer>
// '+'? n ['+' | '-'] <signless-integer>
// '+'? n- <signless-integer>
// '+'? <ndashdigit-ident>
else if (token.type === types$L.Ident || (isDelim$1(token, PLUSSIGN$8) && getNextToken(offset + 1).type === types$L.Ident)) {
// just ignore a plus
if (token.type !== types$L.Ident) {
token = getNextToken(++offset);
}
if (token === null || !utils$g.cmpChar(token.value, 0, N$3)) {
return 0;
}
switch (token.value.length) {
// '+'? n
// '+'? n <signed-integer>
// '+'? n ['+' | '-'] <signless-integer>
case 1:
return consumeB$1(getNextToken(++offset), offset, getNextToken);
// '+'? n- <signless-integer>
case 2:
if (token.value.charCodeAt(1) !== HYPHENMINUS$4) {
return 0;
}
offset = skipSC(getNextToken(++offset), offset, getNextToken);
token = getNextToken(offset);
return checkInteger$1(token, 0, DISALLOW_SIGN$1, offset);
// '+'? <ndashdigit-ident>
default:
if (token.value.charCodeAt(1) !== HYPHENMINUS$4) {
return 0;
}
return checkInteger$1(token, 2, DISALLOW_SIGN$1, offset);
}
}
// <ndashdigit-dimension>
// <ndash-dimension> <signless-integer>
// <n-dimension>
// <n-dimension> <signed-integer>
// <n-dimension> ['+' | '-'] <signless-integer>
else if (token.type === types$L.Dimension) {
let code = token.value.charCodeAt(0);
let sign = code === PLUSSIGN$8 || code === HYPHENMINUS$4 ? 1 : 0;
let i = sign;
for (; i < token.value.length; i++) {
if (!charCodeDefinitions$8.isDigit(token.value.charCodeAt(i))) {
break;
}
}
if (i === sign) {
// Integer is expected
return 0;
}
if (!utils$g.cmpChar(token.value, i, N$3)) {
return 0;
}
// <n-dimension>
// <n-dimension> <signed-integer>
// <n-dimension> ['+' | '-'] <signless-integer>
if (i + 1 === token.value.length) {
return consumeB$1(getNextToken(++offset), offset, getNextToken);
} else {
if (token.value.charCodeAt(i + 1) !== HYPHENMINUS$4) {
return 0;
}
// <ndash-dimension> <signless-integer>
if (i + 2 === token.value.length) {
offset = skipSC(getNextToken(++offset), offset, getNextToken);
token = getNextToken(offset);
return checkInteger$1(token, 0, DISALLOW_SIGN$1, offset);
}
// <ndashdigit-dimension>
else {
return checkInteger$1(token, i + 2, DISALLOW_SIGN$1, offset);
}
}
}
return 0;
}
var genericAnPlusB$1 = anPlusB;
const charCodeDefinitions$7 = charCodeDefinitions$c;
const types$K = types$S;
const utils$f = utils$k;
const PLUSSIGN$7 = 0x002B; // U+002B PLUS SIGN (+)
const HYPHENMINUS$3 = 0x002D; // U+002D HYPHEN-MINUS (-)
const QUESTIONMARK$2 = 0x003F; // U+003F QUESTION MARK (?)
const U$1 = 0x0075; // U+0075 LATIN SMALL LETTER U (u)
function isDelim(token, code) {
return token !== null && token.type === types$K.Delim && token.value.charCodeAt(0) === code;
}
function startsWith$1(token, code) {
return token.value.charCodeAt(0) === code;
}
function hexSequence(token, offset, allowDash) {
let hexlen = 0;
for (let pos = offset; pos < token.value.length; pos++) {
const code = token.value.charCodeAt(pos);
if (code === HYPHENMINUS$3 && allowDash && hexlen !== 0) {
hexSequence(token, offset + hexlen + 1, false);
return 6; // dissallow following question marks
}
if (!charCodeDefinitions$7.isHexDigit(code)) {
return 0; // not a hex digit
}
if (++hexlen > 6) {
return 0; // too many hex digits
} }
return hexlen;
}
function withQuestionMarkSequence(consumed, length, getNextToken) {
if (!consumed) {
return 0; // nothing consumed
}
while (isDelim(getNextToken(length), QUESTIONMARK$2)) {
if (++consumed > 6) {
return 0; // too many question marks
}
length++;
}
return length;
}
// https://drafts.csswg.org/css-syntax/#urange
// Informally, the <urange> production has three forms:
// U+0001
// Defines a range consisting of a single code point, in this case the code point "1".
// U+0001-00ff
// Defines a range of codepoints between the first and the second value, in this case
// the range between "1" and "ff" (255 in decimal) inclusive.
// U+00??
// Defines a range of codepoints where the "?" characters range over all hex digits,
// in this case defining the same as the value U+0000-00ff.
// In each form, a maximum of 6 digits is allowed for each hexadecimal number (if you treat "?" as a hexadecimal digit).
//
// <urange> =
// u '+' <ident-token> '?'* |
// u <dimension-token> '?'* |
// u <number-token> '?'* |
// u <number-token> <dimension-token> |
// u <number-token> <number-token> |
// u '+' '?'+
function urange(token, getNextToken) {
let length = 0;
// should start with `u` or `U`
if (token === null || token.type !== types$K.Ident || !utils$f.cmpChar(token.value, 0, U$1)) {
return 0;
}
token = getNextToken(++length);
if (token === null) {
return 0;
}
// u '+' <ident-token> '?'*
// u '+' '?'+
if (isDelim(token, PLUSSIGN$7)) {
token = getNextToken(++length);
if (token === null) {
return 0;
}
if (token.type === types$K.Ident) {
// u '+' <ident-token> '?'*
return withQuestionMarkSequence(hexSequence(token, 0, true), ++length, getNextToken);
}
if (isDelim(token, QUESTIONMARK$2)) {
// u '+' '?'+
return withQuestionMarkSequence(1, ++length, getNextToken);
}
// Hex digit or question mark is expected
return 0;
}
// u <number-token> '?'*
// u <number-token> <dimension-token>
// u <number-token> <number-token>
if (token.type === types$K.Number) {
const consumedHexLength = hexSequence(token, 1, true);
if (consumedHexLength === 0) {
return 0;
}
token = getNextToken(++length);
if (token === null) {
// u <number-token> <eof>
return length;
}
if (token.type === types$K.Dimension || token.type === types$K.Number) {
// u <number-token> <dimension-token>
// u <number-token> <number-token>
if (!startsWith$1(token, HYPHENMINUS$3) || !hexSequence(token, 1, false)) {
return 0;
}
return length + 1;
}
// u <number-token> '?'*
return withQuestionMarkSequence(consumedHexLength, length, getNextToken);
}
// u <dimension-token> '?'*
if (token.type === types$K.Dimension) {
return withQuestionMarkSequence(hexSequence(token, 1, true), ++length, getNextToken);
}
return 0;
}
var genericUrange$1 = urange;
const genericConst$1 = genericConst$2;
const genericAnPlusB = genericAnPlusB$1;
const genericUrange = genericUrange$1;
const types$J = types$S;
const charCodeDefinitions$6 = charCodeDefinitions$c;
const utils$e = utils$k;
const calcFunctionNames = ['calc(', '-moz-calc(', '-webkit-calc('];
const balancePair = new Map([
[types$J.Function, types$J.RightParenthesis],
[types$J.LeftParenthesis, types$J.RightParenthesis],
[types$J.LeftSquareBracket, types$J.RightSquareBracket],
[types$J.LeftCurlyBracket, types$J.RightCurlyBracket]
]);
// units
const LENGTH = [
// absolute length units https://www.w3.org/TR/css-values-3/#lengths
'cm', 'mm', 'q', 'in', 'pt', 'pc', 'px',
// font-relative length units https://drafts.csswg.org/css-values-4/#font-relative-lengths
'em', 'rem',
'ex', 'rex',
'cap', 'rcap',
'ch', 'rch',
'ic', 'ric',
'lh', 'rlh',
// viewport-percentage lengths https://drafts.csswg.org/css-values-4/#viewport-relative-lengths
'vw', 'svw', 'lvw', 'dvw',
'vh', 'svh', 'lvh', 'dvh',
'vi', 'svi', 'lvi', 'dvi',
'vb', 'svb', 'lvb', 'dvb',
'vmin', 'svmin', 'lvmin', 'dvmin',
'vmax', 'svmax', 'lvmax', 'dvmax',
// container relative lengths https://drafts.csswg.org/css-contain-3/#container-lengths
'cqw', 'cqh', 'cqi', 'cqb', 'cqmin', 'cqmax'
];
const ANGLE = ['deg', 'grad', 'rad', 'turn']; // https://www.w3.org/TR/css-values-3/#angles
const TIME = ['s', 'ms']; // https://www.w3.org/TR/css-values-3/#time
const FREQUENCY = ['hz', 'khz']; // https://www.w3.org/TR/css-values-3/#frequency
const RESOLUTION = ['dpi', 'dpcm', 'dppx', 'x']; // https://www.w3.org/TR/css-values-3/#resolution
const FLEX = ['fr']; // https://drafts.csswg.org/css-grid/#fr-unit
const DECIBEL = ['db']; // https://www.w3.org/TR/css3-speech/#mixing-props-voice-volume
const SEMITONES = ['st']; // https://www.w3.org/TR/css3-speech/#voice-props-voice-pitch
// safe char code getter
function charCodeAt(str, index) {
return index < str.length ? str.charCodeAt(index) : 0;
}
function eqStr(actual, expected) {
return utils$e.cmpStr(actual, 0, actual.length, expected);
}
function eqStrAny(actual, expected) {
for (let i = 0; i < expected.length; i++) {
if (eqStr(actual, expected[i])) {
return true;
}
}
return false;
}
// IE postfix hack, i.e. 123\0 or 123px\9
function isPostfixIeHack(str, offset) {
if (offset !== str.length - 2) {
return false;
}
return (
charCodeAt(str, offset) === 0x005C && // U+005C REVERSE SOLIDUS (\)
charCodeDefinitions$6.isDigit(charCodeAt(str, offset + 1))
);
}
function outOfRange(opts, value, numEnd) {
if (opts && opts.type === 'Range') {
const num = Number(
numEnd !== undefined && numEnd !== value.length
? value.substr(0, numEnd)
: value
);
if (isNaN(num)) {
return true;
}
// FIXME: when opts.min is a string it's a dimension, skip a range validation
// for now since it requires a type covertation which is not implmented yet
if (opts.min !== null && num < opts.min && typeof opts.min !== 'string') {
return true;
}
// FIXME: when opts.max is a string it's a dimension, skip a range validation
// for now since it requires a type covertation which is not implmented yet
if (opts.max !== null && num > opts.max && typeof opts.max !== 'string') {
return true;
}
}
return false;
}
function consumeFunction(token, getNextToken) {
let balanceCloseType = 0;
let balanceStash = [];
let length = 0;
// balanced token consuming
scan:
do {
switch (token.type) {
case types$J.RightCurlyBracket:
case types$J.RightParenthesis:
case types$J.RightSquareBracket:
if (token.type !== balanceCloseType) {
break scan;
}
balanceCloseType = balanceStash.pop();
if (balanceStash.length === 0) {
length++;
break scan;
}
break;
case types$J.Function:
case types$J.LeftParenthesis:
case types$J.LeftSquareBracket:
case types$J.LeftCurlyBracket:
balanceStash.push(balanceCloseType);
balanceCloseType = balancePair.get(token.type);
break;
}
length++;
} while (token = getNextToken(length));
return length;
}
// TODO: implement
// can be used wherever <length>, <frequency>, <angle>, <time>, <percentage>, <number>, or <integer> values are allowed
// https://drafts.csswg.org/css-values/#calc-notation
function calc(next) {
return function(token, getNextToken, opts) {
if (token === null) {
return 0;
}
if (token.type === types$J.Function && eqStrAny(token.value, calcFunctionNames)) {
return consumeFunction(token, getNextToken);
}
return next(token, getNextToken, opts);
};
}
function tokenType(expectedTokenType) {
return function(token) {
if (token === null || token.type !== expectedTokenType) {
return 0;
}
return 1;
};
}
// =========================
// Complex types
//
// https://drafts.csswg.org/css-values-4/#custom-idents
// 4.2. Author-defined Identifiers: the <custom-ident> type
// Some properties accept arbitrary author-defined identifiers as a component value.
// This generic data type is denoted by <custom-ident>, and represents any valid CSS identifier
// that would not be misinterpreted as a pre-defined keyword in that propertys value definition.
//
// See also: https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident
function customIdent(token) {
if (token === null || token.type !== types$J.Ident) {
return 0;
}
const name = token.value.toLowerCase();
// The CSS-wide keywords are not valid <custom-ident>s
if (eqStrAny(name, genericConst$1.cssWideKeywords)) {
return 0;
}
// The default keyword is reserved and is also not a valid <custom-ident>
if (eqStr(name, 'default')) {
return 0;
}
// TODO: ignore property specific keywords (as described https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident)
// Specifications using <custom-ident> must specify clearly what other keywords
// are excluded from <custom-ident>, if any—for example by saying that any pre-defined keywords
// in that propertys value definition are excluded. Excluded keywords are excluded
// in all ASCII case permutations.
return 1;
}
// https://drafts.csswg.org/css-variables/#typedef-custom-property-name
// A custom property is any property whose name starts with two dashes (U+002D HYPHEN-MINUS), like --foo.
// The <custom-property-name> production corresponds to this: its defined as any valid identifier
// that starts with two dashes, except -- itself, which is reserved for future use by CSS.
// NOTE: Current implementation treat `--` as a valid name since most (all?) major browsers treat it as valid.
function customPropertyName(token) {
// ... defined as any valid identifier
if (token === null || token.type !== types$J.Ident) {
return 0;
}
// ... that starts with two dashes (U+002D HYPHEN-MINUS)
if (charCodeAt(token.value, 0) !== 0x002D || charCodeAt(token.value, 1) !== 0x002D) {
return 0;
}
return 1;
}
// https://drafts.csswg.org/css-color-4/#hex-notation
// The syntax of a <hex-color> is a <hash-token> token whose value consists of 3, 4, 6, or 8 hexadecimal digits.
// In other words, a hex color is written as a hash character, "#", followed by some number of digits 0-9 or
// letters a-f (the case of the letters doesnt matter - #00ff00 is identical to #00FF00).
function hexColor(token) {
if (token === null || token.type !== types$J.Hash) {
return 0;
}
const length = token.value.length;
// valid values (length): #rgb (4), #rgba (5), #rrggbb (7), #rrggbbaa (9)
if (length !== 4 && length !== 5 && length !== 7 && length !== 9) {
return 0;
}
for (let i = 1; i < length; i++) {
if (!charCodeDefinitions$6.isHexDigit(charCodeAt(token.value, i))) {
return 0;
}
}
return 1;
}
function idSelector(token) {
if (token === null || token.type !== types$J.Hash) {
return 0;
}
if (!charCodeDefinitions$6.isIdentifierStart(charCodeAt(token.value, 1), charCodeAt(token.value, 2), charCodeAt(token.value, 3))) {
return 0;
}
return 1;
}
// https://drafts.csswg.org/css-syntax/#any-value
// It represents the entirety of what a valid declaration can have as its value.
function declarationValue(token, getNextToken) {
if (!token) {
return 0;
}
let balanceCloseType = 0;
let balanceStash = [];
let length = 0;
// The <declaration-value> production matches any sequence of one or more tokens,
// so long as the sequence does not contain ...
scan:
do {
switch (token.type) {
// ... <bad-string-token>, <bad-url-token>,
case types$J.BadString:
case types$J.BadUrl:
break scan;
// ... unmatched <)-token>, <]-token>, or <}-token>,
case types$J.RightCurlyBracket:
case types$J.RightParenthesis:
case types$J.RightSquareBracket:
if (token.type !== balanceCloseType) {
break scan;
}
balanceCloseType = balanceStash.pop();
break;
// ... or top-level <semicolon-token> tokens
case types$J.Semicolon:
if (balanceCloseType === 0) {
break scan;
}
break;
// ... or <delim-token> tokens with a value of "!"
case types$J.Delim:
if (balanceCloseType === 0 && token.value === '!') {
break scan;
}
break;
case types$J.Function:
case types$J.LeftParenthesis:
case types$J.LeftSquareBracket:
case types$J.LeftCurlyBracket:
balanceStash.push(balanceCloseType);
balanceCloseType = balancePair.get(token.type);
break;
}
length++;
} while (token = getNextToken(length));
return length;
}
// https://drafts.csswg.org/css-syntax/#any-value
// The <any-value> production is identical to <declaration-value>, but also
// allows top-level <semicolon-token> tokens and <delim-token> tokens
// with a value of "!". It represents the entirety of what valid CSS can be in any context.
function anyValue(token, getNextToken) {
if (!token) {
return 0;
}
let balanceCloseType = 0;
let balanceStash = [];
let length = 0;
// The <any-value> production matches any sequence of one or more tokens,
// so long as the sequence ...
scan:
do {
switch (token.type) {
// ... does not contain <bad-string-token>, <bad-url-token>,
case types$J.BadString:
case types$J.BadUrl:
break scan;
// ... unmatched <)-token>, <]-token>, or <}-token>,
case types$J.RightCurlyBracket:
case types$J.RightParenthesis:
case types$J.RightSquareBracket:
if (token.type !== balanceCloseType) {
break scan;
}
balanceCloseType = balanceStash.pop();
break;
case types$J.Function:
case types$J.LeftParenthesis:
case types$J.LeftSquareBracket:
case types$J.LeftCurlyBracket:
balanceStash.push(balanceCloseType);
balanceCloseType = balancePair.get(token.type);
break;
}
length++;
} while (token = getNextToken(length));
return length;
}
// =========================
// Dimensions
//
function dimension(type) {
if (type) {
type = new Set(type);
}
return function(token, getNextToken, opts) {
if (token === null || token.type !== types$J.Dimension) {
return 0;
}
const numberEnd = utils$e.consumeNumber(token.value, 0);
// check unit
if (type !== null) {
// check for IE postfix hack, i.e. 123px\0 or 123px\9
const reverseSolidusOffset = token.value.indexOf('\\', numberEnd);
const unit = reverseSolidusOffset === -1 || !isPostfixIeHack(token.value, reverseSolidusOffset)
? token.value.substr(numberEnd)
: token.value.substring(numberEnd, reverseSolidusOffset);
if (type.has(unit.toLowerCase()) === false) {
return 0;
}
}
// check range if specified
if (outOfRange(opts, token.value, numberEnd)) {
return 0;
}
return 1;
};
}
// =========================
// Percentage
//
// §5.5. Percentages: the <percentage> type
// https://drafts.csswg.org/css-values-4/#percentages
function percentage(token, getNextToken, opts) {
// ... corresponds to the <percentage-token> production
if (token === null || token.type !== types$J.Percentage) {
return 0;
}
// check range if specified
if (outOfRange(opts, token.value, token.value.length - 1)) {
return 0;
}
return 1;
}
// =========================
// Numeric
//
// https://drafts.csswg.org/css-values-4/#numbers
// The value <zero> represents a literal number with the value 0. Expressions that merely
// evaluate to a <number> with the value 0 (for example, calc(0)) do not match <zero>;
// only literal <number-token>s do.
function zero(next) {
if (typeof next !== 'function') {
next = function() {
return 0;
};
}
return function(token, getNextToken, opts) {
if (token !== null && token.type === types$J.Number) {
if (Number(token.value) === 0) {
return 1;
}
}
return next(token, getNextToken, opts);
};
}
// § 5.3. Real Numbers: the <number> type
// https://drafts.csswg.org/css-values-4/#numbers
// Number values are denoted by <number>, and represent real numbers, possibly with a fractional component.
// ... It corresponds to the <number-token> production
function number(token, getNextToken, opts) {
if (token === null) {
return 0;
}
const numberEnd = utils$e.consumeNumber(token.value, 0);
const isNumber = numberEnd === token.value.length;
if (!isNumber && !isPostfixIeHack(token.value, numberEnd)) {
return 0;
}
// check range if specified
if (outOfRange(opts, token.value, numberEnd)) {
return 0;
}
return 1;
}
// §5.2. Integers: the <integer> type
// https://drafts.csswg.org/css-values-4/#integers
function integer(token, getNextToken, opts) {
// ... corresponds to a subset of the <number-token> production
if (token === null || token.type !== types$J.Number) {
return 0;
}
// The first digit of an integer may be immediately preceded by `-` or `+` to indicate the integers sign.
let i = charCodeAt(token.value, 0) === 0x002B || // U+002B PLUS SIGN (+)
charCodeAt(token.value, 0) === 0x002D ? 1 : 0; // U+002D HYPHEN-MINUS (-)
// When written literally, an integer is one or more decimal digits 0 through 9 ...
for (; i < token.value.length; i++) {
if (!charCodeDefinitions$6.isDigit(charCodeAt(token.value, i))) {
return 0;
}
}
// check range if specified
if (outOfRange(opts, token.value, i)) {
return 0;
}
return 1;
}
const genericSyntaxes = {
// token types
'ident-token': tokenType(types$J.Ident),
'function-token': tokenType(types$J.Function),
'at-keyword-token': tokenType(types$J.AtKeyword),
'hash-token': tokenType(types$J.Hash),
'string-token': tokenType(types$J.String),
'bad-string-token': tokenType(types$J.BadString),
'url-token': tokenType(types$J.Url),
'bad-url-token': tokenType(types$J.BadUrl),
'delim-token': tokenType(types$J.Delim),
'number-token': tokenType(types$J.Number),
'percentage-token': tokenType(types$J.Percentage),
'dimension-token': tokenType(types$J.Dimension),
'whitespace-token': tokenType(types$J.WhiteSpace),
'CDO-token': tokenType(types$J.CDO),
'CDC-token': tokenType(types$J.CDC),
'colon-token': tokenType(types$J.Colon),
'semicolon-token': tokenType(types$J.Semicolon),
'comma-token': tokenType(types$J.Comma),
'[-token': tokenType(types$J.LeftSquareBracket),
']-token': tokenType(types$J.RightSquareBracket),
'(-token': tokenType(types$J.LeftParenthesis),
')-token': tokenType(types$J.RightParenthesis),
'{-token': tokenType(types$J.LeftCurlyBracket),
'}-token': tokenType(types$J.RightCurlyBracket),
// token type aliases
'string': tokenType(types$J.String),
'ident': tokenType(types$J.Ident),
// complex types
'custom-ident': customIdent,
'custom-property-name': customPropertyName,
'hex-color': hexColor,
'id-selector': idSelector, // element( <id-selector> )
'an-plus-b': genericAnPlusB,
'urange': genericUrange,
'declaration-value': declarationValue,
'any-value': anyValue,
// dimensions
'dimension': calc(dimension(null)),
'angle': calc(dimension(ANGLE)),
'decibel': calc(dimension(DECIBEL)),
'frequency': calc(dimension(FREQUENCY)),
'flex': calc(dimension(FLEX)),
'length': calc(zero(dimension(LENGTH))),
'resolution': calc(dimension(RESOLUTION)),
'semitones': calc(dimension(SEMITONES)),
'time': calc(dimension(TIME)),
// percentage
'percentage': calc(percentage),
// numeric
'zero': zero(),
'number': calc(number),
'integer': calc(integer)
};
var generic$1 = genericSyntaxes;
const index$9 = tokenizer$2;
const astToTokens = {
decorator(handlers) {
const tokens = [];
let curNode = null;
return {
...handlers,
node(node) {
const tmp = curNode;
curNode = node;
handlers.node.call(this, node);
curNode = tmp;
},
emit(value, type, auto) {
tokens.push({
type,
value,
node: auto ? null : curNode
});
},
result() {
return tokens;
}
};
}
};
function stringToTokens(str) {
const tokens = [];
index$9.tokenize(str, (type, start, end) =>
tokens.push({
type,
value: str.slice(start, end),
node: null
})
);
return tokens;
}
function prepareTokens$1(value, syntax) {
if (typeof value === 'string') {
return stringToTokens(value);
}
return syntax.generate(value, astToTokens);
}
var prepareTokens_1 = prepareTokens$1;
var matchGraph$2 = {};
var parse$L = {};
var tokenizer$1 = {};
var _SyntaxError = {};
const createCustomError = createCustomError$4;
function SyntaxError$3(message, input, offset) {
return Object.assign(createCustomError.createCustomError('SyntaxError', message), {
input,
offset,
rawMessage: message,
message: message + '\n' +
' ' + input + '\n' +
'--' + new Array((offset || input.length) + 1).join('-') + '^'
});
}
_SyntaxError.SyntaxError = SyntaxError$3;
const SyntaxError$2 = _SyntaxError;
const TAB$1 = 9;
const N$2 = 10;
const F$1 = 12;
const R$1 = 13;
const SPACE$3 = 32;
class Tokenizer {
constructor(str) {
this.str = str;
this.pos = 0;
}
charCodeAt(pos) {
return pos < this.str.length ? this.str.charCodeAt(pos) : 0;
}
charCode() {
return this.charCodeAt(this.pos);
}
nextCharCode() {
return this.charCodeAt(this.pos + 1);
}
nextNonWsCode(pos) {
return this.charCodeAt(this.findWsEnd(pos));
}
findWsEnd(pos) {
for (; pos < this.str.length; pos++) {
const code = this.str.charCodeAt(pos);
if (code !== R$1 && code !== N$2 && code !== F$1 && code !== SPACE$3 && code !== TAB$1) {
break;
}
}
return pos;
}
substringToPos(end) {
return this.str.substring(this.pos, this.pos = end);
}
eat(code) {
if (this.charCode() !== code) {
this.error('Expect `' + String.fromCharCode(code) + '`');
}
this.pos++;
}
peek() {
return this.pos < this.str.length ? this.str.charAt(this.pos++) : '';
}
error(message) {
throw new SyntaxError$2.SyntaxError(message, this.str, this.pos);
}
}
tokenizer$1.Tokenizer = Tokenizer;
const tokenizer = tokenizer$1;
const TAB = 9;
const N$1 = 10;
const F = 12;
const R = 13;
const SPACE$2 = 32;
const EXCLAMATIONMARK$2 = 33; // !
const NUMBERSIGN$3 = 35; // #
const AMPERSAND$1 = 38; // &
const APOSTROPHE$2 = 39; // '
const LEFTPARENTHESIS$2 = 40; // (
const RIGHTPARENTHESIS$2 = 41; // )
const ASTERISK$6 = 42; // *
const PLUSSIGN$6 = 43; // +
const COMMA = 44; // ,
const HYPERMINUS = 45; // -
const LESSTHANSIGN = 60; // <
const GREATERTHANSIGN$2 = 62; // >
const QUESTIONMARK$1 = 63; // ?
const COMMERCIALAT = 64; // @
const LEFTSQUAREBRACKET = 91; // [
const RIGHTSQUAREBRACKET = 93; // ]
const LEFTCURLYBRACKET = 123; // {
const VERTICALLINE$3 = 124; // |
const RIGHTCURLYBRACKET = 125; // }
const INFINITY = 8734; // ∞
const NAME_CHAR = new Uint8Array(128).map((_, idx) =>
/[a-zA-Z0-9\-]/.test(String.fromCharCode(idx)) ? 1 : 0
);
const COMBINATOR_PRECEDENCE = {
' ': 1,
'&&': 2,
'||': 3,
'|': 4
};
function scanSpaces(tokenizer) {
return tokenizer.substringToPos(
tokenizer.findWsEnd(tokenizer.pos)
);
}
function scanWord(tokenizer) {
let end = tokenizer.pos;
for (; end < tokenizer.str.length; end++) {
const code = tokenizer.str.charCodeAt(end);
if (code >= 128 || NAME_CHAR[code] === 0) {
break;
}
}
if (tokenizer.pos === end) {
tokenizer.error('Expect a keyword');
}
return tokenizer.substringToPos(end);
}
function scanNumber(tokenizer) {
let end = tokenizer.pos;
for (; end < tokenizer.str.length; end++) {
const code = tokenizer.str.charCodeAt(end);
if (code < 48 || code > 57) {
break;
}
}
if (tokenizer.pos === end) {
tokenizer.error('Expect a number');
}
return tokenizer.substringToPos(end);
}
function scanString(tokenizer) {
const end = tokenizer.str.indexOf('\'', tokenizer.pos + 1);
if (end === -1) {
tokenizer.pos = tokenizer.str.length;
tokenizer.error('Expect an apostrophe');
}
return tokenizer.substringToPos(end + 1);
}
function readMultiplierRange(tokenizer) {
let min = null;
let max = null;
tokenizer.eat(LEFTCURLYBRACKET);
min = scanNumber(tokenizer);
if (tokenizer.charCode() === COMMA) {
tokenizer.pos++;
if (tokenizer.charCode() !== RIGHTCURLYBRACKET) {
max = scanNumber(tokenizer);
}
} else {
max = min;
}
tokenizer.eat(RIGHTCURLYBRACKET);
return {
min: Number(min),
max: max ? Number(max) : 0
};
}
function readMultiplier(tokenizer) {
let range = null;
let comma = false;
switch (tokenizer.charCode()) {
case ASTERISK$6:
tokenizer.pos++;
range = {
min: 0,
max: 0
};
break;
case PLUSSIGN$6:
tokenizer.pos++;
range = {
min: 1,
max: 0
};
break;
case QUESTIONMARK$1:
tokenizer.pos++;
range = {
min: 0,
max: 1
};
break;
case NUMBERSIGN$3:
tokenizer.pos++;
comma = true;
if (tokenizer.charCode() === LEFTCURLYBRACKET) {
range = readMultiplierRange(tokenizer);
} else if (tokenizer.charCode() === QUESTIONMARK$1) {
// https://www.w3.org/TR/css-values-4/#component-multipliers
// > the # and ? multipliers may be stacked as #?
// In this case just treat "#?" as a single multiplier
// { min: 0, max: 0, comma: true }
tokenizer.pos++;
range = {
min: 0,
max: 0
};
} else {
range = {
min: 1,
max: 0
};
}
break;
case LEFTCURLYBRACKET:
range = readMultiplierRange(tokenizer);
break;
default:
return null;
}
return {
type: 'Multiplier',
comma,
min: range.min,
max: range.max,
term: null
};
}
function maybeMultiplied(tokenizer, node) {
const multiplier = readMultiplier(tokenizer);
if (multiplier !== null) {
multiplier.term = node;
// https://www.w3.org/TR/css-values-4/#component-multipliers
// > The + and # multipliers may be stacked as +#;
// Represent "+#" as nested multipliers:
// { ...<multiplier #>,
// term: {
// ...<multipler +>,
// term: node
// }
// }
if (tokenizer.charCode() === NUMBERSIGN$3 &&
tokenizer.charCodeAt(tokenizer.pos - 1) === PLUSSIGN$6) {
return maybeMultiplied(tokenizer, multiplier);
}
return multiplier;
}
return node;
}
function maybeToken(tokenizer) {
const ch = tokenizer.peek();
if (ch === '') {
return null;
}
return {
type: 'Token',
value: ch
};
}
function readProperty$1(tokenizer) {
let name;
tokenizer.eat(LESSTHANSIGN);
tokenizer.eat(APOSTROPHE$2);
name = scanWord(tokenizer);
tokenizer.eat(APOSTROPHE$2);
tokenizer.eat(GREATERTHANSIGN$2);
return maybeMultiplied(tokenizer, {
type: 'Property',
name
});
}
// https://drafts.csswg.org/css-values-3/#numeric-ranges
// 4.1. Range Restrictions and Range Definition Notation
//
// Range restrictions can be annotated in the numeric type notation using CSS bracketed
// range notation—[min,max]—within the angle brackets, after the identifying keyword,
// indicating a closed range between (and including) min and max.
// For example, <integer [0, 10]> indicates an integer between 0 and 10, inclusive.
function readTypeRange(tokenizer) {
// use null for Infinity to make AST format JSON serializable/deserializable
let min = null; // -Infinity
let max = null; // Infinity
let sign = 1;
tokenizer.eat(LEFTSQUAREBRACKET);
if (tokenizer.charCode() === HYPERMINUS) {
tokenizer.peek();
sign = -1;
}
if (sign == -1 && tokenizer.charCode() === INFINITY) {
tokenizer.peek();
} else {
min = sign * Number(scanNumber(tokenizer));
if (NAME_CHAR[tokenizer.charCode()] !== 0) {
min += scanWord(tokenizer);
}
}
scanSpaces(tokenizer);
tokenizer.eat(COMMA);
scanSpaces(tokenizer);
if (tokenizer.charCode() === INFINITY) {
tokenizer.peek();
} else {
sign = 1;
if (tokenizer.charCode() === HYPERMINUS) {
tokenizer.peek();
sign = -1;
}
max = sign * Number(scanNumber(tokenizer));
if (NAME_CHAR[tokenizer.charCode()] !== 0) {
max += scanWord(tokenizer);
}
}
tokenizer.eat(RIGHTSQUAREBRACKET);
return {
type: 'Range',
min,
max
};
}
function readType(tokenizer) {
let name;
let opts = null;
tokenizer.eat(LESSTHANSIGN);
name = scanWord(tokenizer);
if (tokenizer.charCode() === LEFTPARENTHESIS$2 &&
tokenizer.nextCharCode() === RIGHTPARENTHESIS$2) {
tokenizer.pos += 2;
name += '()';
}
if (tokenizer.charCodeAt(tokenizer.findWsEnd(tokenizer.pos)) === LEFTSQUAREBRACKET) {
scanSpaces(tokenizer);
opts = readTypeRange(tokenizer);
}
tokenizer.eat(GREATERTHANSIGN$2);
return maybeMultiplied(tokenizer, {
type: 'Type',
name,
opts
});
}
function readKeywordOrFunction(tokenizer) {
const name = scanWord(tokenizer);
if (tokenizer.charCode() === LEFTPARENTHESIS$2) {
tokenizer.pos++;
return {
type: 'Function',
name
};
}
return maybeMultiplied(tokenizer, {
type: 'Keyword',
name
});
}
function regroupTerms(terms, combinators) {
function createGroup(terms, combinator) {
return {
type: 'Group',
terms,
combinator,
disallowEmpty: false,
explicit: false
};
}
let combinator;
combinators = Object.keys(combinators)
.sort((a, b) => COMBINATOR_PRECEDENCE[a] - COMBINATOR_PRECEDENCE[b]);
while (combinators.length > 0) {
combinator = combinators.shift();
let i = 0;
let subgroupStart = 0;
for (; i < terms.length; i++) {
const term = terms[i];
if (term.type === 'Combinator') {
if (term.value === combinator) {
if (subgroupStart === -1) {
subgroupStart = i - 1;
}
terms.splice(i, 1);
i--;
} else {
if (subgroupStart !== -1 && i - subgroupStart > 1) {
terms.splice(
subgroupStart,
i - subgroupStart,
createGroup(terms.slice(subgroupStart, i), combinator)
);
i = subgroupStart + 1;
}
subgroupStart = -1;
}
}
}
if (subgroupStart !== -1 && combinators.length) {
terms.splice(
subgroupStart,
i - subgroupStart,
createGroup(terms.slice(subgroupStart, i), combinator)
);
}
}
return combinator;
}
function readImplicitGroup(tokenizer) {
const terms = [];
const combinators = {};
let token;
let prevToken = null;
let prevTokenPos = tokenizer.pos;
while (token = peek(tokenizer)) {
if (token.type !== 'Spaces') {
if (token.type === 'Combinator') {
// check for combinator in group beginning and double combinator sequence
if (prevToken === null || prevToken.type === 'Combinator') {
tokenizer.pos = prevTokenPos;
tokenizer.error('Unexpected combinator');
}
combinators[token.value] = true;
} else if (prevToken !== null && prevToken.type !== 'Combinator') {
combinators[' '] = true; // a b
terms.push({
type: 'Combinator',
value: ' '
});
}
terms.push(token);
prevToken = token;
prevTokenPos = tokenizer.pos;
}
}
// check for combinator in group ending
if (prevToken !== null && prevToken.type === 'Combinator') {
tokenizer.pos -= prevTokenPos;
tokenizer.error('Unexpected combinator');
}
return {
type: 'Group',
terms,
combinator: regroupTerms(terms, combinators) || ' ',
disallowEmpty: false,
explicit: false
};
}
function readGroup(tokenizer) {
let result;
tokenizer.eat(LEFTSQUAREBRACKET);
result = readImplicitGroup(tokenizer);
tokenizer.eat(RIGHTSQUAREBRACKET);
result.explicit = true;
if (tokenizer.charCode() === EXCLAMATIONMARK$2) {
tokenizer.pos++;
result.disallowEmpty = true;
}
return result;
}
function peek(tokenizer) {
let code = tokenizer.charCode();
if (code < 128 && NAME_CHAR[code] === 1) {
return readKeywordOrFunction(tokenizer);
}
switch (code) {
case RIGHTSQUAREBRACKET:
// don't eat, stop scan a group
break;
case LEFTSQUAREBRACKET:
return maybeMultiplied(tokenizer, readGroup(tokenizer));
case LESSTHANSIGN:
return tokenizer.nextCharCode() === APOSTROPHE$2
? readProperty$1(tokenizer)
: readType(tokenizer);
case VERTICALLINE$3:
return {
type: 'Combinator',
value: tokenizer.substringToPos(
tokenizer.pos + (tokenizer.nextCharCode() === VERTICALLINE$3 ? 2 : 1)
)
};
case AMPERSAND$1:
tokenizer.pos++;
tokenizer.eat(AMPERSAND$1);
return {
type: 'Combinator',
value: '&&'
};
case COMMA:
tokenizer.pos++;
return {
type: 'Comma'
};
case APOSTROPHE$2:
return maybeMultiplied(tokenizer, {
type: 'String',
value: scanString(tokenizer)
});
case SPACE$2:
case TAB:
case N$1:
case R:
case F:
return {
type: 'Spaces',
value: scanSpaces(tokenizer)
};
case COMMERCIALAT:
code = tokenizer.nextCharCode();
if (code < 128 && NAME_CHAR[code] === 1) {
tokenizer.pos++;
return {
type: 'AtKeyword',
name: scanWord(tokenizer)
};
}
return maybeToken(tokenizer);
case ASTERISK$6:
case PLUSSIGN$6:
case QUESTIONMARK$1:
case NUMBERSIGN$3:
case EXCLAMATIONMARK$2:
// prohibited tokens (used as a multiplier start)
break;
case LEFTCURLYBRACKET:
// LEFTCURLYBRACKET is allowed since mdn/data uses it w/o quoting
// check next char isn't a number, because it's likely a disjoined multiplier
code = tokenizer.nextCharCode();
if (code < 48 || code > 57) {
return maybeToken(tokenizer);
}
break;
default:
return maybeToken(tokenizer);
}
}
function parse$K(source) {
const tokenizer$1 = new tokenizer.Tokenizer(source);
const result = readImplicitGroup(tokenizer$1);
if (tokenizer$1.pos !== source.length) {
tokenizer$1.error('Unexpected input');
}
// reduce redundant groups with single group term
if (result.terms.length === 1 && result.terms[0].type === 'Group') {
return result.terms[0];
}
return result;
}
parse$L.parse = parse$K;
const parse$J = parse$L;
const MATCH = { type: 'Match' };
const MISMATCH = { type: 'Mismatch' };
const DISALLOW_EMPTY = { type: 'DisallowEmpty' };
const LEFTPARENTHESIS$1 = 40; // (
const RIGHTPARENTHESIS$1 = 41; // )
function createCondition(match, thenBranch, elseBranch) {
// reduce node count
if (thenBranch === MATCH && elseBranch === MISMATCH) {
return match;
}
if (match === MATCH && thenBranch === MATCH && elseBranch === MATCH) {
return match;
}
if (match.type === 'If' && match.else === MISMATCH && thenBranch === MATCH) {
thenBranch = match.then;
match = match.match;
}
return {
type: 'If',
match,
then: thenBranch,
else: elseBranch
};
}
function isFunctionType(name) {
return (
name.length > 2 &&
name.charCodeAt(name.length - 2) === LEFTPARENTHESIS$1 &&
name.charCodeAt(name.length - 1) === RIGHTPARENTHESIS$1
);
}
function isEnumCapatible(term) {
return (
term.type === 'Keyword' ||
term.type === 'AtKeyword' ||
term.type === 'Function' ||
term.type === 'Type' && isFunctionType(term.name)
);
}
function buildGroupMatchGraph(combinator, terms, atLeastOneTermMatched) {
switch (combinator) {
case ' ': {
// Juxtaposing components means that all of them must occur, in the given order.
//
// a b c
// =
// match a
// then match b
// then match c
// then MATCH
// else MISMATCH
// else MISMATCH
// else MISMATCH
let result = MATCH;
for (let i = terms.length - 1; i >= 0; i--) {
const term = terms[i];
result = createCondition(
term,
result,
MISMATCH
);
}
return result;
}
case '|': {
// A bar (|) separates two or more alternatives: exactly one of them must occur.
//
// a | b | c
// =
// match a
// then MATCH
// else match b
// then MATCH
// else match c
// then MATCH
// else MISMATCH
let result = MISMATCH;
let map = null;
for (let i = terms.length - 1; i >= 0; i--) {
let term = terms[i];
// reduce sequence of keywords into a Enum
if (isEnumCapatible(term)) {
if (map === null && i > 0 && isEnumCapatible(terms[i - 1])) {
map = Object.create(null);
result = createCondition(
{
type: 'Enum',
map
},
MATCH,
result
);
}
if (map !== null) {
const key = (isFunctionType(term.name) ? term.name.slice(0, -1) : term.name).toLowerCase();
if (key in map === false) {
map[key] = term;
continue;
}
}
}
map = null;
// create a new conditonal node
result = createCondition(
term,
MATCH,
result
);
}
return result;
}
case '&&': {
// A double ampersand (&&) separates two or more components,
// all of which must occur, in any order.
// Use MatchOnce for groups with a large number of terms,
// since &&-groups produces at least N!-node trees
if (terms.length > 5) {
return {
type: 'MatchOnce',
terms,
all: true
};
}
// Use a combination tree for groups with small number of terms
//
// a && b && c
// =
// match a
// then [b && c]
// else match b
// then [a && c]
// else match c
// then [a && b]
// else MISMATCH
//
// a && b
// =
// match a
// then match b
// then MATCH
// else MISMATCH
// else match b
// then match a
// then MATCH
// else MISMATCH
// else MISMATCH
let result = MISMATCH;
for (let i = terms.length - 1; i >= 0; i--) {
const term = terms[i];
let thenClause;
if (terms.length > 1) {
thenClause = buildGroupMatchGraph(
combinator,
terms.filter(function(newGroupTerm) {
return newGroupTerm !== term;
}),
false
);
} else {
thenClause = MATCH;
}
result = createCondition(
term,
thenClause,
result
);
}
return result;
}
case '||': {
// A double bar (||) separates two or more options:
// one or more of them must occur, in any order.
// Use MatchOnce for groups with a large number of terms,
// since ||-groups produces at least N!-node trees
if (terms.length > 5) {
return {
type: 'MatchOnce',
terms,
all: false
};
}
// Use a combination tree for groups with small number of terms
//
// a || b || c
// =
// match a
// then [b || c]
// else match b
// then [a || c]
// else match c
// then [a || b]
// else MISMATCH
//
// a || b
// =
// match a
// then match b
// then MATCH
// else MATCH
// else match b
// then match a
// then MATCH
// else MATCH
// else MISMATCH
let result = atLeastOneTermMatched ? MATCH : MISMATCH;
for (let i = terms.length - 1; i >= 0; i--) {
const term = terms[i];
let thenClause;
if (terms.length > 1) {
thenClause = buildGroupMatchGraph(
combinator,
terms.filter(function(newGroupTerm) {
return newGroupTerm !== term;
}),
true
);
} else {
thenClause = MATCH;
}
result = createCondition(
term,
thenClause,
result
);
}
return result;
}
}
}
function buildMultiplierMatchGraph(node) {
let result = MATCH;
let matchTerm = buildMatchGraphInternal(node.term);
if (node.max === 0) {
// disable repeating of empty match to prevent infinite loop
matchTerm = createCondition(
matchTerm,
DISALLOW_EMPTY,
MISMATCH
);
// an occurrence count is not limited, make a cycle;
// to collect more terms on each following matching mismatch
result = createCondition(
matchTerm,
null, // will be a loop
MISMATCH
);
result.then = createCondition(
MATCH,
MATCH,
result // make a loop
);
if (node.comma) {
result.then.else = createCondition(
{ type: 'Comma', syntax: node },
result,
MISMATCH
);
}
} else {
// create a match node chain for [min .. max] interval with optional matches
for (let i = node.min || 1; i <= node.max; i++) {
if (node.comma && result !== MATCH) {
result = createCondition(
{ type: 'Comma', syntax: node },
result,
MISMATCH
);
}
result = createCondition(
matchTerm,
createCondition(
MATCH,
MATCH,
result
),
MISMATCH
);
}
}
if (node.min === 0) {
// allow zero match
result = createCondition(
MATCH,
MATCH,
result
);
} else {
// create a match node chain to collect [0 ... min - 1] required matches
for (let i = 0; i < node.min - 1; i++) {
if (node.comma && result !== MATCH) {
result = createCondition(
{ type: 'Comma', syntax: node },
result,
MISMATCH
);
}
result = createCondition(
matchTerm,
result,
MISMATCH
);
}
}
return result;
}
function buildMatchGraphInternal(node) {
if (typeof node === 'function') {
return {
type: 'Generic',
fn: node
};
}
switch (node.type) {
case 'Group': {
let result = buildGroupMatchGraph(
node.combinator,
node.terms.map(buildMatchGraphInternal),
false
);
if (node.disallowEmpty) {
result = createCondition(
result,
DISALLOW_EMPTY,
MISMATCH
);
}
return result;
}
case 'Multiplier':
return buildMultiplierMatchGraph(node);
case 'Type':
case 'Property':
return {
type: node.type,
name: node.name,
syntax: node
};
case 'Keyword':
return {
type: node.type,
name: node.name.toLowerCase(),
syntax: node
};
case 'AtKeyword':
return {
type: node.type,
name: '@' + node.name.toLowerCase(),
syntax: node
};
case 'Function':
return {
type: node.type,
name: node.name.toLowerCase() + '(',
syntax: node
};
case 'String':
// convert a one char length String to a Token
if (node.value.length === 3) {
return {
type: 'Token',
value: node.value.charAt(1),
syntax: node
};
}
// otherwise use it as is
return {
type: node.type,
value: node.value.substr(1, node.value.length - 2).replace(/\\'/g, '\''),
syntax: node
};
case 'Token':
return {
type: node.type,
value: node.value,
syntax: node
};
case 'Comma':
return {
type: node.type,
syntax: node
};
default:
throw new Error('Unknown node type:', node.type);
}
}
function buildMatchGraph(syntaxTree, ref) {
if (typeof syntaxTree === 'string') {
syntaxTree = parse$J.parse(syntaxTree);
}
return {
type: 'MatchGraph',
match: buildMatchGraphInternal(syntaxTree),
syntax: ref || null,
source: syntaxTree
};
}
matchGraph$2.DISALLOW_EMPTY = DISALLOW_EMPTY;
matchGraph$2.MATCH = MATCH;
matchGraph$2.MISMATCH = MISMATCH;
matchGraph$2.buildMatchGraph = buildMatchGraph;
var match$1 = {};
const matchGraph$1 = matchGraph$2;
const types$I = types$S;
const { hasOwnProperty: hasOwnProperty$7 } = Object.prototype;
const STUB = 0;
const TOKEN = 1;
const OPEN_SYNTAX = 2;
const CLOSE_SYNTAX = 3;
const EXIT_REASON_MATCH = 'Match';
const EXIT_REASON_MISMATCH = 'Mismatch';
const EXIT_REASON_ITERATION_LIMIT = 'Maximum iteration number exceeded (please fill an issue on https://github.com/csstree/csstree/issues)';
const ITERATION_LIMIT = 15000;
function reverseList(list) {
let prev = null;
let next = null;
let item = list;
while (item !== null) {
next = item.prev;
item.prev = prev;
prev = item;
item = next;
}
return prev;
}
function areStringsEqualCaseInsensitive(testStr, referenceStr) {
if (testStr.length !== referenceStr.length) {
return false;
}
for (let i = 0; i < testStr.length; i++) {
const referenceCode = referenceStr.charCodeAt(i);
let testCode = testStr.charCodeAt(i);
// testCode.toLowerCase() for U+0041 LATIN CAPITAL LETTER A (A) .. U+005A LATIN CAPITAL LETTER Z (Z).
if (testCode >= 0x0041 && testCode <= 0x005A) {
testCode = testCode | 32;
}
if (testCode !== referenceCode) {
return false;
}
}
return true;
}
function isContextEdgeDelim(token) {
if (token.type !== types$I.Delim) {
return false;
}
// Fix matching for unicode-range: U+30??, U+FF00-FF9F
// Probably we need to check out previous match instead
return token.value !== '?';
}
function isCommaContextStart(token) {
if (token === null) {
return true;
}
return (
token.type === types$I.Comma ||
token.type === types$I.Function ||
token.type === types$I.LeftParenthesis ||
token.type === types$I.LeftSquareBracket ||
token.type === types$I.LeftCurlyBracket ||
isContextEdgeDelim(token)
);
}
function isCommaContextEnd(token) {
if (token === null) {
return true;
}
return (
token.type === types$I.RightParenthesis ||
token.type === types$I.RightSquareBracket ||
token.type === types$I.RightCurlyBracket ||
(token.type === types$I.Delim && token.value === '/')
);
}
function internalMatch(tokens, state, syntaxes) {
function moveToNextToken() {
do {
tokenIndex++;
token = tokenIndex < tokens.length ? tokens[tokenIndex] : null;
} while (token !== null && (token.type === types$I.WhiteSpace || token.type === types$I.Comment));
}
function getNextToken(offset) {
const nextIndex = tokenIndex + offset;
return nextIndex < tokens.length ? tokens[nextIndex] : null;
}
function stateSnapshotFromSyntax(nextState, prev) {
return {
nextState,
matchStack,
syntaxStack,
thenStack,
tokenIndex,
prev
};
}
function pushThenStack(nextState) {
thenStack = {
nextState,
matchStack,
syntaxStack,
prev: thenStack
};
}
function pushElseStack(nextState) {
elseStack = stateSnapshotFromSyntax(nextState, elseStack);
}
function addTokenToMatch() {
matchStack = {
type: TOKEN,
syntax: state.syntax,
token,
prev: matchStack
};
moveToNextToken();
syntaxStash = null;
if (tokenIndex > longestMatch) {
longestMatch = tokenIndex;
}
}
function openSyntax() {
syntaxStack = {
syntax: state.syntax,
opts: state.syntax.opts || (syntaxStack !== null && syntaxStack.opts) || null,
prev: syntaxStack
};
matchStack = {
type: OPEN_SYNTAX,
syntax: state.syntax,
token: matchStack.token,
prev: matchStack
};
}
function closeSyntax() {
if (matchStack.type === OPEN_SYNTAX) {
matchStack = matchStack.prev;
} else {
matchStack = {
type: CLOSE_SYNTAX,
syntax: syntaxStack.syntax,
token: matchStack.token,
prev: matchStack
};
}
syntaxStack = syntaxStack.prev;
}
let syntaxStack = null;
let thenStack = null;
let elseStack = null;
// null stashing allowed, nothing stashed
// false stashing disabled, nothing stashed
// anithing else fail stashable syntaxes, some syntax stashed
let syntaxStash = null;
let iterationCount = 0; // count iterations and prevent infinite loop
let exitReason = null;
let token = null;
let tokenIndex = -1;
let longestMatch = 0;
let matchStack = {
type: STUB,
syntax: null,
token: null,
prev: null
};
moveToNextToken();
while (exitReason === null && ++iterationCount < ITERATION_LIMIT) {
// function mapList(list, fn) {
// const result = [];
// while (list) {
// result.unshift(fn(list));
// list = list.prev;
// }
// return result;
// }
// console.log('--\n',
// '#' + iterationCount,
// require('util').inspect({
// match: mapList(matchStack, x => x.type === TOKEN ? x.token && x.token.value : x.syntax ? ({ [OPEN_SYNTAX]: '<', [CLOSE_SYNTAX]: '</' }[x.type] || x.type) + '!' + x.syntax.name : null),
// token: token && token.value,
// tokenIndex,
// syntax: syntax.type + (syntax.id ? ' #' + syntax.id : '')
// }, { depth: null })
// );
switch (state.type) {
case 'Match':
if (thenStack === null) {
// turn to MISMATCH when some tokens left unmatched
if (token !== null) {
// doesn't mismatch if just one token left and it's an IE hack
if (tokenIndex !== tokens.length - 1 || (token.value !== '\\0' && token.value !== '\\9')) {
state = matchGraph$1.MISMATCH;
break;
}
}
// break the main loop, return a result - MATCH
exitReason = EXIT_REASON_MATCH;
break;
}
// go to next syntax (`then` branch)
state = thenStack.nextState;
// check match is not empty
if (state === matchGraph$1.DISALLOW_EMPTY) {
if (thenStack.matchStack === matchStack) {
state = matchGraph$1.MISMATCH;
break;
} else {
state = matchGraph$1.MATCH;
}
}
// close syntax if needed
while (thenStack.syntaxStack !== syntaxStack) {
closeSyntax();
}
// pop stack
thenStack = thenStack.prev;
break;
case 'Mismatch':
// when some syntax is stashed
if (syntaxStash !== null && syntaxStash !== false) {
// there is no else branches or a branch reduce match stack
if (elseStack === null || tokenIndex > elseStack.tokenIndex) {
// restore state from the stash
elseStack = syntaxStash;
syntaxStash = false; // disable stashing
}
} else if (elseStack === null) {
// no else branches -> break the main loop
// return a result - MISMATCH
exitReason = EXIT_REASON_MISMATCH;
break;
}
// go to next syntax (`else` branch)
state = elseStack.nextState;
// restore all the rest stack states
thenStack = elseStack.thenStack;
syntaxStack = elseStack.syntaxStack;
matchStack = elseStack.matchStack;
tokenIndex = elseStack.tokenIndex;
token = tokenIndex < tokens.length ? tokens[tokenIndex] : null;
// pop stack
elseStack = elseStack.prev;
break;
case 'MatchGraph':
state = state.match;
break;
case 'If':
// IMPORTANT: else stack push must go first,
// since it stores the state of thenStack before changes
if (state.else !== matchGraph$1.MISMATCH) {
pushElseStack(state.else);
}
if (state.then !== matchGraph$1.MATCH) {
pushThenStack(state.then);
}
state = state.match;
break;
case 'MatchOnce':
state = {
type: 'MatchOnceBuffer',
syntax: state,
index: 0,
mask: 0
};
break;
case 'MatchOnceBuffer': {
const terms = state.syntax.terms;
if (state.index === terms.length) {
// no matches at all or it's required all terms to be matched
if (state.mask === 0 || state.syntax.all) {
state = matchGraph$1.MISMATCH;
break;
}
// a partial match is ok
state = matchGraph$1.MATCH;
break;
}
// all terms are matched
if (state.mask === (1 << terms.length) - 1) {
state = matchGraph$1.MATCH;
break;
}
for (; state.index < terms.length; state.index++) {
const matchFlag = 1 << state.index;
if ((state.mask & matchFlag) === 0) {
// IMPORTANT: else stack push must go first,
// since it stores the state of thenStack before changes
pushElseStack(state);
pushThenStack({
type: 'AddMatchOnce',
syntax: state.syntax,
mask: state.mask | matchFlag
});
// match
state = terms[state.index++];
break;
}
}
break;
}
case 'AddMatchOnce':
state = {
type: 'MatchOnceBuffer',
syntax: state.syntax,
index: 0,
mask: state.mask
};
break;
case 'Enum':
if (token !== null) {
let name = token.value.toLowerCase();
// drop \0 and \9 hack from keyword name
if (name.indexOf('\\') !== -1) {
name = name.replace(/\\[09].*$/, '');
}
if (hasOwnProperty$7.call(state.map, name)) {
state = state.map[name];
break;
}
}
state = matchGraph$1.MISMATCH;
break;
case 'Generic': {
const opts = syntaxStack !== null ? syntaxStack.opts : null;
const lastTokenIndex = tokenIndex + Math.floor(state.fn(token, getNextToken, opts));
if (!isNaN(lastTokenIndex) && lastTokenIndex > tokenIndex) {
while (tokenIndex < lastTokenIndex) {
addTokenToMatch();
}
state = matchGraph$1.MATCH;
} else {
state = matchGraph$1.MISMATCH;
}
break;
}
case 'Type':
case 'Property': {
const syntaxDict = state.type === 'Type' ? 'types' : 'properties';
const dictSyntax = hasOwnProperty$7.call(syntaxes, syntaxDict) ? syntaxes[syntaxDict][state.name] : null;
if (!dictSyntax || !dictSyntax.match) {
throw new Error(
'Bad syntax reference: ' +
(state.type === 'Type'
? '<' + state.name + '>'
: '<\'' + state.name + '\'>')
);
}
// stash a syntax for types with low priority
if (syntaxStash !== false && token !== null && state.type === 'Type') {
const lowPriorityMatching =
// https://drafts.csswg.org/css-values-4/#custom-idents
// When parsing positionally-ambiguous keywords in a property value, a <custom-ident> production
// can only claim the keyword if no other unfulfilled production can claim it.
(state.name === 'custom-ident' && token.type === types$I.Ident) ||
// https://drafts.csswg.org/css-values-4/#lengths
// ... if a `0` could be parsed as either a <number> or a <length> in a property (such as line-height),
// it must parse as a <number>
(state.name === 'length' && token.value === '0');
if (lowPriorityMatching) {
if (syntaxStash === null) {
syntaxStash = stateSnapshotFromSyntax(state, elseStack);
}
state = matchGraph$1.MISMATCH;
break;
}
}
openSyntax();
state = dictSyntax.match;
break;
}
case 'Keyword': {
const name = state.name;
if (token !== null) {
let keywordName = token.value;
// drop \0 and \9 hack from keyword name
if (keywordName.indexOf('\\') !== -1) {
keywordName = keywordName.replace(/\\[09].*$/, '');
}
if (areStringsEqualCaseInsensitive(keywordName, name)) {
addTokenToMatch();
state = matchGraph$1.MATCH;
break;
}
}
state = matchGraph$1.MISMATCH;
break;
}
case 'AtKeyword':
case 'Function':
if (token !== null && areStringsEqualCaseInsensitive(token.value, state.name)) {
addTokenToMatch();
state = matchGraph$1.MATCH;
break;
}
state = matchGraph$1.MISMATCH;
break;
case 'Token':
if (token !== null && token.value === state.value) {
addTokenToMatch();
state = matchGraph$1.MATCH;
break;
}
state = matchGraph$1.MISMATCH;
break;
case 'Comma':
if (token !== null && token.type === types$I.Comma) {
if (isCommaContextStart(matchStack.token)) {
state = matchGraph$1.MISMATCH;
} else {
addTokenToMatch();
state = isCommaContextEnd(token) ? matchGraph$1.MISMATCH : matchGraph$1.MATCH;
}
} else {
state = isCommaContextStart(matchStack.token) || isCommaContextEnd(token) ? matchGraph$1.MATCH : matchGraph$1.MISMATCH;
}
break;
case 'String':
let string = '';
let lastTokenIndex = tokenIndex;
for (; lastTokenIndex < tokens.length && string.length < state.value.length; lastTokenIndex++) {
string += tokens[lastTokenIndex].value;
}
if (areStringsEqualCaseInsensitive(string, state.value)) {
while (tokenIndex < lastTokenIndex) {
addTokenToMatch();
}
state = matchGraph$1.MATCH;
} else {
state = matchGraph$1.MISMATCH;
}
break;
default:
throw new Error('Unknown node type: ' + state.type);
}
}
switch (exitReason) {
case null:
console.warn('[csstree-match] BREAK after ' + ITERATION_LIMIT + ' iterations');
exitReason = EXIT_REASON_ITERATION_LIMIT;
matchStack = null;
break;
case EXIT_REASON_MATCH:
while (syntaxStack !== null) {
closeSyntax();
}
break;
default:
matchStack = null;
}
return {
tokens,
reason: exitReason,
iterations: iterationCount,
match: matchStack,
longestMatch
};
}
function matchAsList(tokens, matchGraph, syntaxes) {
const matchResult = internalMatch(tokens, matchGraph, syntaxes || {});
if (matchResult.match !== null) {
let item = reverseList(matchResult.match).prev;
matchResult.match = [];
while (item !== null) {
switch (item.type) {
case OPEN_SYNTAX:
case CLOSE_SYNTAX:
matchResult.match.push({
type: item.type,
syntax: item.syntax
});
break;
default:
matchResult.match.push({
token: item.token.value,
node: item.token.node
});
break;
}
item = item.prev;
}
}
return matchResult;
}
function matchAsTree(tokens, matchGraph, syntaxes) {
const matchResult = internalMatch(tokens, matchGraph, syntaxes || {});
if (matchResult.match === null) {
return matchResult;
}
let item = matchResult.match;
let host = matchResult.match = {
syntax: matchGraph.syntax || null,
match: []
};
const hostStack = [host];
// revert a list and start with 2nd item since 1st is a stub item
item = reverseList(item).prev;
// build a tree
while (item !== null) {
switch (item.type) {
case OPEN_SYNTAX:
host.match.push(host = {
syntax: item.syntax,
match: []
});
hostStack.push(host);
break;
case CLOSE_SYNTAX:
hostStack.pop();
host = hostStack[hostStack.length - 1];
break;
default:
host.match.push({
syntax: item.syntax || null,
token: item.token.value,
node: item.token.node
});
}
item = item.prev;
}
return matchResult;
}
match$1.matchAsList = matchAsList;
match$1.matchAsTree = matchAsTree;
var trace$1 = {};
function getTrace(node) {
function shouldPutToTrace(syntax) {
if (syntax === null) {
return false;
}
return (
syntax.type === 'Type' ||
syntax.type === 'Property' ||
syntax.type === 'Keyword'
);
}
function hasMatch(matchNode) {
if (Array.isArray(matchNode.match)) {
// use for-loop for better perfomance
for (let i = 0; i < matchNode.match.length; i++) {
if (hasMatch(matchNode.match[i])) {
if (shouldPutToTrace(matchNode.syntax)) {
result.unshift(matchNode.syntax);
}
return true;
}
}
} else if (matchNode.node === node) {
result = shouldPutToTrace(matchNode.syntax)
? [matchNode.syntax]
: [];
return true;
}
return false;
}
let result = null;
if (this.matched !== null) {
hasMatch(this.matched);
}
return result;
}
function isType(node, type) {
return testNode(this, node, match => match.type === 'Type' && match.name === type);
}
function isProperty(node, property) {
return testNode(this, node, match => match.type === 'Property' && match.name === property);
}
function isKeyword(node) {
return testNode(this, node, match => match.type === 'Keyword');
}
function testNode(match, node, fn) {
const trace = getTrace.call(match, node);
if (trace === null) {
return false;
}
return trace.some(fn);
}
trace$1.getTrace = getTrace;
trace$1.isKeyword = isKeyword;
trace$1.isProperty = isProperty;
trace$1.isType = isType;
var search$1 = {};
const List$3 = List$7;
function getFirstMatchNode(matchNode) {
if ('node' in matchNode) {
return matchNode.node;
}
return getFirstMatchNode(matchNode.match[0]);
}
function getLastMatchNode(matchNode) {
if ('node' in matchNode) {
return matchNode.node;
}
return getLastMatchNode(matchNode.match[matchNode.match.length - 1]);
}
function matchFragments(lexer, ast, match, type, name) {
function findFragments(matchNode) {
if (matchNode.syntax !== null &&
matchNode.syntax.type === type &&
matchNode.syntax.name === name) {
const start = getFirstMatchNode(matchNode);
const end = getLastMatchNode(matchNode);
lexer.syntax.walk(ast, function(node, item, list) {
if (node === start) {
const nodes = new List$3.List();
do {
nodes.appendData(item.data);
if (item.data === end) {
break;
}
item = item.next;
} while (item !== null);
fragments.push({
parent: list,
nodes
});
}
});
}
if (Array.isArray(matchNode.match)) {
matchNode.match.forEach(findFragments);
}
}
const fragments = [];
if (match.matched !== null) {
findFragments(match.matched);
}
return fragments;
}
search$1.matchFragments = matchFragments;
var structure$F = {};
const List$2 = List$7;
const { hasOwnProperty: hasOwnProperty$6 } = Object.prototype;
function isValidNumber(value) {
// Number.isInteger(value) && value >= 0
return (
typeof value === 'number' &&
isFinite(value) &&
Math.floor(value) === value &&
value >= 0
);
}
function isValidLocation(loc) {
return (
Boolean(loc) &&
isValidNumber(loc.offset) &&
isValidNumber(loc.line) &&
isValidNumber(loc.column)
);
}
function createNodeStructureChecker(type, fields) {
return function checkNode(node, warn) {
if (!node || node.constructor !== Object) {
return warn(node, 'Type of node should be an Object');
}
for (let key in node) {
let valid = true;
if (hasOwnProperty$6.call(node, key) === false) {
continue;
}
if (key === 'type') {
if (node.type !== type) {
warn(node, 'Wrong node type `' + node.type + '`, expected `' + type + '`');
}
} else if (key === 'loc') {
if (node.loc === null) {
continue;
} else if (node.loc && node.loc.constructor === Object) {
if (typeof node.loc.source !== 'string') {
key += '.source';
} else if (!isValidLocation(node.loc.start)) {
key += '.start';
} else if (!isValidLocation(node.loc.end)) {
key += '.end';
} else {
continue;
}
}
valid = false;
} else if (fields.hasOwnProperty(key)) {
valid = false;
for (let i = 0; !valid && i < fields[key].length; i++) {
const fieldType = fields[key][i];
switch (fieldType) {
case String:
valid = typeof node[key] === 'string';
break;
case Boolean:
valid = typeof node[key] === 'boolean';
break;
case null:
valid = node[key] === null;
break;
default:
if (typeof fieldType === 'string') {
valid = node[key] && node[key].type === fieldType;
} else if (Array.isArray(fieldType)) {
valid = node[key] instanceof List$2.List;
}
}
}
} else {
warn(node, 'Unknown field `' + key + '` for ' + type + ' node type');
}
if (!valid) {
warn(node, 'Bad value for `' + type + '.' + key + '`');
}
}
for (const key in fields) {
if (hasOwnProperty$6.call(fields, key) &&
hasOwnProperty$6.call(node, key) === false) {
warn(node, 'Field `' + type + '.' + key + '` is missed');
}
}
};
}
function processStructure(name, nodeType) {
const structure = nodeType.structure;
const fields = {
type: String,
loc: true
};
const docs = {
type: '"' + name + '"'
};
for (const key in structure) {
if (hasOwnProperty$6.call(structure, key) === false) {
continue;
}
const docsTypes = [];
const fieldTypes = fields[key] = Array.isArray(structure[key])
? structure[key].slice()
: [structure[key]];
for (let i = 0; i < fieldTypes.length; i++) {
const fieldType = fieldTypes[i];
if (fieldType === String || fieldType === Boolean) {
docsTypes.push(fieldType.name);
} else if (fieldType === null) {
docsTypes.push('null');
} else if (typeof fieldType === 'string') {
docsTypes.push('<' + fieldType + '>');
} else if (Array.isArray(fieldType)) {
docsTypes.push('List'); // TODO: use type enum
} else {
throw new Error('Wrong value `' + fieldType + '` in `' + name + '.' + key + '` structure definition');
}
}
docs[key] = docsTypes.join(' | ');
}
return {
docs,
check: createNodeStructureChecker(name, fields)
};
}
function getStructureFromConfig(config) {
const structure = {};
if (config.node) {
for (const name in config.node) {
if (hasOwnProperty$6.call(config.node, name)) {
const nodeType = config.node[name];
if (nodeType.structure) {
structure[name] = processStructure(name, nodeType);
} else {
throw new Error('Missed `structure` field in `' + name + '` node type definition');
}
}
}
}
return structure;
}
structure$F.getStructureFromConfig = getStructureFromConfig;
var walk$5 = {};
const noop = function() {};
function ensureFunction(value) {
return typeof value === 'function' ? value : noop;
}
function walk$4(node, options, context) {
function walk(node) {
enter.call(context, node);
switch (node.type) {
case 'Group':
node.terms.forEach(walk);
break;
case 'Multiplier':
walk(node.term);
break;
case 'Type':
case 'Property':
case 'Keyword':
case 'AtKeyword':
case 'Function':
case 'String':
case 'Token':
case 'Comma':
break;
default:
throw new Error('Unknown type: ' + node.type);
}
leave.call(context, node);
}
let enter = noop;
let leave = noop;
if (typeof options === 'function') {
enter = options;
} else if (options) {
enter = ensureFunction(options.enter);
leave = ensureFunction(options.leave);
}
if (enter === noop && leave === noop) {
throw new Error('Neither `enter` nor `leave` walker handler is set or both aren\'t a function');
}
walk(node);
}
walk$5.walk = walk$4;
const error$1 = error$2;
const names$3 = names$4;
const genericConst = genericConst$2;
const generic = generic$1;
const prepareTokens = prepareTokens_1;
const matchGraph = matchGraph$2;
const match = match$1;
const trace = trace$1;
const search = search$1;
const structure$E = structure$F;
const parse$I = parse$L;
const generate$I = generate$L;
const walk$3 = walk$5;
const cssWideKeywordsSyntax = matchGraph.buildMatchGraph(genericConst.cssWideKeywords.join(' | '));
function dumpMapSyntax(map, compact, syntaxAsAst) {
const result = {};
for (const name in map) {
if (map[name].syntax) {
result[name] = syntaxAsAst
? map[name].syntax
: generate$I.generate(map[name].syntax, { compact });
}
}
return result;
}
function dumpAtruleMapSyntax(map, compact, syntaxAsAst) {
const result = {};
for (const [name, atrule] of Object.entries(map)) {
result[name] = {
prelude: atrule.prelude && (
syntaxAsAst
? atrule.prelude.syntax
: generate$I.generate(atrule.prelude.syntax, { compact })
),
descriptors: atrule.descriptors && dumpMapSyntax(atrule.descriptors, compact, syntaxAsAst)
};
}
return result;
}
function valueHasVar(tokens) {
for (let i = 0; i < tokens.length; i++) {
if (tokens[i].value.toLowerCase() === 'var(') {
return true;
}
}
return false;
}
function buildMatchResult(matched, error, iterations) {
return {
matched,
iterations,
error,
...trace
};
}
function matchSyntax(lexer, syntax, value, useCssWideKeywords) {
const tokens = prepareTokens(value, lexer.syntax);
let result;
if (valueHasVar(tokens)) {
return buildMatchResult(null, new Error('Matching for a tree with var() is not supported'));
}
if (useCssWideKeywords) {
result = match.matchAsTree(tokens, lexer.cssWideKeywordsSyntax, lexer);
}
if (!useCssWideKeywords || !result.match) {
result = match.matchAsTree(tokens, syntax.match, lexer);
if (!result.match) {
return buildMatchResult(
null,
new error$1.SyntaxMatchError(result.reason, syntax.syntax, value, result),
result.iterations
);
}
}
return buildMatchResult(result.match, null, result.iterations);
}
let Lexer$2 = class Lexer {
constructor(config, syntax, structure$1) {
this.cssWideKeywordsSyntax = cssWideKeywordsSyntax;
this.syntax = syntax;
this.generic = false;
this.atrules = Object.create(null);
this.properties = Object.create(null);
this.types = Object.create(null);
this.structure = structure$1 || structure$E.getStructureFromConfig(config);
if (config) {
if (config.types) {
for (const name in config.types) {
this.addType_(name, config.types[name]);
}
}
if (config.generic) {
this.generic = true;
for (const name in generic) {
this.addType_(name, generic[name]);
}
}
if (config.atrules) {
for (const name in config.atrules) {
this.addAtrule_(name, config.atrules[name]);
}
}
if (config.properties) {
for (const name in config.properties) {
this.addProperty_(name, config.properties[name]);
}
}
}
}
checkStructure(ast) {
function collectWarning(node, message) {
warns.push({ node, message });
}
const structure = this.structure;
const warns = [];
this.syntax.walk(ast, function(node) {
if (structure.hasOwnProperty(node.type)) {
structure[node.type].check(node, collectWarning);
} else {
collectWarning(node, 'Unknown node type `' + node.type + '`');
}
});
return warns.length ? warns : false;
}
createDescriptor(syntax, type, name, parent = null) {
const ref = {
type,
name
};
const descriptor = {
type,
name,
parent,
serializable: typeof syntax === 'string' || (syntax && typeof syntax.type === 'string'),
syntax: null,
match: null
};
if (typeof syntax === 'function') {
descriptor.match = matchGraph.buildMatchGraph(syntax, ref);
} else {
if (typeof syntax === 'string') {
// lazy parsing on first access
Object.defineProperty(descriptor, 'syntax', {
get() {
Object.defineProperty(descriptor, 'syntax', {
value: parse$I.parse(syntax)
});
return descriptor.syntax;
}
});
} else {
descriptor.syntax = syntax;
}
// lazy graph build on first access
Object.defineProperty(descriptor, 'match', {
get() {
Object.defineProperty(descriptor, 'match', {
value: matchGraph.buildMatchGraph(descriptor.syntax, ref)
});
return descriptor.match;
}
});
}
return descriptor;
}
addAtrule_(name, syntax) {
if (!syntax) {
return;
}
this.atrules[name] = {
type: 'Atrule',
name: name,
prelude: syntax.prelude ? this.createDescriptor(syntax.prelude, 'AtrulePrelude', name) : null,
descriptors: syntax.descriptors
? Object.keys(syntax.descriptors).reduce(
(map, descName) => {
map[descName] = this.createDescriptor(syntax.descriptors[descName], 'AtruleDescriptor', descName, name);
return map;
},
Object.create(null)
)
: null
};
}
addProperty_(name, syntax) {
if (!syntax) {
return;
}
this.properties[name] = this.createDescriptor(syntax, 'Property', name);
}
addType_(name, syntax) {
if (!syntax) {
return;
}
this.types[name] = this.createDescriptor(syntax, 'Type', name);
}
checkAtruleName(atruleName) {
if (!this.getAtrule(atruleName)) {
return new error$1.SyntaxReferenceError('Unknown at-rule', '@' + atruleName);
}
}
checkAtrulePrelude(atruleName, prelude) {
const error = this.checkAtruleName(atruleName);
if (error) {
return error;
}
const atrule = this.getAtrule(atruleName);
if (!atrule.prelude && prelude) {
return new SyntaxError('At-rule `@' + atruleName + '` should not contain a prelude');
}
if (atrule.prelude && !prelude) {
if (!matchSyntax(this, atrule.prelude, '', false).matched) {
return new SyntaxError('At-rule `@' + atruleName + '` should contain a prelude');
}
}
}
checkAtruleDescriptorName(atruleName, descriptorName) {
const error$1$1 = this.checkAtruleName(atruleName);
if (error$1$1) {
return error$1$1;
}
const atrule = this.getAtrule(atruleName);
const descriptor = names$3.keyword(descriptorName);
if (!atrule.descriptors) {
return new SyntaxError('At-rule `@' + atruleName + '` has no known descriptors');
}
if (!atrule.descriptors[descriptor.name] &&
!atrule.descriptors[descriptor.basename]) {
return new error$1.SyntaxReferenceError('Unknown at-rule descriptor', descriptorName);
}
}
checkPropertyName(propertyName) {
if (!this.getProperty(propertyName)) {
return new error$1.SyntaxReferenceError('Unknown property', propertyName);
}
}
matchAtrulePrelude(atruleName, prelude) {
const error = this.checkAtrulePrelude(atruleName, prelude);
if (error) {
return buildMatchResult(null, error);
}
const atrule = this.getAtrule(atruleName);
if (!atrule.prelude) {
return buildMatchResult(null, null);
}
return matchSyntax(this, atrule.prelude, prelude || '', false);
}
matchAtruleDescriptor(atruleName, descriptorName, value) {
const error = this.checkAtruleDescriptorName(atruleName, descriptorName);
if (error) {
return buildMatchResult(null, error);
}
const atrule = this.getAtrule(atruleName);
const descriptor = names$3.keyword(descriptorName);
return matchSyntax(this, atrule.descriptors[descriptor.name] || atrule.descriptors[descriptor.basename], value, false);
}
matchDeclaration(node) {
if (node.type !== 'Declaration') {
return buildMatchResult(null, new Error('Not a Declaration node'));
}
return this.matchProperty(node.property, node.value);
}
matchProperty(propertyName, value) {
// don't match syntax for a custom property at the moment
if (names$3.property(propertyName).custom) {
return buildMatchResult(null, new Error('Lexer matching doesn\'t applicable for custom properties'));
}
const error = this.checkPropertyName(propertyName);
if (error) {
return buildMatchResult(null, error);
}
return matchSyntax(this, this.getProperty(propertyName), value, true);
}
matchType(typeName, value) {
const typeSyntax = this.getType(typeName);
if (!typeSyntax) {
return buildMatchResult(null, new error$1.SyntaxReferenceError('Unknown type', typeName));
}
return matchSyntax(this, typeSyntax, value, false);
}
match(syntax, value) {
if (typeof syntax !== 'string' && (!syntax || !syntax.type)) {
return buildMatchResult(null, new error$1.SyntaxReferenceError('Bad syntax'));
}
if (typeof syntax === 'string' || !syntax.match) {
syntax = this.createDescriptor(syntax, 'Type', 'anonymous');
}
return matchSyntax(this, syntax, value, false);
}
findValueFragments(propertyName, value, type, name) {
return search.matchFragments(this, value, this.matchProperty(propertyName, value), type, name);
}
findDeclarationValueFragments(declaration, type, name) {
return search.matchFragments(this, declaration.value, this.matchDeclaration(declaration), type, name);
}
findAllFragments(ast, type, name) {
const result = [];
this.syntax.walk(ast, {
visit: 'Declaration',
enter: (declaration) => {
result.push.apply(result, this.findDeclarationValueFragments(declaration, type, name));
}
});
return result;
}
getAtrule(atruleName, fallbackBasename = true) {
const atrule = names$3.keyword(atruleName);
const atruleEntry = atrule.vendor && fallbackBasename
? this.atrules[atrule.name] || this.atrules[atrule.basename]
: this.atrules[atrule.name];
return atruleEntry || null;
}
getAtrulePrelude(atruleName, fallbackBasename = true) {
const atrule = this.getAtrule(atruleName, fallbackBasename);
return atrule && atrule.prelude || null;
}
getAtruleDescriptor(atruleName, name) {
return this.atrules.hasOwnProperty(atruleName) && this.atrules.declarators
? this.atrules[atruleName].declarators[name] || null
: null;
}
getProperty(propertyName, fallbackBasename = true) {
const property = names$3.property(propertyName);
const propertyEntry = property.vendor && fallbackBasename
? this.properties[property.name] || this.properties[property.basename]
: this.properties[property.name];
return propertyEntry || null;
}
getType(name) {
return hasOwnProperty.call(this.types, name) ? this.types[name] : null;
}
validate() {
function validate(syntax, name, broken, descriptor) {
if (broken.has(name)) {
return broken.get(name);
}
broken.set(name, false);
if (descriptor.syntax !== null) {
walk$3.walk(descriptor.syntax, function(node) {
if (node.type !== 'Type' && node.type !== 'Property') {
return;
}
const map = node.type === 'Type' ? syntax.types : syntax.properties;
const brokenMap = node.type === 'Type' ? brokenTypes : brokenProperties;
if (!hasOwnProperty.call(map, node.name) || validate(syntax, node.name, brokenMap, map[node.name])) {
broken.set(name, true);
}
}, this);
}
}
let brokenTypes = new Map();
let brokenProperties = new Map();
for (const key in this.types) {
validate(this, key, brokenTypes, this.types[key]);
}
for (const key in this.properties) {
validate(this, key, brokenProperties, this.properties[key]);
}
brokenTypes = [...brokenTypes.keys()].filter(name => brokenTypes.get(name));
brokenProperties = [...brokenProperties.keys()].filter(name => brokenProperties.get(name));
if (brokenTypes.length || brokenProperties.length) {
return {
types: brokenTypes,
properties: brokenProperties
};
}
return null;
}
dump(syntaxAsAst, pretty) {
return {
generic: this.generic,
types: dumpMapSyntax(this.types, !pretty, syntaxAsAst),
properties: dumpMapSyntax(this.properties, !pretty, syntaxAsAst),
atrules: dumpAtruleMapSyntax(this.atrules, !pretty, syntaxAsAst)
};
}
toString() {
return JSON.stringify(this.dump());
}
};
Lexer$3.Lexer = Lexer$2;
const { hasOwnProperty: hasOwnProperty$5 } = Object.prototype;
const shape$1 = {
generic: true,
types: appendOrAssign,
atrules: {
prelude: appendOrAssignOrNull,
descriptors: appendOrAssignOrNull
},
properties: appendOrAssign,
parseContext: assign,
scope: deepAssign,
atrule: ['parse'],
pseudo: ['parse'],
node: ['name', 'structure', 'parse', 'generate', 'walkContext']
};
function isObject(value) {
return value && value.constructor === Object;
}
function copy(value) {
return isObject(value)
? { ...value }
: value;
}
function assign(dest, src) {
return Object.assign(dest, src);
}
function deepAssign(dest, src) {
for (const key in src) {
if (hasOwnProperty$5.call(src, key)) {
if (isObject(dest[key])) {
deepAssign(dest[key], src[key]);
} else {
dest[key] = copy(src[key]);
}
}
}
return dest;
}
function append(a, b) {
if (typeof b === 'string' && /^\s*\|/.test(b)) {
return typeof a === 'string'
? a + b
: b.replace(/^\s*\|\s*/, '');
}
return b || null;
}
function appendOrAssign(a, b) {
if (typeof b === 'string') {
return append(a, b);
}
const result = { ...a };
for (let key in b) {
if (hasOwnProperty$5.call(b, key)) {
result[key] = append(hasOwnProperty$5.call(a, key) ? a[key] : undefined, b[key]);
}
}
return result;
}
function appendOrAssignOrNull(a, b) {
const result = appendOrAssign(a, b);
return !isObject(result) || Object.keys(result).length
? result
: null;
}
function mix$1(dest, src, shape) {
for (const key in shape) {
if (hasOwnProperty$5.call(shape, key) === false) {
continue;
}
if (shape[key] === true) {
if (hasOwnProperty$5.call(src, key)) {
dest[key] = copy(src[key]);
}
} else if (shape[key]) {
if (typeof shape[key] === 'function') {
const fn = shape[key];
dest[key] = fn({}, dest[key]);
dest[key] = fn(dest[key] || {}, src[key]);
} else if (isObject(shape[key])) {
const result = {};
for (let name in dest[key]) {
result[name] = mix$1({}, dest[key][name], shape[key]);
}
for (let name in src[key]) {
result[name] = mix$1(result[name] || {}, src[key][name], shape[key]);
}
dest[key] = result;
} else if (Array.isArray(shape[key])) {
const res = {};
const innerShape = shape[key].reduce(function(s, k) {
s[k] = true;
return s;
}, {});
for (const [name, value] of Object.entries(dest[key] || {})) {
res[name] = {};
if (value) {
mix$1(res[name], value, innerShape);
}
}
for (const name in src[key]) {
if (hasOwnProperty$5.call(src[key], name)) {
if (!res[name]) {
res[name] = {};
}
if (src[key] && src[key][name]) {
mix$1(res[name], src[key][name], innerShape);
}
}
}
dest[key] = res;
}
}
}
return dest;
}
const mix$1$1 = (dest, src) => mix$1(dest, src, shape$1);
var mix_1 = mix$1$1;
const index$8 = tokenizer$2;
const create$2 = create$7;
const create$2$1 = create$6;
const create$3 = create$5;
const create$1$1 = create$4;
const Lexer$1 = Lexer$3;
const mix = mix_1;
function createSyntax(config) {
const parse = create$2.createParser(config);
const walk = create$1$1.createWalker(config);
const generate = create$2$1.createGenerator(config);
const { fromPlainObject, toPlainObject } = create$3.createConvertor(walk);
const syntax = {
lexer: null,
createLexer: config => new Lexer$1.Lexer(config, syntax, syntax.lexer.structure),
tokenize: index$8.tokenize,
parse,
generate,
walk,
find: walk.find,
findLast: walk.findLast,
findAll: walk.findAll,
fromPlainObject,
toPlainObject,
fork(extension) {
const base = mix({}, config); // copy of config
return createSyntax(
typeof extension === 'function'
? extension(base, Object.assign)
: mix(base, extension)
);
}
};
syntax.lexer = new Lexer$1.Lexer({
generic: true,
types: config.types,
atrules: config.atrules,
properties: config.properties,
node: config.node
}, syntax);
return syntax;
}
const createSyntax$1 = config => createSyntax(mix({}, config));
var create_1 = createSyntax$1;
const atrules = {
charset: {
prelude: "<string>"
},
"font-face": {
descriptors: {
"unicode-range": {
comment: "replaces <unicode-range>, an old production name",
syntax: "<urange>#"
}
}
}
};
const properties = {
"-moz-background-clip": {
comment: "deprecated syntax in old Firefox, https://developer.mozilla.org/en/docs/Web/CSS/background-clip",
syntax: "padding | border"
},
"-moz-border-radius-bottomleft": {
comment: "https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-left-radius",
syntax: "<'border-bottom-left-radius'>"
},
"-moz-border-radius-bottomright": {
comment: "https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-right-radius",
syntax: "<'border-bottom-right-radius'>"
},
"-moz-border-radius-topleft": {
comment: "https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-left-radius",
syntax: "<'border-top-left-radius'>"
},
"-moz-border-radius-topright": {
comment: "https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-right-radius",
syntax: "<'border-bottom-right-radius'>"
},
"-moz-control-character-visibility": {
comment: "firefox specific keywords, https://bugzilla.mozilla.org/show_bug.cgi?id=947588",
syntax: "visible | hidden"
},
"-moz-osx-font-smoothing": {
comment: "misssed old syntax https://developer.mozilla.org/en-US/docs/Web/CSS/font-smooth",
syntax: "auto | grayscale"
},
"-moz-user-select": {
comment: "https://developer.mozilla.org/en-US/docs/Web/CSS/user-select",
syntax: "none | text | all | -moz-none"
},
"-ms-flex-align": {
comment: "misssed old syntax implemented in IE, https://www.w3.org/TR/2012/WD-css3-flexbox-20120322/#flex-align",
syntax: "start | end | center | baseline | stretch"
},
"-ms-flex-item-align": {
comment: "misssed old syntax implemented in IE, https://www.w3.org/TR/2012/WD-css3-flexbox-20120322/#flex-align",
syntax: "auto | start | end | center | baseline | stretch"
},
"-ms-flex-line-pack": {
comment: "misssed old syntax implemented in IE, https://www.w3.org/TR/2012/WD-css3-flexbox-20120322/#flex-line-pack",
syntax: "start | end | center | justify | distribute | stretch"
},
"-ms-flex-negative": {
comment: "misssed old syntax implemented in IE; TODO: find references for comfirmation",
syntax: "<'flex-shrink'>"
},
"-ms-flex-pack": {
comment: "misssed old syntax implemented in IE, https://www.w3.org/TR/2012/WD-css3-flexbox-20120322/#flex-pack",
syntax: "start | end | center | justify | distribute"
},
"-ms-flex-order": {
comment: "misssed old syntax implemented in IE; https://msdn.microsoft.com/en-us/library/jj127303(v=vs.85).aspx",
syntax: "<integer>"
},
"-ms-flex-positive": {
comment: "misssed old syntax implemented in IE; TODO: find references for comfirmation",
syntax: "<'flex-grow'>"
},
"-ms-flex-preferred-size": {
comment: "misssed old syntax implemented in IE; TODO: find references for comfirmation",
syntax: "<'flex-basis'>"
},
"-ms-interpolation-mode": {
comment: "https://msdn.microsoft.com/en-us/library/ff521095(v=vs.85).aspx",
syntax: "nearest-neighbor | bicubic"
},
"-ms-grid-column-align": {
comment: "add this property first since it uses as fallback for flexbox, https://msdn.microsoft.com/en-us/library/windows/apps/hh466338.aspx",
syntax: "start | end | center | stretch"
},
"-ms-grid-row-align": {
comment: "add this property first since it uses as fallback for flexbox, https://msdn.microsoft.com/en-us/library/windows/apps/hh466348.aspx",
syntax: "start | end | center | stretch"
},
"-ms-hyphenate-limit-last": {
comment: "misssed old syntax implemented in IE; https://www.w3.org/TR/css-text-4/#hyphenate-line-limits",
syntax: "none | always | column | page | spread"
},
"-webkit-appearance": {
comment: "webkit specific keywords",
references: [
"http://css-infos.net/property/-webkit-appearance"
],
syntax: "none | button | button-bevel | caps-lock-indicator | 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 | scrollbarbutton-down | scrollbarbutton-left | scrollbarbutton-right | scrollbarbutton-up | scrollbargripper-horizontal | scrollbargripper-vertical | scrollbarthumb-horizontal | scrollbarthumb-vertical | scrollbartrack-horizontal | scrollbartrack-vertical | 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-background-clip": {
comment: "https://developer.mozilla.org/en/docs/Web/CSS/background-clip",
syntax: "[ <box> | border | padding | content | text ]#"
},
"-webkit-column-break-after": {
comment: "added, http://help.dottoro.com/lcrthhhv.php",
syntax: "always | auto | avoid"
},
"-webkit-column-break-before": {
comment: "added, http://help.dottoro.com/lcxquvkf.php",
syntax: "always | auto | avoid"
},
"-webkit-column-break-inside": {
comment: "added, http://help.dottoro.com/lclhnthl.php",
syntax: "always | auto | avoid"
},
"-webkit-font-smoothing": {
comment: "https://developer.mozilla.org/en-US/docs/Web/CSS/font-smooth",
syntax: "auto | none | antialiased | subpixel-antialiased"
},
"-webkit-mask-box-image": {
comment: "missed; https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-mask-box-image",
syntax: "[ <url> | <gradient> | none ] [ <length-percentage>{4} <-webkit-mask-box-repeat>{2} ]?"
},
"-webkit-print-color-adjust": {
comment: "missed",
references: [
"https://developer.mozilla.org/en/docs/Web/CSS/-webkit-print-color-adjust"
],
syntax: "economy | exact"
},
"-webkit-text-security": {
comment: "missed; http://help.dottoro.com/lcbkewgt.php",
syntax: "none | circle | disc | square"
},
"-webkit-user-drag": {
comment: "missed; http://help.dottoro.com/lcbixvwm.php",
syntax: "none | element | auto"
},
"-webkit-user-select": {
comment: "auto is supported by old webkit, https://developer.mozilla.org/en-US/docs/Web/CSS/user-select",
syntax: "auto | none | text | all"
},
"alignment-baseline": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/text.html#AlignmentBaselineProperty"
],
syntax: "auto | baseline | before-edge | text-before-edge | middle | central | after-edge | text-after-edge | ideographic | alphabetic | hanging | mathematical"
},
"background-clip": {
comment: "used <bg-clip> from CSS Backgrounds and Borders 4 since it adds new values",
references: [
"https://github.com/csstree/csstree/issues/190"
],
syntax: "<bg-clip>#"
},
"baseline-shift": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/text.html#BaselineShiftProperty"
],
syntax: "baseline | sub | super | <svg-length>"
},
behavior: {
comment: "added old IE property https://msdn.microsoft.com/en-us/library/ms530723(v=vs.85).aspx",
syntax: "<url>+"
},
"clip-rule": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/masking.html#ClipRuleProperty"
],
syntax: "nonzero | evenodd"
},
cue: {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<'cue-before'> <'cue-after'>?"
},
"cue-after": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<url> <decibel>? | none"
},
"cue-before": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<url> <decibel>? | none"
},
cursor: {
comment: "added legacy keywords: hand, -webkit-grab. -webkit-grabbing, -webkit-zoom-in, -webkit-zoom-out, -moz-grab, -moz-grabbing, -moz-zoom-in, -moz-zoom-out",
references: [
"https://www.sitepoint.com/css3-cursor-styles/"
],
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 | hand | -webkit-grab | -webkit-grabbing | -webkit-zoom-in | -webkit-zoom-out | -moz-grab | -moz-grabbing | -moz-zoom-in | -moz-zoom-out ] ]"
},
display: {
comment: "extended with -ms-flexbox",
syntax: "| <-non-standard-display>"
},
position: {
comment: "extended with -webkit-sticky",
syntax: "| -webkit-sticky"
},
"dominant-baseline": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/text.html#DominantBaselineProperty"
],
syntax: "auto | use-script | no-change | reset-size | ideographic | alphabetic | hanging | mathematical | central | middle | text-after-edge | text-before-edge"
},
"image-rendering": {
comment: "extended with <-non-standard-image-rendering>, added SVG keywords optimizeSpeed and optimizeQuality",
references: [
"https://developer.mozilla.org/en/docs/Web/CSS/image-rendering",
"https://www.w3.org/TR/SVG/painting.html#ImageRenderingProperty"
],
syntax: "| optimizeSpeed | optimizeQuality | <-non-standard-image-rendering>"
},
fill: {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#FillProperty"
],
syntax: "<paint>"
},
"fill-opacity": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#FillProperty"
],
syntax: "<number-zero-one>"
},
"fill-rule": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#FillProperty"
],
syntax: "nonzero | evenodd"
},
filter: {
comment: "extend with IE legacy syntaxes",
syntax: "| <-ms-filter-function-list>"
},
"glyph-orientation-horizontal": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/text.html#GlyphOrientationHorizontalProperty"
],
syntax: "<angle>"
},
"glyph-orientation-vertical": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/text.html#GlyphOrientationVerticalProperty"
],
syntax: "<angle>"
},
kerning: {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/text.html#KerningProperty"
],
syntax: "auto | <svg-length>"
},
"letter-spacing": {
comment: "fix syntax <length> -> <length-percentage>",
references: [
"https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/letter-spacing"
],
syntax: "normal | <length-percentage>"
},
marker: {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#MarkerProperties"
],
syntax: "none | <url>"
},
"marker-end": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#MarkerProperties"
],
syntax: "none | <url>"
},
"marker-mid": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#MarkerProperties"
],
syntax: "none | <url>"
},
"marker-start": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#MarkerProperties"
],
syntax: "none | <url>"
},
"max-width": {
comment: "extend by non-standard width keywords https://developer.mozilla.org/en-US/docs/Web/CSS/max-width",
syntax: "| <-non-standard-width>"
},
width: {
references: [
"https://developer.mozilla.org/en-US/docs/Web/CSS/width",
"https://github.com/csstree/stylelint-validator/issues/29"
],
syntax: "| fill | stretch | intrinsic | -moz-max-content | -webkit-max-content | -moz-fit-content | -webkit-fit-content"
},
"min-width": {
comment: "extend by non-standard width keywords https://developer.mozilla.org/en-US/docs/Web/CSS/width",
syntax: "| <-non-standard-width>"
},
overflow: {
comment: "extend by vendor keywords https://developer.mozilla.org/en-US/docs/Web/CSS/overflow",
syntax: "| <-non-standard-overflow>"
},
pause: {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<'pause-before'> <'pause-after'>?"
},
"pause-after": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<time> | none | x-weak | weak | medium | strong | x-strong"
},
"pause-before": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<time> | none | x-weak | weak | medium | strong | x-strong"
},
rest: {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<'rest-before'> <'rest-after'>?"
},
"rest-after": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<time> | none | x-weak | weak | medium | strong | x-strong"
},
"rest-before": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<time> | none | x-weak | weak | medium | strong | x-strong"
},
"shape-rendering": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#ShapeRenderingPropert"
],
syntax: "auto | optimizeSpeed | crispEdges | geometricPrecision"
},
src: {
comment: "added @font-face's src property https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/src",
syntax: "[ <url> [ format( <string># ) ]? | local( <family-name> ) ]#"
},
speak: {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "auto | none | normal"
},
"speak-as": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "normal | spell-out || digits || [ literal-punctuation | no-punctuation ]"
},
stroke: {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
],
syntax: "<paint>"
},
"stroke-dasharray": {
comment: "added SVG property; a list of comma and/or white space separated <length>s and <percentage>s",
references: [
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
],
syntax: "none | [ <svg-length>+ ]#"
},
"stroke-dashoffset": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
],
syntax: "<svg-length>"
},
"stroke-linecap": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
],
syntax: "butt | round | square"
},
"stroke-linejoin": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
],
syntax: "miter | round | bevel"
},
"stroke-miterlimit": {
comment: "added SVG property (<miterlimit> = <number-one-or-greater>) ",
references: [
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
],
syntax: "<number-one-or-greater>"
},
"stroke-opacity": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
],
syntax: "<number-zero-one>"
},
"stroke-width": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
],
syntax: "<svg-length>"
},
"text-anchor": {
comment: "added SVG property",
references: [
"https://www.w3.org/TR/SVG/text.html#TextAlignmentProperties"
],
syntax: "start | middle | end"
},
"unicode-bidi": {
comment: "added prefixed keywords https://developer.mozilla.org/en-US/docs/Web/CSS/unicode-bidi",
syntax: "| -moz-isolate | -moz-isolate-override | -moz-plaintext | -webkit-isolate | -webkit-isolate-override | -webkit-plaintext"
},
"unicode-range": {
comment: "added missed property https://developer.mozilla.org/en-US/docs/Web/CSS/%40font-face/unicode-range",
syntax: "<urange>#"
},
"voice-balance": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<number> | left | center | right | leftwards | rightwards"
},
"voice-duration": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "auto | <time>"
},
"voice-family": {
comment: "<name> -> <family-name>, https://www.w3.org/TR/css3-speech/#property-index",
syntax: "[ [ <family-name> | <generic-voice> ] , ]* [ <family-name> | <generic-voice> ] | preserve"
},
"voice-pitch": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<frequency> && absolute | [ [ x-low | low | medium | high | x-high ] || [ <frequency> | <semitones> | <percentage> ] ]"
},
"voice-range": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "<frequency> && absolute | [ [ x-low | low | medium | high | x-high ] || [ <frequency> | <semitones> | <percentage> ] ]"
},
"voice-rate": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "[ normal | x-slow | slow | medium | fast | x-fast ] || <percentage>"
},
"voice-stress": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "normal | strong | moderate | none | reduced"
},
"voice-volume": {
comment: "https://www.w3.org/TR/css3-speech/#property-index",
syntax: "silent | [ [ x-soft | soft | medium | loud | x-loud ] || <decibel> ]"
},
"writing-mode": {
comment: "extend with SVG keywords",
syntax: "| <svg-writing-mode>"
}
};
const types$H = {
"-legacy-gradient": {
comment: "added collection of legacy gradient syntaxes",
syntax: "<-webkit-gradient()> | <-legacy-linear-gradient> | <-legacy-repeating-linear-gradient> | <-legacy-radial-gradient> | <-legacy-repeating-radial-gradient>"
},
"-legacy-linear-gradient": {
comment: "like standard syntax but w/o `to` keyword https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient",
syntax: "-moz-linear-gradient( <-legacy-linear-gradient-arguments> ) | -webkit-linear-gradient( <-legacy-linear-gradient-arguments> ) | -o-linear-gradient( <-legacy-linear-gradient-arguments> )"
},
"-legacy-repeating-linear-gradient": {
comment: "like standard syntax but w/o `to` keyword https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient",
syntax: "-moz-repeating-linear-gradient( <-legacy-linear-gradient-arguments> ) | -webkit-repeating-linear-gradient( <-legacy-linear-gradient-arguments> ) | -o-repeating-linear-gradient( <-legacy-linear-gradient-arguments> )"
},
"-legacy-linear-gradient-arguments": {
comment: "like standard syntax but w/o `to` keyword https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient",
syntax: "[ <angle> | <side-or-corner> ]? , <color-stop-list>"
},
"-legacy-radial-gradient": {
comment: "deprecated syntax that implemented by some browsers https://www.w3.org/TR/2011/WD-css3-images-20110908/#radial-gradients",
syntax: "-moz-radial-gradient( <-legacy-radial-gradient-arguments> ) | -webkit-radial-gradient( <-legacy-radial-gradient-arguments> ) | -o-radial-gradient( <-legacy-radial-gradient-arguments> )"
},
"-legacy-repeating-radial-gradient": {
comment: "deprecated syntax that implemented by some browsers https://www.w3.org/TR/2011/WD-css3-images-20110908/#radial-gradients",
syntax: "-moz-repeating-radial-gradient( <-legacy-radial-gradient-arguments> ) | -webkit-repeating-radial-gradient( <-legacy-radial-gradient-arguments> ) | -o-repeating-radial-gradient( <-legacy-radial-gradient-arguments> )"
},
"-legacy-radial-gradient-arguments": {
comment: "deprecated syntax that implemented by some browsers https://www.w3.org/TR/2011/WD-css3-images-20110908/#radial-gradients",
syntax: "[ <position> , ]? [ [ [ <-legacy-radial-gradient-shape> || <-legacy-radial-gradient-size> ] | [ <length> | <percentage> ]{2} ] , ]? <color-stop-list>"
},
"-legacy-radial-gradient-size": {
comment: "before a standard it contains 2 extra keywords (`contain` and `cover`) https://www.w3.org/TR/2011/WD-css3-images-20110908/#ltsize",
syntax: "closest-side | closest-corner | farthest-side | farthest-corner | contain | cover"
},
"-legacy-radial-gradient-shape": {
comment: "define to double sure it doesn't extends in future https://www.w3.org/TR/2011/WD-css3-images-20110908/#ltshape",
syntax: "circle | ellipse"
},
"-non-standard-font": {
comment: "non standard fonts",
references: [
"https://webkit.org/blog/3709/using-the-system-font-in-web-content/"
],
syntax: "-apple-system-body | -apple-system-headline | -apple-system-subheadline | -apple-system-caption1 | -apple-system-caption2 | -apple-system-footnote | -apple-system-short-body | -apple-system-short-headline | -apple-system-short-subheadline | -apple-system-short-caption1 | -apple-system-short-footnote | -apple-system-tall-body"
},
"-non-standard-color": {
comment: "non standard colors",
references: [
"http://cssdot.ru/%D0%A1%D0%BF%D1%80%D0%B0%D0%B2%D0%BE%D1%87%D0%BD%D0%B8%D0%BA_CSS/color-i305.html",
"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Mozilla_Color_Preference_Extensions"
],
syntax: "-moz-ButtonDefault | -moz-ButtonHoverFace | -moz-ButtonHoverText | -moz-CellHighlight | -moz-CellHighlightText | -moz-Combobox | -moz-ComboboxText | -moz-Dialog | -moz-DialogText | -moz-dragtargetzone | -moz-EvenTreeRow | -moz-Field | -moz-FieldText | -moz-html-CellHighlight | -moz-html-CellHighlightText | -moz-mac-accentdarkestshadow | -moz-mac-accentdarkshadow | -moz-mac-accentface | -moz-mac-accentlightesthighlight | -moz-mac-accentlightshadow | -moz-mac-accentregularhighlight | -moz-mac-accentregularshadow | -moz-mac-chrome-active | -moz-mac-chrome-inactive | -moz-mac-focusring | -moz-mac-menuselect | -moz-mac-menushadow | -moz-mac-menutextselect | -moz-MenuHover | -moz-MenuHoverText | -moz-MenuBarText | -moz-MenuBarHoverText | -moz-nativehyperlinktext | -moz-OddTreeRow | -moz-win-communicationstext | -moz-win-mediatext | -moz-activehyperlinktext | -moz-default-background-color | -moz-default-color | -moz-hyperlinktext | -moz-visitedhyperlinktext | -webkit-activelink | -webkit-focus-ring-color | -webkit-link | -webkit-text"
},
"-non-standard-image-rendering": {
comment: "non-standard keywords http://phrogz.net/tmp/canvas_image_zoom.html",
syntax: "optimize-contrast | -moz-crisp-edges | -o-crisp-edges | -webkit-optimize-contrast"
},
"-non-standard-overflow": {
comment: "non-standard keywords https://developer.mozilla.org/en-US/docs/Web/CSS/overflow",
syntax: "-moz-scrollbars-none | -moz-scrollbars-horizontal | -moz-scrollbars-vertical | -moz-hidden-unscrollable"
},
"-non-standard-width": {
comment: "non-standard keywords https://developer.mozilla.org/en-US/docs/Web/CSS/width",
syntax: "fill-available | min-intrinsic | intrinsic | -moz-available | -moz-fit-content | -moz-min-content | -moz-max-content | -webkit-min-content | -webkit-max-content"
},
"-webkit-gradient()": {
comment: "first Apple proposal gradient syntax https://webkit.org/blog/175/introducing-css-gradients/ - TODO: simplify when after match algorithm improvement ( [, point, radius | , point] -> [, radius]? , point )",
syntax: "-webkit-gradient( <-webkit-gradient-type>, <-webkit-gradient-point> [, <-webkit-gradient-point> | , <-webkit-gradient-radius>, <-webkit-gradient-point> ] [, <-webkit-gradient-radius>]? [, <-webkit-gradient-color-stop>]* )"
},
"-webkit-gradient-color-stop": {
comment: "first Apple proposal gradient syntax https://webkit.org/blog/175/introducing-css-gradients/",
syntax: "from( <color> ) | color-stop( [ <number-zero-one> | <percentage> ] , <color> ) | to( <color> )"
},
"-webkit-gradient-point": {
comment: "first Apple proposal gradient syntax https://webkit.org/blog/175/introducing-css-gradients/",
syntax: "[ left | center | right | <length-percentage> ] [ top | center | bottom | <length-percentage> ]"
},
"-webkit-gradient-radius": {
comment: "first Apple proposal gradient syntax https://webkit.org/blog/175/introducing-css-gradients/",
syntax: "<length> | <percentage>"
},
"-webkit-gradient-type": {
comment: "first Apple proposal gradient syntax https://webkit.org/blog/175/introducing-css-gradients/",
syntax: "linear | radial"
},
"-webkit-mask-box-repeat": {
comment: "missed; https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-mask-box-image",
syntax: "repeat | stretch | round"
},
"-webkit-mask-clip-style": {
comment: "missed; there is no enough information about `-webkit-mask-clip` property, but looks like all those keywords are working",
syntax: "border | border-box | padding | padding-box | content | content-box | text"
},
"-ms-filter-function-list": {
comment: "https://developer.mozilla.org/en-US/docs/Web/CSS/-ms-filter",
syntax: "<-ms-filter-function>+"
},
"-ms-filter-function": {
comment: "https://developer.mozilla.org/en-US/docs/Web/CSS/-ms-filter",
syntax: "<-ms-filter-function-progid> | <-ms-filter-function-legacy>"
},
"-ms-filter-function-progid": {
comment: "https://developer.mozilla.org/en-US/docs/Web/CSS/-ms-filter",
syntax: "'progid:' [ <ident-token> '.' ]* [ <ident-token> | <function-token> <any-value>? ) ]"
},
"-ms-filter-function-legacy": {
comment: "https://developer.mozilla.org/en-US/docs/Web/CSS/-ms-filter",
syntax: "<ident-token> | <function-token> <any-value>? )"
},
"-ms-filter": {
syntax: "<string>"
},
age: {
comment: "https://www.w3.org/TR/css3-speech/#voice-family",
syntax: "child | young | old"
},
"attr-name": {
syntax: "<wq-name>"
},
"attr-fallback": {
syntax: "<any-value>"
},
"bg-clip": {
comment: "missed, https://drafts.csswg.org/css-backgrounds-4/#typedef-bg-clip",
syntax: "<box> | border | text"
},
"border-radius": {
comment: "missed, https://drafts.csswg.org/css-backgrounds-3/#the-border-radius",
syntax: "<length-percentage>{1,2}"
},
bottom: {
comment: "missed; not sure we should add it, but no others except `shape` is using it so it's ok for now; https://drafts.fxtf.org/css-masking-1/#funcdef-clip-rect",
syntax: "<length> | auto"
},
"content-list": {
comment: "added attr(), see https://github.com/csstree/csstree/issues/201",
syntax: "[ <string> | contents | <image> | <counter> | <quote> | <target> | <leader()> | <attr()> ]+"
},
"element()": {
comment: "https://drafts.csswg.org/css-gcpm/#element-syntax & https://drafts.csswg.org/css-images-4/#element-notation",
syntax: "element( <custom-ident> , [ first | start | last | first-except ]? ) | element( <id-selector> )"
},
"generic-voice": {
comment: "https://www.w3.org/TR/css3-speech/#voice-family",
syntax: "[ <age>? <gender> <integer>? ]"
},
gender: {
comment: "https://www.w3.org/TR/css3-speech/#voice-family",
syntax: "male | female | neutral"
},
"generic-family": {
comment: "added -apple-system",
references: [
"https://webkit.org/blog/3709/using-the-system-font-in-web-content/"
],
syntax: "| -apple-system"
},
gradient: {
comment: "added legacy syntaxes support",
syntax: "| <-legacy-gradient>"
},
"lab()": {
comment: "missed; https://www.w3.org/TR/css-color-4/#specifying-lab-lch",
syntax: "lab( [<percentage> | <number> | none] [ <percentage> | <number> | none] [ <percentage> | <number> | none] [ / [<alpha-value> | none] ]? )"
},
"lch()": {
comment: "missed; https://www.w3.org/TR/css-color-4/#specifying-lab-lch",
syntax: "lch( [<percentage> | <number> | none] [ <percentage> | <number> | none] [ <hue> | none] [ / [<alpha-value> | none] ]? )"
},
left: {
comment: "missed; not sure we should add it, but no others except `shape` is using it so it's ok for now; https://drafts.fxtf.org/css-masking-1/#funcdef-clip-rect",
syntax: "<length> | auto"
},
"mask-image": {
comment: "missed; https://drafts.fxtf.org/css-masking-1/#the-mask-image",
syntax: "<mask-reference>#"
},
"named-color": {
comment: "added non standard color names",
syntax: "| <-non-standard-color>"
},
paint: {
comment: "used by SVG https://www.w3.org/TR/SVG/painting.html#SpecifyingPaint",
syntax: "none | <color> | <url> [ none | <color> ]? | context-fill | context-stroke"
},
ratio: {
comment: "missed, https://drafts.csswg.org/css-values-4/#ratio-value",
syntax: "<number [0,∞]> [ / <number [0,∞]> ]?"
},
"reversed-counter-name": {
comment: "missed; https://drafts.csswg.org/css-lists/#typedef-reversed-counter-name",
syntax: "reversed( <counter-name> )"
},
right: {
comment: "missed; not sure we should add it, but no others except `shape` is using it so it's ok for now; https://drafts.fxtf.org/css-masking-1/#funcdef-clip-rect",
syntax: "<length> | auto"
},
shape: {
comment: "missed spaces in function body and add backwards compatible syntax",
syntax: "rect( <top>, <right>, <bottom>, <left> ) | rect( <top> <right> <bottom> <left> )"
},
"svg-length": {
comment: "All coordinates and lengths in SVG can be specified with or without a unit identifier",
references: [
"https://www.w3.org/TR/SVG11/coords.html#Units"
],
syntax: "<percentage> | <length> | <number>"
},
"svg-writing-mode": {
comment: "SVG specific keywords (deprecated for CSS)",
references: [
"https://developer.mozilla.org/en/docs/Web/CSS/writing-mode",
"https://www.w3.org/TR/SVG/text.html#WritingModeProperty"
],
syntax: "lr-tb | rl-tb | tb-rl | lr | rl | tb"
},
top: {
comment: "missed; not sure we should add it, but no others except `shape` is using it so it's ok for now; https://drafts.fxtf.org/css-masking-1/#funcdef-clip-rect",
syntax: "<length> | auto"
},
"track-group": {
comment: "used by old grid-columns and grid-rows syntax v0",
syntax: "'(' [ <string>* <track-minmax> <string>* ]+ ')' [ '[' <positive-integer> ']' ]? | <track-minmax>"
},
"track-list-v0": {
comment: "used by old grid-columns and grid-rows syntax v0",
syntax: "[ <string>* <track-group> <string>* ]+ | none"
},
"track-minmax": {
comment: "used by old grid-columns and grid-rows syntax v0",
syntax: "minmax( <track-breadth> , <track-breadth> ) | auto | <track-breadth> | fit-content"
},
x: {
comment: "missed; not sure we should add it, but no others except `cursor` is using it so it's ok for now; https://drafts.csswg.org/css-ui-3/#cursor",
syntax: "<number>"
},
y: {
comment: "missed; not sure we should add it, but no others except `cursor` is using so it's ok for now; https://drafts.csswg.org/css-ui-3/#cursor",
syntax: "<number>"
},
declaration: {
comment: "missed, restored by https://drafts.csswg.org/css-syntax",
syntax: "<ident-token> : <declaration-value>? [ '!' important ]?"
},
"declaration-list": {
comment: "missed, restored by https://drafts.csswg.org/css-syntax",
syntax: "[ <declaration>? ';' ]* <declaration>?"
},
url: {
comment: "https://drafts.csswg.org/css-values-4/#urls",
syntax: "url( <string> <url-modifier>* ) | <url-token>"
},
"url-modifier": {
comment: "https://drafts.csswg.org/css-values-4/#typedef-url-modifier",
syntax: "<ident> | <function-token> <any-value> )"
},
"number-zero-one": {
syntax: "<number [0,1]>"
},
"number-one-or-greater": {
syntax: "<number [1,∞]>"
},
"positive-integer": {
syntax: "<integer [0,∞]>"
},
"-non-standard-display": {
syntax: "-ms-inline-flexbox | -ms-grid | -ms-inline-grid | -webkit-flex | -webkit-inline-flex | -webkit-box | -webkit-inline-box | -moz-inline-stack | -moz-box | -moz-inline-box"
}
};
const require$$0$1 = {
atrules: atrules,
properties: properties,
types: types$H
};
const patch = require$$0$1;
const patch$1 = patch;
var dataPatch$1 = patch$1;
const require$$1 = {
"@charset": {
syntax: "@charset \"<charset>\";",
groups: [
"CSS Charsets"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@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}",
interfaces: [
"CSSCounterStyleRule"
],
groups: [
"CSS Counter Styles"
],
descriptors: {
"additive-symbols": {
syntax: "[ <integer> && <symbol> ]#",
media: "all",
initial: "n/a (required)",
percentages: "no",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard"
},
fallback: {
syntax: "<counter-style-name>",
media: "all",
initial: "decimal",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
negative: {
syntax: "<symbol> <symbol>?",
media: "all",
initial: "\"-\" hyphen-minus",
percentages: "no",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard"
},
pad: {
syntax: "<integer> && <symbol>",
media: "all",
initial: "0 \"\"",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
prefix: {
syntax: "<symbol>",
media: "all",
initial: "\"\"",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
range: {
syntax: "[ [ <integer> | infinite ]{2} ]# | auto",
media: "all",
initial: "auto",
percentages: "no",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard"
},
"speak-as": {
syntax: "auto | bullets | numbers | words | spell-out | <counter-style-name>",
media: "all",
initial: "auto",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
suffix: {
syntax: "<symbol>",
media: "all",
initial: "\". \"",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
symbols: {
syntax: "<symbol>+",
media: "all",
initial: "n/a (required)",
percentages: "no",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard"
},
system: {
syntax: "cyclic | numeric | alphabetic | symbolic | additive | [ fixed <integer>? ] | [ extends <counter-style-name> ]",
media: "all",
initial: "symbolic",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
}
},
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@counter-style"
},
"@document": {
syntax: "@document [ <url> | url-prefix(<string>) | domain(<string>) | media-document(<string>) | regexp(<string>) ]# {\n <group-rule-body>\n}",
interfaces: [
"CSSGroupingRule",
"CSSConditionRule"
],
groups: [
"CSS Conditional Rules"
],
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@document"
},
"@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}",
interfaces: [
"CSSFontFaceRule"
],
groups: [
"CSS Fonts"
],
descriptors: {
"ascent-override": {
syntax: "normal | <percentage>",
media: "all",
initial: "normal",
percentages: "asSpecified",
computed: "asSpecified",
order: "orderOfAppearance",
status: "experimental"
},
"descent-override": {
syntax: "normal | <percentage>",
media: "all",
initial: "normal",
percentages: "asSpecified",
computed: "asSpecified",
order: "orderOfAppearance",
status: "experimental"
},
"font-display": {
syntax: "[ auto | block | swap | fallback | optional ]",
media: "visual",
percentages: "no",
initial: "auto",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental"
},
"font-family": {
syntax: "<family-name>",
media: "all",
initial: "n/a (required)",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
"font-feature-settings": {
syntax: "normal | <feature-tag-value>#",
media: "all",
initial: "normal",
percentages: "no",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard"
},
"font-variation-settings": {
syntax: "normal | [ <string> <number> ]#",
media: "all",
initial: "normal",
percentages: "no",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard"
},
"font-stretch": {
syntax: "<font-stretch-absolute>{1,2}",
media: "all",
initial: "normal",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
"font-style": {
syntax: "normal | italic | oblique <angle>{0,2}",
media: "all",
initial: "normal",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
"font-weight": {
syntax: "<font-weight-absolute>{1,2}",
media: "all",
initial: "normal",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
"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 ]",
media: "all",
initial: "normal",
percentages: "no",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard"
},
"line-gap-override": {
syntax: "normal | <percentage>",
media: "all",
initial: "normal",
percentages: "asSpecified",
computed: "asSpecified",
order: "orderOfAppearance",
status: "experimental"
},
"size-adjust": {
syntax: "<percentage>",
media: "all",
initial: "100%",
percentages: "asSpecified",
computed: "asSpecified",
order: "orderOfAppearance",
status: "experimental"
},
src: {
syntax: "[ <url> [ format( <string># ) ]? | local( <family-name> ) ]#",
media: "all",
initial: "n/a (required)",
percentages: "no",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard"
},
"unicode-range": {
syntax: "<unicode-range>#",
media: "all",
initial: "U+0-10FFFF",
percentages: "no",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard"
}
},
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@font-face"
},
"@font-feature-values": {
syntax: "@font-feature-values <family-name># {\n <feature-value-block-list>\n}",
interfaces: [
"CSSFontFeatureValuesRule"
],
groups: [
"CSS Fonts"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@font-feature-values"
},
"@import": {
syntax: "@import [ <string> | <url> ]\n [ layer | layer(<layer-name>) ]?\n [ supports( [ <supports-condition> | <declaration> ] ) ]?\n <media-query-list>? ;",
groups: [
"CSS Conditional Rules",
"Media Queries"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@import"
},
"@keyframes": {
syntax: "@keyframes <keyframes-name> {\n <keyframe-block-list>\n}",
interfaces: [
"CSSKeyframeRule",
"CSSKeyframesRule"
],
groups: [
"CSS Animations"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@keyframes"
},
"@layer": {
syntax: "@layer [ <layer-name># | <layer-name>? {\n <stylesheet>\n} ]",
interfaces: [
"CSSLayerBlockRule",
"CSSLayerStatementRule"
],
groups: [
"CSS Cascading and Inheritance"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@layer"
},
"@media": {
syntax: "@media <media-query-list> {\n <group-rule-body>\n}",
interfaces: [
"CSSGroupingRule",
"CSSConditionRule",
"CSSMediaRule",
"CSSCustomMediaRule"
],
groups: [
"CSS Conditional Rules",
"Media Queries"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@media"
},
"@namespace": {
syntax: "@namespace <namespace-prefix>? [ <string> | <url> ];",
groups: [
"CSS Namespaces"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@namespace"
},
"@page": {
syntax: "@page <page-selector-list> {\n <page-body>\n}",
interfaces: [
"CSSPageRule"
],
groups: [
"CSS Pages"
],
descriptors: {
bleed: {
syntax: "auto | <length>",
media: [
"visual",
"paged"
],
initial: "auto",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
marks: {
syntax: "none | [ crop || cross ]",
media: [
"visual",
"paged"
],
initial: "none",
percentages: "no",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard"
},
size: {
syntax: "<length>{1,2} | auto | [ <page-size> || [ portrait | landscape ] ]",
media: [
"visual",
"paged"
],
initial: "auto",
percentages: "no",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "orderOfAppearance",
status: "standard"
}
},
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@page"
},
"@property": {
syntax: "@property <custom-property-name> {\n <declaration-list>\n}",
interfaces: [
"CSS",
"CSSPropertyRule"
],
groups: [
"CSS Houdini"
],
descriptors: {
syntax: {
syntax: "<string>",
media: "all",
percentages: "no",
initial: "n/a (required)",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental"
},
inherits: {
syntax: "true | false",
media: "all",
percentages: "no",
initial: "auto",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental"
},
"initial-value": {
syntax: "<string>",
media: "all",
initial: "n/a (required)",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental"
}
},
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@property"
},
"@scroll-timeline": {
syntax: "@scroll-timeline <timeline-name> { <declaration-list> }",
interfaces: [
"ScrollTimeline"
],
groups: [
"CSS Animations"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@scroll-timeline"
},
"@supports": {
syntax: "@supports <supports-condition> {\n <group-rule-body>\n}",
interfaces: [
"CSSGroupingRule",
"CSSConditionRule",
"CSSSupportsRule"
],
groups: [
"CSS Conditional Rules"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@supports"
},
"@viewport": {
syntax: "@viewport {\n <group-rule-body>\n}",
interfaces: [
"CSSViewportRule"
],
groups: [
"CSS Device Adaptation"
],
descriptors: {
height: {
syntax: "<viewport-length>{1,2}",
media: [
"visual",
"continuous"
],
initial: [
"min-height",
"max-height"
],
percentages: [
"min-height",
"max-height"
],
computed: [
"min-height",
"max-height"
],
order: "orderOfAppearance",
status: "standard"
},
"max-height": {
syntax: "<viewport-length>",
media: [
"visual",
"continuous"
],
initial: "auto",
percentages: "referToHeightOfInitialViewport",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard"
},
"max-width": {
syntax: "<viewport-length>",
media: [
"visual",
"continuous"
],
initial: "auto",
percentages: "referToWidthOfInitialViewport",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard"
},
"max-zoom": {
syntax: "auto | <number> | <percentage>",
media: [
"visual",
"continuous"
],
initial: "auto",
percentages: "the zoom factor itself",
computed: "autoNonNegativeOrPercentage",
order: "uniqueOrder",
status: "standard"
},
"min-height": {
syntax: "<viewport-length>",
media: [
"visual",
"continuous"
],
initial: "auto",
percentages: "referToHeightOfInitialViewport",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard"
},
"min-width": {
syntax: "<viewport-length>",
media: [
"visual",
"continuous"
],
initial: "auto",
percentages: "referToWidthOfInitialViewport",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard"
},
"min-zoom": {
syntax: "auto | <number> | <percentage>",
media: [
"visual",
"continuous"
],
initial: "auto",
percentages: "the zoom factor itself",
computed: "autoNonNegativeOrPercentage",
order: "uniqueOrder",
status: "standard"
},
orientation: {
syntax: "auto | portrait | landscape",
media: [
"visual",
"continuous"
],
initial: "auto",
percentages: "referToSizeOfBoundingBox",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
"user-zoom": {
syntax: "zoom | fixed",
media: [
"visual",
"continuous"
],
initial: "zoom",
percentages: "referToSizeOfBoundingBox",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
"viewport-fit": {
syntax: "auto | contain | cover",
media: [
"visual",
"continuous"
],
initial: "auto",
percentages: "no",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard"
},
width: {
syntax: "<viewport-length>{1,2}",
media: [
"visual",
"continuous"
],
initial: [
"min-width",
"max-width"
],
percentages: [
"min-width",
"max-width"
],
computed: [
"min-width",
"max-width"
],
order: "orderOfAppearance",
status: "standard"
},
zoom: {
syntax: "auto | <number> | <percentage>",
media: [
"visual",
"continuous"
],
initial: "auto",
percentages: "the zoom factor itself",
computed: "autoNonNegativeOrPercentage",
order: "uniqueOrder",
status: "standard"
}
},
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/@viewport"
}
};
const all = {
syntax: "initial | inherit | unset | revert | revert-layer",
media: "noPracticalMedia",
inherited: false,
animationType: "eachOfShorthandPropertiesExceptUnicodeBiDiAndDirection",
percentages: "no",
groups: [
"CSS Miscellaneous"
],
initial: "noPracticalInitialValue",
appliesto: "allElements",
computed: "asSpecifiedAppliesToEachProperty",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/all"
};
const animation = {
syntax: "<single-animation>#",
media: "visual",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: [
"animation-name",
"animation-duration",
"animation-timing-function",
"animation-delay",
"animation-iteration-count",
"animation-direction",
"animation-fill-mode",
"animation-play-state",
"animation-timeline"
],
appliesto: "allElementsAndPseudos",
computed: [
"animation-name",
"animation-duration",
"animation-timing-function",
"animation-delay",
"animation-direction",
"animation-iteration-count",
"animation-fill-mode",
"animation-play-state",
"animation-timeline"
],
order: "orderOfAppearance",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/animation"
};
const appearance = {
syntax: "none | auto | textfield | menulist-button | <compat-auto>",
media: "all",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/appearance"
};
const azimuth = {
syntax: "<angle> | [ [ left-side | far-left | left | center-left | center | center-right | right | far-right | right-side ] || behind ] | leftwards | rightwards",
media: "aural",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Speech"
],
initial: "center",
appliesto: "allElements",
computed: "normalizedAngle",
order: "orderOfAppearance",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/azimuth"
};
const background$2 = {
syntax: "[ <bg-layer> , ]* <final-bg-layer>",
media: "visual",
inherited: false,
animationType: [
"background-color",
"background-image",
"background-clip",
"background-position",
"background-size",
"background-repeat",
"background-attachment"
],
percentages: [
"background-position",
"background-size"
],
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"background-image",
"background-position",
"background-size",
"background-repeat",
"background-origin",
"background-clip",
"background-attachment",
"background-color"
],
appliesto: "allElements",
computed: [
"background-image",
"background-position",
"background-size",
"background-repeat",
"background-origin",
"background-clip",
"background-attachment",
"background-color"
],
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background"
};
const border$2 = {
syntax: "<line-width> || <line-style> || <color>",
media: "visual",
inherited: false,
animationType: [
"border-color",
"border-style",
"border-width"
],
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"border-width",
"border-style",
"border-color"
],
appliesto: "allElements",
computed: [
"border-width",
"border-style",
"border-color"
],
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border"
};
const bottom = {
syntax: "<length> | <percentage> | auto",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToContainingBlockHeight",
groups: [
"CSS Positioning"
],
initial: "auto",
appliesto: "positionedElements",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/bottom"
};
const clear = {
syntax: "none | left | right | both | inline-start | inline-end",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Positioning"
],
initial: "none",
appliesto: "blockLevelElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/clear"
};
const clip = {
syntax: "<shape> | auto",
media: "visual",
inherited: false,
animationType: "rectangle",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "auto",
appliesto: "absolutelyPositionedElements",
computed: "autoOrRectangle",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/clip"
};
const color$3 = {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Color"
],
initial: "canvastext",
appliesto: "allElementsAndText",
computed: "computedColor",
order: "perGrammar",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/color"
};
const columns = {
syntax: "<'column-width'> || <'column-count'>",
media: "visual",
inherited: false,
animationType: [
"column-width",
"column-count"
],
percentages: "no",
groups: [
"CSS Columns"
],
initial: [
"column-width",
"column-count"
],
appliesto: "blockContainersExceptTableWrappers",
computed: [
"column-width",
"column-count"
],
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/columns"
};
const contain = {
syntax: "none | strict | content | [ size || layout || style || paint ]",
media: "all",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Containment"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/contain"
};
const content = {
syntax: "normal | none | [ <content-replacement> | <content-list> ] [/ [ <string> | <counter> ]+ ]?",
media: "all",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Generated Content"
],
initial: "normal",
appliesto: "allElementsTreeAbidingPseudoElementsPageMarginBoxes",
computed: "normalOnElementsForPseudosNoneAbsoluteURIStringOrAsSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/content"
};
const 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 ] ]",
media: [
"visual",
"interactive"
],
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecifiedURLsAbsolute",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/cursor"
};
const direction = {
syntax: "ltr | rtl",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Writing Modes"
],
initial: "ltr",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/direction"
};
const display = {
syntax: "[ <display-outside> || <display-inside> ] | <display-listitem> | <display-internal> | <display-box> | <display-legacy>",
media: "all",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Display"
],
initial: "inline",
appliesto: "allElements",
computed: "asSpecifiedExceptPositionedFloatingAndRootElementsKeywordMaybeDifferent",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/display"
};
const filter = {
syntax: "none | <filter-function-list>",
media: "visual",
inherited: false,
animationType: "filterList",
percentages: "no",
groups: [
"Filter Effects"
],
initial: "none",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/filter"
};
const flex = {
syntax: "none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]",
media: "visual",
inherited: false,
animationType: [
"flex-grow",
"flex-shrink",
"flex-basis"
],
percentages: "no",
groups: [
"CSS Flexible Box Layout"
],
initial: [
"flex-grow",
"flex-shrink",
"flex-basis"
],
appliesto: "flexItemsAndInFlowPseudos",
computed: [
"flex-grow",
"flex-shrink",
"flex-basis"
],
order: "orderOfAppearance",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/flex"
};
const float = {
syntax: "left | right | none | inline-start | inline-end",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Positioning"
],
initial: "none",
appliesto: "allElementsNoEffectIfDisplayNone",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/float"
};
const font$2 = {
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",
media: "visual",
inherited: true,
animationType: [
"font-style",
"font-variant",
"font-weight",
"font-stretch",
"font-size",
"line-height",
"font-family"
],
percentages: [
"font-size",
"line-height"
],
groups: [
"CSS Fonts"
],
initial: [
"font-style",
"font-variant",
"font-weight",
"font-stretch",
"font-size",
"line-height",
"font-family"
],
appliesto: "allElements",
computed: [
"font-style",
"font-variant",
"font-weight",
"font-stretch",
"font-size",
"line-height",
"font-family"
],
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font"
};
const gap = {
syntax: "<'row-gap'> <'column-gap'>?",
media: "visual",
inherited: false,
animationType: [
"row-gap",
"column-gap"
],
percentages: "no",
groups: [
"CSS Box Alignment"
],
initial: [
"row-gap",
"column-gap"
],
appliesto: "multiColumnElementsFlexContainersGridContainers",
computed: [
"row-gap",
"column-gap"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/gap"
};
const grid = {
syntax: "<'grid-template'> | <'grid-template-rows'> / [ auto-flow && dense? ] <'grid-auto-columns'>? | [ auto-flow && dense? ] <'grid-auto-rows'>? / <'grid-template-columns'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: [
"grid-template-rows",
"grid-template-columns",
"grid-auto-rows",
"grid-auto-columns"
],
groups: [
"CSS Grid Layout"
],
initial: [
"grid-template-rows",
"grid-template-columns",
"grid-template-areas",
"grid-auto-rows",
"grid-auto-columns",
"grid-auto-flow",
"grid-column-gap",
"grid-row-gap",
"column-gap",
"row-gap"
],
appliesto: "gridContainers",
computed: [
"grid-template-rows",
"grid-template-columns",
"grid-template-areas",
"grid-auto-rows",
"grid-auto-columns",
"grid-auto-flow",
"grid-column-gap",
"grid-row-gap",
"column-gap",
"row-gap"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid"
};
const height = {
syntax: "auto | <length> | <percentage> | min-content | max-content | fit-content | fit-content(<length-percentage>)",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "regardingHeightOfGeneratedBoxContainingBlockPercentagesRelativeToContainingBlock",
groups: [
"CSS Box Model"
],
initial: "auto",
appliesto: "allElementsButNonReplacedAndTableColumns",
computed: "percentageAutoOrAbsoluteLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/height"
};
const hyphens = {
syntax: "none | manual | auto",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "manual",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/hyphens"
};
const inset = {
syntax: "<'top'>{1,4}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "logicalHeightOrWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "auto",
appliesto: "positionedElements",
computed: "sameAsBoxOffsets",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/inset"
};
const isolation = {
syntax: "auto | isolate",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Compositing and Blending"
],
initial: "auto",
appliesto: "allElementsSVGContainerGraphicsAndGraphicsReferencingElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/isolation"
};
const left = {
syntax: "<length> | <percentage> | auto",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Positioning"
],
initial: "auto",
appliesto: "positionedElements",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/left"
};
const margin = {
syntax: "[ <length> | <percentage> | auto ]{1,4}",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: [
"margin-bottom",
"margin-left",
"margin-right",
"margin-top"
],
appliesto: "allElementsExceptTableDisplayTypes",
computed: [
"margin-bottom",
"margin-left",
"margin-right",
"margin-top"
],
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin"
};
const mask = {
syntax: "<mask-layer>#",
media: "visual",
inherited: false,
animationType: [
"mask-image",
"mask-mode",
"mask-repeat",
"mask-position",
"mask-clip",
"mask-origin",
"mask-size",
"mask-composite"
],
percentages: [
"mask-position"
],
groups: [
"CSS Masking"
],
initial: [
"mask-image",
"mask-mode",
"mask-repeat",
"mask-position",
"mask-clip",
"mask-origin",
"mask-size",
"mask-composite"
],
appliesto: "allElementsSVGContainerElements",
computed: [
"mask-image",
"mask-mode",
"mask-repeat",
"mask-position",
"mask-clip",
"mask-origin",
"mask-size",
"mask-composite"
],
order: "perGrammar",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask"
};
const offset = {
syntax: "[ <'offset-position'>? [ <'offset-path'> [ <'offset-distance'> || <'offset-rotate'> ]? ]? ]! [ / <'offset-anchor'> ]?",
media: "visual",
inherited: false,
animationType: [
"offset-position",
"offset-path",
"offset-distance",
"offset-anchor",
"offset-rotate"
],
percentages: [
"offset-position",
"offset-distance",
"offset-anchor"
],
groups: [
"CSS Motion Path"
],
initial: [
"offset-position",
"offset-path",
"offset-distance",
"offset-anchor",
"offset-rotate"
],
appliesto: "transformableElements",
computed: [
"offset-position",
"offset-path",
"offset-distance",
"offset-anchor",
"offset-rotate"
],
order: "perGrammar",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/offset"
};
const opacity = {
syntax: "<alpha-value>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "mapToRange0To1",
groups: [
"CSS Color"
],
initial: "1",
appliesto: "allElements",
computed: "specifiedValueNumberClipped0To1",
order: "perGrammar",
alsoAppliesTo: [
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/opacity"
};
const order = {
syntax: "<integer>",
media: "visual",
inherited: false,
animationType: "integer",
percentages: "no",
groups: [
"CSS Flexible Box Layout"
],
initial: "0",
appliesto: "flexItemsGridItemsAbsolutelyPositionedContainerChildren",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/order"
};
const orphans = {
syntax: "<integer>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fragmentation"
],
initial: "2",
appliesto: "blockContainerElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/orphans"
};
const outline = {
syntax: "[ <'outline-color'> || <'outline-style'> || <'outline-width'> ]",
media: [
"visual",
"interactive"
],
inherited: false,
animationType: [
"outline-color",
"outline-width",
"outline-style"
],
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: [
"outline-color",
"outline-style",
"outline-width"
],
appliesto: "allElements",
computed: [
"outline-color",
"outline-width",
"outline-style"
],
order: "orderOfAppearance",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/outline"
};
const overflow = {
syntax: "[ visible | hidden | clip | scroll | auto ]{1,2}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Overflow"
],
initial: "visible",
appliesto: "blockContainersFlexContainersGridContainers",
computed: [
"overflow-x",
"overflow-y"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/overflow"
};
const padding = {
syntax: "[ <length> | <percentage> ]{1,4}",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: [
"padding-bottom",
"padding-left",
"padding-right",
"padding-top"
],
appliesto: "allElementsExceptInternalTableDisplayTypes",
computed: [
"padding-bottom",
"padding-left",
"padding-right",
"padding-top"
],
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding"
};
const perspective = {
syntax: "none | <length>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "no",
groups: [
"CSS Transforms"
],
initial: "none",
appliesto: "transformableElements",
computed: "absoluteLengthOrNone",
order: "uniqueOrder",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/perspective"
};
const position$1 = {
syntax: "static | relative | absolute | sticky | fixed",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Positioning"
],
initial: "static",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/position"
};
const quotes = {
syntax: "none | auto | [ <string> <string> ]+",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Generated Content"
],
initial: "dependsOnUserAgent",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/quotes"
};
const resize = {
syntax: "none | both | horizontal | vertical | block | inline",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "none",
appliesto: "elementsWithOverflowNotVisibleAndReplacedElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/resize"
};
const right = {
syntax: "<length> | <percentage> | auto",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Positioning"
],
initial: "auto",
appliesto: "positionedElements",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/right"
};
const rotate = {
syntax: "none | <angle> | [ x | y | z | <number>{3} ] && <angle>",
media: "visual",
inherited: false,
animationType: "transform",
percentages: "no",
groups: [
"CSS Transforms"
],
initial: "none",
appliesto: "transformableElements",
computed: "asSpecified",
order: "perGrammar",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/rotate"
};
const scale = {
syntax: "none | <number>{1,3}",
media: "visual",
inherited: false,
animationType: "transform",
percentages: "no",
groups: [
"CSS Transforms"
],
initial: "none",
appliesto: "transformableElements",
computed: "asSpecified",
order: "perGrammar",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scale"
};
const top = {
syntax: "<length> | <percentage> | auto",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToContainingBlockHeight",
groups: [
"CSS Positioning"
],
initial: "auto",
appliesto: "positionedElements",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/top"
};
const transform = {
syntax: "none | <transform-list>",
media: "visual",
inherited: false,
animationType: "transform",
percentages: "referToSizeOfBoundingBox",
groups: [
"CSS Transforms"
],
initial: "none",
appliesto: "transformableElements",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/transform"
};
const transition = {
syntax: "<single-transition>#",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Transitions"
],
initial: [
"transition-delay",
"transition-duration",
"transition-property",
"transition-timing-function"
],
appliesto: "allElementsAndPseudos",
computed: [
"transition-delay",
"transition-duration",
"transition-property",
"transition-timing-function"
],
order: "orderOfAppearance",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/transition"
};
const translate = {
syntax: "none | <length-percentage> [ <length-percentage> <length>? ]?",
media: "visual",
inherited: false,
animationType: "transform",
percentages: "referToSizeOfBoundingBox",
groups: [
"CSS Transforms"
],
initial: "none",
appliesto: "transformableElements",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "perGrammar",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/translate"
};
const visibility = {
syntax: "visible | hidden | collapse",
media: "visual",
inherited: true,
animationType: "visibility",
percentages: "no",
groups: [
"CSS Box Model"
],
initial: "visible",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/visibility"
};
const widows = {
syntax: "<integer>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fragmentation"
],
initial: "2",
appliesto: "blockContainerElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/widows"
};
const width = {
syntax: "auto | <length> | <percentage> | min-content | max-content | fit-content | fit-content(<length-percentage>)",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "auto",
appliesto: "allElementsButNonReplacedAndTableRows",
computed: "percentageAutoOrAbsoluteLength",
order: "lengthOrPercentageBeforeKeywordIfBothPresent",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/width"
};
const zoom = {
syntax: "normal | reset | <number> | <percentage>",
media: "visual",
inherited: false,
animationType: "integer",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/zoom"
};
const require$$2 = {
"--*": {
syntax: "<declaration-value>",
media: "all",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Variables"
],
initial: "seeProse",
appliesto: "allElements",
computed: "asSpecifiedWithVarsSubstituted",
order: "perGrammar",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/--*"
},
"-ms-accelerator": {
syntax: "false | true",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "false",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-accelerator"
},
"-ms-block-progression": {
syntax: "tb | rl | bt | lr",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "tb",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-block-progression"
},
"-ms-content-zoom-chaining": {
syntax: "none | chained",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "none",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-content-zoom-chaining"
},
"-ms-content-zooming": {
syntax: "none | zoom",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "zoomForTheTopLevelNoneForTheRest",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-content-zooming"
},
"-ms-content-zoom-limit": {
syntax: "<'-ms-content-zoom-limit-min'> <'-ms-content-zoom-limit-max'>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: [
"-ms-content-zoom-limit-max",
"-ms-content-zoom-limit-min"
],
groups: [
"Microsoft Extensions"
],
initial: [
"-ms-content-zoom-limit-max",
"-ms-content-zoom-limit-min"
],
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: [
"-ms-content-zoom-limit-max",
"-ms-content-zoom-limit-min"
],
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-content-zoom-limit"
},
"-ms-content-zoom-limit-max": {
syntax: "<percentage>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "maxZoomFactor",
groups: [
"Microsoft Extensions"
],
initial: "400%",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-content-zoom-limit-max"
},
"-ms-content-zoom-limit-min": {
syntax: "<percentage>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "minZoomFactor",
groups: [
"Microsoft Extensions"
],
initial: "100%",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-content-zoom-limit-min"
},
"-ms-content-zoom-snap": {
syntax: "<'-ms-content-zoom-snap-type'> || <'-ms-content-zoom-snap-points'>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: [
"-ms-content-zoom-snap-type",
"-ms-content-zoom-snap-points"
],
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: [
"-ms-content-zoom-snap-type",
"-ms-content-zoom-snap-points"
],
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-content-zoom-snap"
},
"-ms-content-zoom-snap-points": {
syntax: "snapInterval( <percentage>, <percentage> ) | snapList( <percentage># )",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "snapInterval(0%, 100%)",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-content-zoom-snap-points"
},
"-ms-content-zoom-snap-type": {
syntax: "none | proximity | mandatory",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "none",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-content-zoom-snap-type"
},
"-ms-filter": {
syntax: "<string>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "\"\"",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-filter"
},
"-ms-flow-from": {
syntax: "[ none | <custom-ident> ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "none",
appliesto: "nonReplacedElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-flow-from"
},
"-ms-flow-into": {
syntax: "[ none | <custom-ident> ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "none",
appliesto: "iframeElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-flow-into"
},
"-ms-grid-columns": {
syntax: "none | <track-list> | <auto-track-list>",
media: "visual",
inherited: false,
animationType: "simpleListOfLpcDifferenceLpc",
percentages: "referToDimensionOfContentArea",
groups: [
"CSS Grid Layout"
],
initial: "none",
appliesto: "gridContainers",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-grid-columns"
},
"-ms-grid-rows": {
syntax: "none | <track-list> | <auto-track-list>",
media: "visual",
inherited: false,
animationType: "simpleListOfLpcDifferenceLpc",
percentages: "referToDimensionOfContentArea",
groups: [
"CSS Grid Layout"
],
initial: "none",
appliesto: "gridContainers",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-grid-rows"
},
"-ms-high-contrast-adjust": {
syntax: "auto | none",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-high-contrast-adjust"
},
"-ms-hyphenate-limit-chars": {
syntax: "auto | <integer>{1,3}",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-hyphenate-limit-chars"
},
"-ms-hyphenate-limit-lines": {
syntax: "no-limit | <integer>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "no-limit",
appliesto: "blockContainerElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-hyphenate-limit-lines"
},
"-ms-hyphenate-limit-zone": {
syntax: "<percentage> | <length>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "referToLineBoxWidth",
groups: [
"Microsoft Extensions"
],
initial: "0",
appliesto: "blockContainerElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-hyphenate-limit-zone"
},
"-ms-ime-align": {
syntax: "auto | after",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-ime-align"
},
"-ms-overflow-style": {
syntax: "auto | none | scrollbar | -ms-autohiding-scrollbar",
media: "interactive",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "auto",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-overflow-style"
},
"-ms-scrollbar-3dlight-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "dependsOnUserAgent",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scrollbar-3dlight-color"
},
"-ms-scrollbar-arrow-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "ButtonText",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scrollbar-arrow-color"
},
"-ms-scrollbar-base-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "dependsOnUserAgent",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scrollbar-base-color"
},
"-ms-scrollbar-darkshadow-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "ThreeDDarkShadow",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scrollbar-darkshadow-color"
},
"-ms-scrollbar-face-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "ThreeDFace",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scrollbar-face-color"
},
"-ms-scrollbar-highlight-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "ThreeDHighlight",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scrollbar-highlight-color"
},
"-ms-scrollbar-shadow-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "ThreeDDarkShadow",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scrollbar-shadow-color"
},
"-ms-scrollbar-track-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "Scrollbar",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scrollbar-track-color"
},
"-ms-scroll-chaining": {
syntax: "chained | none",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "chained",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-chaining"
},
"-ms-scroll-limit": {
syntax: "<'-ms-scroll-limit-x-min'> <'-ms-scroll-limit-y-min'> <'-ms-scroll-limit-x-max'> <'-ms-scroll-limit-y-max'>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: [
"-ms-scroll-limit-x-min",
"-ms-scroll-limit-y-min",
"-ms-scroll-limit-x-max",
"-ms-scroll-limit-y-max"
],
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: [
"-ms-scroll-limit-x-min",
"-ms-scroll-limit-y-min",
"-ms-scroll-limit-x-max",
"-ms-scroll-limit-y-max"
],
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-limit"
},
"-ms-scroll-limit-x-max": {
syntax: "auto | <length>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "auto",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-limit-x-max"
},
"-ms-scroll-limit-x-min": {
syntax: "<length>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "0",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-limit-x-min"
},
"-ms-scroll-limit-y-max": {
syntax: "auto | <length>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "auto",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-limit-y-max"
},
"-ms-scroll-limit-y-min": {
syntax: "<length>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "0",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-limit-y-min"
},
"-ms-scroll-rails": {
syntax: "none | railed",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "railed",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-rails"
},
"-ms-scroll-snap-points-x": {
syntax: "snapInterval( <length-percentage>, <length-percentage> ) | snapList( <length-percentage># )",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "snapInterval(0px, 100%)",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-snap-points-x"
},
"-ms-scroll-snap-points-y": {
syntax: "snapInterval( <length-percentage>, <length-percentage> ) | snapList( <length-percentage># )",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "snapInterval(0px, 100%)",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-snap-points-y"
},
"-ms-scroll-snap-type": {
syntax: "none | proximity | mandatory",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "none",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-snap-type"
},
"-ms-scroll-snap-x": {
syntax: "<'-ms-scroll-snap-type'> <'-ms-scroll-snap-points-x'>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: [
"-ms-scroll-snap-type",
"-ms-scroll-snap-points-x"
],
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: [
"-ms-scroll-snap-type",
"-ms-scroll-snap-points-x"
],
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-snap-x"
},
"-ms-scroll-snap-y": {
syntax: "<'-ms-scroll-snap-type'> <'-ms-scroll-snap-points-y'>",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: [
"-ms-scroll-snap-type",
"-ms-scroll-snap-points-y"
],
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: [
"-ms-scroll-snap-type",
"-ms-scroll-snap-points-y"
],
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-snap-y"
},
"-ms-scroll-translation": {
syntax: "none | vertical-to-horizontal",
media: "interactive",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-scroll-translation"
},
"-ms-text-autospace": {
syntax: "none | ideograph-alpha | ideograph-numeric | ideograph-parenthesis | ideograph-space",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-text-autospace"
},
"-ms-touch-select": {
syntax: "grippers | none",
media: "interactive",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "grippers",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-touch-select"
},
"-ms-user-select": {
syntax: "none | element | text",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "text",
appliesto: "nonReplacedElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-user-select"
},
"-ms-wrap-flow": {
syntax: "auto | both | start | end | maximum | clear",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "auto",
appliesto: "blockLevelElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-wrap-flow"
},
"-ms-wrap-margin": {
syntax: "<length>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "0",
appliesto: "exclusionElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-wrap-margin"
},
"-ms-wrap-through": {
syntax: "wrap | none",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Microsoft Extensions"
],
initial: "wrap",
appliesto: "blockLevelElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-ms-wrap-through"
},
"-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",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions",
"WebKit Extensions"
],
initial: "noneButOverriddenInUserAgentCSS",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/appearance"
},
"-moz-binding": {
syntax: "<url> | none",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "none",
appliesto: "allElementsExceptGeneratedContentOrPseudoElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-binding"
},
"-moz-border-bottom-colors": {
syntax: "<color>+ | none",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-border-bottom-colors"
},
"-moz-border-left-colors": {
syntax: "<color>+ | none",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-border-left-colors"
},
"-moz-border-right-colors": {
syntax: "<color>+ | none",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-border-right-colors"
},
"-moz-border-top-colors": {
syntax: "<color>+ | none",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-border-top-colors"
},
"-moz-context-properties": {
syntax: "none | [ fill | fill-opacity | stroke | stroke-opacity ]#",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "none",
appliesto: "allElementsThatCanReferenceImages",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-context-properties"
},
"-moz-float-edge": {
syntax: "border-box | content-box | margin-box | padding-box",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "content-box",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-float-edge"
},
"-moz-force-broken-image-icon": {
syntax: "0 | 1",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "0",
appliesto: "images",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-force-broken-image-icon"
},
"-moz-image-region": {
syntax: "<shape> | auto",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "auto",
appliesto: "xulImageElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-image-region"
},
"-moz-orient": {
syntax: "inline | block | horizontal | vertical",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "inline",
appliesto: "anyElementEffectOnProgressAndMeter",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-orient"
},
"-moz-outline-radius": {
syntax: "<outline-radius>{1,4} [ / <outline-radius>{1,4} ]?",
media: "visual",
inherited: false,
animationType: [
"-moz-outline-radius-topleft",
"-moz-outline-radius-topright",
"-moz-outline-radius-bottomright",
"-moz-outline-radius-bottomleft"
],
percentages: [
"-moz-outline-radius-topleft",
"-moz-outline-radius-topright",
"-moz-outline-radius-bottomright",
"-moz-outline-radius-bottomleft"
],
groups: [
"Mozilla Extensions"
],
initial: [
"-moz-outline-radius-topleft",
"-moz-outline-radius-topright",
"-moz-outline-radius-bottomright",
"-moz-outline-radius-bottomleft"
],
appliesto: "allElements",
computed: [
"-moz-outline-radius-topleft",
"-moz-outline-radius-topright",
"-moz-outline-radius-bottomright",
"-moz-outline-radius-bottomleft"
],
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-outline-radius"
},
"-moz-outline-radius-bottomleft": {
syntax: "<outline-radius>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"Mozilla Extensions"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-outline-radius-bottomleft"
},
"-moz-outline-radius-bottomright": {
syntax: "<outline-radius>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"Mozilla Extensions"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-outline-radius-bottomright"
},
"-moz-outline-radius-topleft": {
syntax: "<outline-radius>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"Mozilla Extensions"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-outline-radius-topleft"
},
"-moz-outline-radius-topright": {
syntax: "<outline-radius>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"Mozilla Extensions"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-outline-radius-topright"
},
"-moz-stack-sizing": {
syntax: "ignore | stretch-to-fit",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "stretch-to-fit",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-stack-sizing"
},
"-moz-text-blink": {
syntax: "none | blink",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-text-blink"
},
"-moz-user-focus": {
syntax: "ignore | normal | select-after | select-before | select-menu | select-same | select-all | none",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-user-focus"
},
"-moz-user-input": {
syntax: "auto | none | enabled | disabled",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-user-input"
},
"-moz-user-modify": {
syntax: "read-only | read-write | write-only",
media: "interactive",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "read-only",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-user-modify"
},
"-moz-window-dragging": {
syntax: "drag | no-drag",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "drag",
appliesto: "allElementsCreatingNativeWindows",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-window-dragging"
},
"-moz-window-shadow": {
syntax: "default | menu | tooltip | sheet | none",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "default",
appliesto: "allElementsCreatingNativeWindows",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-moz-window-shadow"
},
"-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",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "noneButOverriddenInUserAgentCSS",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/appearance"
},
"-webkit-border-before": {
syntax: "<'border-width'> || <'border-style'> || <color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: [
"-webkit-border-before-width"
],
groups: [
"WebKit Extensions"
],
initial: [
"border-width",
"border-style",
"color"
],
appliesto: "allElements",
computed: [
"border-width",
"border-style",
"color"
],
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-border-before"
},
"-webkit-border-before-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
status: "nonstandard"
},
"-webkit-border-before-style": {
syntax: "<'border-style'>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard"
},
"-webkit-border-before-width": {
syntax: "<'border-width'>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "logicalWidthOfContainingBlock",
groups: [
"WebKit Extensions"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthZeroIfBorderStyleNoneOrHidden",
order: "uniqueOrder",
status: "nonstandard"
},
"-webkit-box-reflect": {
syntax: "[ above | below | right | left ]? <length>? <image>?",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-box-reflect"
},
"-webkit-line-clamp": {
syntax: "none | <integer>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"WebKit Extensions",
"CSS Overflow"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-line-clamp"
},
"-webkit-mask": {
syntax: "[ <mask-reference> || <position> [ / <bg-size> ]? || <repeat-style> || [ <box> | border | padding | content | text ] || [ <box> | border | padding | content ] ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: [
"-webkit-mask-image",
"-webkit-mask-repeat",
"-webkit-mask-attachment",
"-webkit-mask-position",
"-webkit-mask-origin",
"-webkit-mask-clip"
],
appliesto: "allElements",
computed: [
"-webkit-mask-image",
"-webkit-mask-repeat",
"-webkit-mask-attachment",
"-webkit-mask-position",
"-webkit-mask-origin",
"-webkit-mask-clip"
],
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask"
},
"-webkit-mask-attachment": {
syntax: "<attachment>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "scroll",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-mask-attachment"
},
"-webkit-mask-clip": {
syntax: "[ <box> | border | padding | content | text ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "border",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-clip"
},
"-webkit-mask-composite": {
syntax: "<composite-style>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "source-over",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-mask-composite"
},
"-webkit-mask-image": {
syntax: "<mask-reference>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "none",
appliesto: "allElements",
computed: "absoluteURIOrNone",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-image"
},
"-webkit-mask-origin": {
syntax: "[ <box> | border | padding | content ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "padding",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-origin"
},
"-webkit-mask-position": {
syntax: "<position>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "referToSizeOfElement",
groups: [
"WebKit Extensions"
],
initial: "0% 0%",
appliesto: "allElements",
computed: "absoluteLengthOrPercentage",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-position"
},
"-webkit-mask-position-x": {
syntax: "[ <length-percentage> | left | center | right ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "referToSizeOfElement",
groups: [
"WebKit Extensions"
],
initial: "0%",
appliesto: "allElements",
computed: "absoluteLengthOrPercentage",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-mask-position-x"
},
"-webkit-mask-position-y": {
syntax: "[ <length-percentage> | top | center | bottom ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "referToSizeOfElement",
groups: [
"WebKit Extensions"
],
initial: "0%",
appliesto: "allElements",
computed: "absoluteLengthOrPercentage",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-mask-position-y"
},
"-webkit-mask-repeat": {
syntax: "<repeat-style>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "repeat",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-repeat"
},
"-webkit-mask-repeat-x": {
syntax: "repeat | no-repeat | space | round",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "repeat",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-mask-repeat-x"
},
"-webkit-mask-repeat-y": {
syntax: "repeat | no-repeat | space | round",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "repeat",
appliesto: "allElements",
computed: "absoluteLengthOrPercentage",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-mask-repeat-y"
},
"-webkit-mask-size": {
syntax: "<bg-size>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "relativeToBackgroundPositioningArea",
groups: [
"WebKit Extensions"
],
initial: "auto auto",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-size"
},
"-webkit-overflow-scrolling": {
syntax: "auto | touch",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "auto",
appliesto: "scrollingBoxes",
computed: "asSpecified",
order: "orderOfAppearance",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-overflow-scrolling"
},
"-webkit-tap-highlight-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "black",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-tap-highlight-color"
},
"-webkit-text-fill-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "color",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-text-fill-color"
},
"-webkit-text-stroke": {
syntax: "<length> || <color>",
media: "visual",
inherited: true,
animationType: [
"-webkit-text-stroke-width",
"-webkit-text-stroke-color"
],
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: [
"-webkit-text-stroke-width",
"-webkit-text-stroke-color"
],
appliesto: "allElements",
computed: [
"-webkit-text-stroke-width",
"-webkit-text-stroke-color"
],
order: "canonicalOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-text-stroke"
},
"-webkit-text-stroke-color": {
syntax: "<color>",
media: "visual",
inherited: true,
animationType: "color",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-text-stroke-color"
},
"-webkit-text-stroke-width": {
syntax: "<length>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "0",
appliesto: "allElements",
computed: "absoluteLength",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-text-stroke-width"
},
"-webkit-touch-callout": {
syntax: "default | none",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "default",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/-webkit-touch-callout"
},
"-webkit-user-modify": {
syntax: "read-only | read-write | read-write-plaintext-only",
media: "interactive",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"WebKit Extensions"
],
initial: "read-only",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard"
},
"accent-color": {
syntax: "auto | <color>",
media: "interactive",
inherited: true,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "auto",
appliesto: "allElements",
computed: "asAutoOrColor",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/accent-color"
},
"align-content": {
syntax: "normal | <baseline-position> | <content-distribution> | <overflow-position>? <content-position>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Alignment"
],
initial: "normal",
appliesto: "multilineFlexContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/align-content"
},
"align-items": {
syntax: "normal | stretch | <baseline-position> | [ <overflow-position>? <self-position> ]",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Alignment"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/align-items"
},
"align-self": {
syntax: "auto | normal | stretch | <baseline-position> | <overflow-position>? <self-position>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Alignment"
],
initial: "auto",
appliesto: "flexItemsGridItemsAndAbsolutelyPositionedBoxes",
computed: "autoOnAbsolutelyPositionedElementsValueOfAlignItemsOnParent",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/align-self"
},
"align-tracks": {
syntax: "[ normal | <baseline-position> | <content-distribution> | <overflow-position>? <content-position> ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: "normal",
appliesto: "gridContainersWithMasonryLayoutInTheirBlockAxis",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/align-tracks"
},
all: all,
animation: animation,
"animation-delay": {
syntax: "<time>#",
media: "visual",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: "0s",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/animation-delay"
},
"animation-direction": {
syntax: "<single-animation-direction>#",
media: "visual",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: "normal",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/animation-direction"
},
"animation-duration": {
syntax: "<time>#",
media: "visual",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: "0s",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/animation-duration"
},
"animation-fill-mode": {
syntax: "<single-animation-fill-mode>#",
media: "visual",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: "none",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/animation-fill-mode"
},
"animation-iteration-count": {
syntax: "<single-animation-iteration-count>#",
media: "visual",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: "1",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/animation-iteration-count"
},
"animation-name": {
syntax: "[ none | <keyframes-name> ]#",
media: "visual",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: "none",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/animation-name"
},
"animation-play-state": {
syntax: "<single-animation-play-state>#",
media: "visual",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: "running",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/animation-play-state"
},
"animation-timing-function": {
syntax: "<easing-function>#",
media: "visual",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: "ease",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/animation-timing-function"
},
"animation-timeline": {
syntax: "<single-animation-timeline>#",
media: "visual",
inherited: false,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Animations"
],
initial: "auto",
appliesto: "allElements",
computed: "listEachItemIdentifyerOrNoneAuto",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/animation-timeline"
},
appearance: appearance,
"aspect-ratio": {
syntax: "auto | <ratio>",
media: "all",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "auto",
appliesto: "allElementsExceptInlineBoxesAndInternalRubyOrTableBoxes",
computed: "asSpecified",
order: "perGrammar",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/aspect-ratio"
},
azimuth: azimuth,
"backdrop-filter": {
syntax: "none | <filter-function-list>",
media: "visual",
inherited: false,
animationType: "filterList",
percentages: "no",
groups: [
"Filter Effects"
],
initial: "none",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/backdrop-filter"
},
"backface-visibility": {
syntax: "visible | hidden",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Transforms"
],
initial: "visible",
appliesto: "transformableElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/backface-visibility"
},
background: background$2,
"background-attachment": {
syntax: "<attachment>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "scroll",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-attachment"
},
"background-blend-mode": {
syntax: "<blend-mode>#",
media: "none",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Compositing and Blending"
],
initial: "normal",
appliesto: "allElementsSVGContainerGraphicsAndGraphicsReferencingElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-blend-mode"
},
"background-clip": {
syntax: "<box>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "border-box",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-clip"
},
"background-color": {
syntax: "<color>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "transparent",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-color"
},
"background-image": {
syntax: "<bg-image>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecifiedURLsAbsolute",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-image"
},
"background-origin": {
syntax: "<box>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "padding-box",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-origin"
},
"background-position": {
syntax: "<bg-position>#",
media: "visual",
inherited: false,
animationType: "repeatableListOfSimpleListOfLpc",
percentages: "referToSizeOfBackgroundPositioningAreaMinusBackgroundImageSize",
groups: [
"CSS Backgrounds and Borders"
],
initial: "0% 0%",
appliesto: "allElements",
computed: [
"background-position-x",
"background-position-y"
],
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-position"
},
"background-position-x": {
syntax: "[ center | [ [ left | right | x-start | x-end ]? <length-percentage>? ]! ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "referToWidthOfBackgroundPositioningAreaMinusBackgroundImageHeight",
groups: [
"CSS Backgrounds and Borders"
],
initial: "0%",
appliesto: "allElements",
computed: "listEachItemConsistingOfAbsoluteLengthPercentageAndOrigin",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-position-x"
},
"background-position-y": {
syntax: "[ center | [ [ top | bottom | y-start | y-end ]? <length-percentage>? ]! ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "referToHeightOfBackgroundPositioningAreaMinusBackgroundImageHeight",
groups: [
"CSS Backgrounds and Borders"
],
initial: "0%",
appliesto: "allElements",
computed: "listEachItemConsistingOfAbsoluteLengthPercentageAndOrigin",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-position-y"
},
"background-repeat": {
syntax: "<repeat-style>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "repeat",
appliesto: "allElements",
computed: "listEachItemHasTwoKeywordsOnePerDimension",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-repeat"
},
"background-size": {
syntax: "<bg-size>#",
media: "visual",
inherited: false,
animationType: "repeatableListOfSimpleListOfLpc",
percentages: "relativeToBackgroundPositioningArea",
groups: [
"CSS Backgrounds and Borders"
],
initial: "auto auto",
appliesto: "allElements",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/background-size"
},
"block-overflow": {
syntax: "clip | ellipsis | <string>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Overflow"
],
initial: "clip",
appliesto: "blockContainers",
computed: "asSpecified",
order: "perGrammar",
status: "experimental"
},
"block-size": {
syntax: "<'width'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "blockSizeOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "auto",
appliesto: "sameAsWidthAndHeight",
computed: "sameAsWidthAndHeight",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/block-size"
},
border: border$2,
"border-block": {
syntax: "<'border-top-width'> || <'border-top-style'> || <color>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: [
"border-top-width",
"border-top-style",
"border-top-color"
],
appliesto: "allElements",
computed: [
"border-top-width",
"border-top-style",
"border-top-color"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block"
},
"border-block-color": {
syntax: "<'border-top-color'>{1,2}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-color"
},
"border-block-style": {
syntax: "<'border-top-style'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-style"
},
"border-block-width": {
syntax: "<'border-top-width'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthZeroIfBorderStyleNoneOrHidden",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-width"
},
"border-block-end": {
syntax: "<'border-top-width'> || <'border-top-style'> || <color>",
media: "visual",
inherited: false,
animationType: [
"border-block-end-color",
"border-block-end-style",
"border-block-end-width"
],
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: [
"border-top-width",
"border-top-style",
"border-top-color"
],
appliesto: "allElements",
computed: [
"border-top-width",
"border-top-style",
"border-top-color"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-end"
},
"border-block-end-color": {
syntax: "<'border-top-color'>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-end-color"
},
"border-block-end-style": {
syntax: "<'border-top-style'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-end-style"
},
"border-block-end-width": {
syntax: "<'border-top-width'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthZeroIfBorderStyleNoneOrHidden",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-end-width"
},
"border-block-start": {
syntax: "<'border-top-width'> || <'border-top-style'> || <color>",
media: "visual",
inherited: false,
animationType: [
"border-block-start-color",
"border-block-start-style",
"border-block-start-width"
],
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: [
"border-width",
"border-style",
"color"
],
appliesto: "allElements",
computed: [
"border-width",
"border-style",
"border-block-start-color"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-start"
},
"border-block-start-color": {
syntax: "<'border-top-color'>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-start-color"
},
"border-block-start-style": {
syntax: "<'border-top-style'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-start-style"
},
"border-block-start-width": {
syntax: "<'border-top-width'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthZeroIfBorderStyleNoneOrHidden",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-block-start-width"
},
"border-bottom": {
syntax: "<line-width> || <line-style> || <color>",
media: "visual",
inherited: false,
animationType: [
"border-bottom-color",
"border-bottom-style",
"border-bottom-width"
],
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"border-bottom-width",
"border-bottom-style",
"border-bottom-color"
],
appliesto: "allElements",
computed: [
"border-bottom-width",
"border-bottom-style",
"border-bottom-color"
],
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-bottom"
},
"border-bottom-color": {
syntax: "<'border-top-color'>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-bottom-color"
},
"border-bottom-left-radius": {
syntax: "<length-percentage>{1,2}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"CSS Backgrounds and Borders"
],
initial: "0",
appliesto: "allElementsUAsNotRequiredWhenCollapse",
computed: "twoAbsoluteLengthOrPercentages",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-bottom-left-radius"
},
"border-bottom-right-radius": {
syntax: "<length-percentage>{1,2}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"CSS Backgrounds and Borders"
],
initial: "0",
appliesto: "allElementsUAsNotRequiredWhenCollapse",
computed: "twoAbsoluteLengthOrPercentages",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-bottom-right-radius"
},
"border-bottom-style": {
syntax: "<line-style>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-bottom-style"
},
"border-bottom-width": {
syntax: "<line-width>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthOr0IfBorderBottomStyleNoneOrHidden",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-bottom-width"
},
"border-collapse": {
syntax: "collapse | separate",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Table"
],
initial: "separate",
appliesto: "tableElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-collapse"
},
"border-color": {
syntax: "<color>{1,4}",
media: "visual",
inherited: false,
animationType: [
"border-bottom-color",
"border-left-color",
"border-right-color",
"border-top-color"
],
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"border-top-color",
"border-right-color",
"border-bottom-color",
"border-left-color"
],
appliesto: "allElements",
computed: [
"border-bottom-color",
"border-left-color",
"border-right-color",
"border-top-color"
],
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-color"
},
"border-end-end-radius": {
syntax: "<length-percentage>{1,2}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "allElementsUAsNotRequiredWhenCollapse",
computed: "twoAbsoluteLengthOrPercentages",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-end-end-radius"
},
"border-end-start-radius": {
syntax: "<length-percentage>{1,2}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "allElementsUAsNotRequiredWhenCollapse",
computed: "twoAbsoluteLengthOrPercentages",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-end-start-radius"
},
"border-image": {
syntax: "<'border-image-source'> || <'border-image-slice'> [ / <'border-image-width'> | / <'border-image-width'>? / <'border-image-outset'> ]? || <'border-image-repeat'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: [
"border-image-slice",
"border-image-width"
],
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"border-image-source",
"border-image-slice",
"border-image-width",
"border-image-outset",
"border-image-repeat"
],
appliesto: "allElementsExceptTableElementsWhenCollapse",
computed: [
"border-image-outset",
"border-image-repeat",
"border-image-slice",
"border-image-source",
"border-image-width"
],
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-image"
},
"border-image-outset": {
syntax: "[ <length> | <number> ]{1,4}",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "0",
appliesto: "allElementsExceptTableElementsWhenCollapse",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-image-outset"
},
"border-image-repeat": {
syntax: "[ stretch | repeat | round | space ]{1,2}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "stretch",
appliesto: "allElementsExceptTableElementsWhenCollapse",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-image-repeat"
},
"border-image-slice": {
syntax: "<number-percentage>{1,4} && fill?",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "referToSizeOfBorderImage",
groups: [
"CSS Backgrounds and Borders"
],
initial: "100%",
appliesto: "allElementsExceptTableElementsWhenCollapse",
computed: "oneToFourPercentagesOrAbsoluteLengthsPlusFill",
order: "percentagesOrLengthsFollowedByFill",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-image-slice"
},
"border-image-source": {
syntax: "none | <image>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "none",
appliesto: "allElementsExceptTableElementsWhenCollapse",
computed: "noneOrImageWithAbsoluteURI",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-image-source"
},
"border-image-width": {
syntax: "[ <length-percentage> | <number> | auto ]{1,4}",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "referToWidthOrHeightOfBorderImageArea",
groups: [
"CSS Backgrounds and Borders"
],
initial: "1",
appliesto: "allElementsExceptTableElementsWhenCollapse",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-image-width"
},
"border-inline": {
syntax: "<'border-top-width'> || <'border-top-style'> || <color>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: [
"border-top-width",
"border-top-style",
"border-top-color"
],
appliesto: "allElements",
computed: [
"border-top-width",
"border-top-style",
"border-top-color"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline"
},
"border-inline-end": {
syntax: "<'border-top-width'> || <'border-top-style'> || <color>",
media: "visual",
inherited: false,
animationType: [
"border-inline-end-color",
"border-inline-end-style",
"border-inline-end-width"
],
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: [
"border-width",
"border-style",
"color"
],
appliesto: "allElements",
computed: [
"border-width",
"border-style",
"border-inline-end-color"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-end"
},
"border-inline-color": {
syntax: "<'border-top-color'>{1,2}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-color"
},
"border-inline-style": {
syntax: "<'border-top-style'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-style"
},
"border-inline-width": {
syntax: "<'border-top-width'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthZeroIfBorderStyleNoneOrHidden",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-width"
},
"border-inline-end-color": {
syntax: "<'border-top-color'>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-end-color"
},
"border-inline-end-style": {
syntax: "<'border-top-style'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-end-style"
},
"border-inline-end-width": {
syntax: "<'border-top-width'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthZeroIfBorderStyleNoneOrHidden",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-end-width"
},
"border-inline-start": {
syntax: "<'border-top-width'> || <'border-top-style'> || <color>",
media: "visual",
inherited: false,
animationType: [
"border-inline-start-color",
"border-inline-start-style",
"border-inline-start-width"
],
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: [
"border-width",
"border-style",
"color"
],
appliesto: "allElements",
computed: [
"border-width",
"border-style",
"border-inline-start-color"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-start"
},
"border-inline-start-color": {
syntax: "<'border-top-color'>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-start-color"
},
"border-inline-start-style": {
syntax: "<'border-top-style'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Logical Properties"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-start-style"
},
"border-inline-start-width": {
syntax: "<'border-top-width'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthZeroIfBorderStyleNoneOrHidden",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-inline-start-width"
},
"border-left": {
syntax: "<line-width> || <line-style> || <color>",
media: "visual",
inherited: false,
animationType: [
"border-left-color",
"border-left-style",
"border-left-width"
],
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"border-left-width",
"border-left-style",
"border-left-color"
],
appliesto: "allElements",
computed: [
"border-left-width",
"border-left-style",
"border-left-color"
],
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-left"
},
"border-left-color": {
syntax: "<color>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-left-color"
},
"border-left-style": {
syntax: "<line-style>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-left-style"
},
"border-left-width": {
syntax: "<line-width>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthOr0IfBorderLeftStyleNoneOrHidden",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-left-width"
},
"border-radius": {
syntax: "<length-percentage>{1,4} [ / <length-percentage>{1,4} ]?",
media: "visual",
inherited: false,
animationType: [
"border-top-left-radius",
"border-top-right-radius",
"border-bottom-right-radius",
"border-bottom-left-radius"
],
percentages: "referToDimensionOfBorderBox",
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"border-top-left-radius",
"border-top-right-radius",
"border-bottom-right-radius",
"border-bottom-left-radius"
],
appliesto: "allElementsUAsNotRequiredWhenCollapse",
computed: [
"border-bottom-left-radius",
"border-bottom-right-radius",
"border-top-left-radius",
"border-top-right-radius"
],
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-radius"
},
"border-right": {
syntax: "<line-width> || <line-style> || <color>",
media: "visual",
inherited: false,
animationType: [
"border-right-color",
"border-right-style",
"border-right-width"
],
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"border-right-width",
"border-right-style",
"border-right-color"
],
appliesto: "allElements",
computed: [
"border-right-width",
"border-right-style",
"border-right-color"
],
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-right"
},
"border-right-color": {
syntax: "<color>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-right-color"
},
"border-right-style": {
syntax: "<line-style>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-right-style"
},
"border-right-width": {
syntax: "<line-width>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthOr0IfBorderRightStyleNoneOrHidden",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-right-width"
},
"border-spacing": {
syntax: "<length> <length>?",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Table"
],
initial: "0",
appliesto: "tableElements",
computed: "twoAbsoluteLengths",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-spacing"
},
"border-start-end-radius": {
syntax: "<length-percentage>{1,2}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "allElementsUAsNotRequiredWhenCollapse",
computed: "twoAbsoluteLengthOrPercentages",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-start-end-radius"
},
"border-start-start-radius": {
syntax: "<length-percentage>{1,2}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "allElementsUAsNotRequiredWhenCollapse",
computed: "twoAbsoluteLengthOrPercentages",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-start-start-radius"
},
"border-style": {
syntax: "<line-style>{1,4}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"border-top-style",
"border-right-style",
"border-bottom-style",
"border-left-style"
],
appliesto: "allElements",
computed: [
"border-bottom-style",
"border-left-style",
"border-right-style",
"border-top-style"
],
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-style"
},
"border-top": {
syntax: "<line-width> || <line-style> || <color>",
media: "visual",
inherited: false,
animationType: [
"border-top-color",
"border-top-style",
"border-top-width"
],
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"border-top-width",
"border-top-style",
"border-top-color"
],
appliesto: "allElements",
computed: [
"border-top-width",
"border-top-style",
"border-top-color"
],
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-top"
},
"border-top-color": {
syntax: "<color>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-top-color"
},
"border-top-left-radius": {
syntax: "<length-percentage>{1,2}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"CSS Backgrounds and Borders"
],
initial: "0",
appliesto: "allElementsUAsNotRequiredWhenCollapse",
computed: "twoAbsoluteLengthOrPercentages",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-top-left-radius"
},
"border-top-right-radius": {
syntax: "<length-percentage>{1,2}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfBorderBox",
groups: [
"CSS Backgrounds and Borders"
],
initial: "0",
appliesto: "allElementsUAsNotRequiredWhenCollapse",
computed: "twoAbsoluteLengthOrPercentages",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-top-right-radius"
},
"border-top-style": {
syntax: "<line-style>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-top-style"
},
"border-top-width": {
syntax: "<line-width>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLengthOr0IfBorderTopStyleNoneOrHidden",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-top-width"
},
"border-width": {
syntax: "<line-width>{1,4}",
media: "visual",
inherited: false,
animationType: [
"border-bottom-width",
"border-left-width",
"border-right-width",
"border-top-width"
],
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: [
"border-top-width",
"border-right-width",
"border-bottom-width",
"border-left-width"
],
appliesto: "allElements",
computed: [
"border-bottom-width",
"border-left-width",
"border-right-width",
"border-top-width"
],
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/border-width"
},
bottom: bottom,
"box-align": {
syntax: "start | center | end | baseline | stretch",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions",
"WebKit Extensions"
],
initial: "stretch",
appliesto: "elementsWithDisplayBoxOrInlineBox",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-align"
},
"box-decoration-break": {
syntax: "slice | clone",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fragmentation"
],
initial: "slice",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-decoration-break"
},
"box-direction": {
syntax: "normal | reverse | inherit",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions",
"WebKit Extensions"
],
initial: "normal",
appliesto: "elementsWithDisplayBoxOrInlineBox",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-direction"
},
"box-flex": {
syntax: "<number>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions",
"WebKit Extensions"
],
initial: "0",
appliesto: "directChildrenOfElementsWithDisplayMozBoxMozInlineBox",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-flex"
},
"box-flex-group": {
syntax: "<integer>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions",
"WebKit Extensions"
],
initial: "1",
appliesto: "inFlowChildrenOfBoxElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-flex-group"
},
"box-lines": {
syntax: "single | multiple",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions",
"WebKit Extensions"
],
initial: "single",
appliesto: "boxElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-lines"
},
"box-ordinal-group": {
syntax: "<integer>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions",
"WebKit Extensions"
],
initial: "1",
appliesto: "childrenOfBoxElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-ordinal-group"
},
"box-orient": {
syntax: "horizontal | vertical | inline-axis | block-axis | inherit",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions",
"WebKit Extensions"
],
initial: "inlineAxisHorizontalInXUL",
appliesto: "elementsWithDisplayBoxOrInlineBox",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-orient"
},
"box-pack": {
syntax: "start | center | end | justify",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions",
"WebKit Extensions"
],
initial: "start",
appliesto: "elementsWithDisplayMozBoxMozInlineBox",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-pack"
},
"box-shadow": {
syntax: "none | <shadow>#",
media: "visual",
inherited: false,
animationType: "shadowList",
percentages: "no",
groups: [
"CSS Backgrounds and Borders"
],
initial: "none",
appliesto: "allElements",
computed: "absoluteLengthsSpecifiedColorAsSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-shadow"
},
"box-sizing": {
syntax: "content-box | border-box",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Model"
],
initial: "content-box",
appliesto: "allElementsAcceptingWidthOrHeight",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/box-sizing"
},
"break-after": {
syntax: "auto | avoid | always | all | avoid-page | page | left | right | recto | verso | avoid-column | column | avoid-region | region",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fragmentation"
],
initial: "auto",
appliesto: "blockLevelElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/break-after"
},
"break-before": {
syntax: "auto | avoid | always | all | avoid-page | page | left | right | recto | verso | avoid-column | column | avoid-region | region",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fragmentation"
],
initial: "auto",
appliesto: "blockLevelElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/break-before"
},
"break-inside": {
syntax: "auto | avoid | avoid-page | avoid-column | avoid-region",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fragmentation"
],
initial: "auto",
appliesto: "blockLevelElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/break-inside"
},
"caption-side": {
syntax: "top | bottom | block-start | block-end | inline-start | inline-end",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Table"
],
initial: "top",
appliesto: "tableCaptionElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/caption-side"
},
"caret-color": {
syntax: "auto | <color>",
media: "interactive",
inherited: true,
animationType: "color",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "auto",
appliesto: "allElements",
computed: "asAutoOrColor",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/caret-color"
},
clear: clear,
clip: clip,
"clip-path": {
syntax: "<clip-source> | [ <basic-shape> || <geometry-box> ] | none",
media: "visual",
inherited: false,
animationType: "basicShapeOtherwiseNo",
percentages: "referToReferenceBoxWhenSpecifiedOtherwiseBorderBox",
groups: [
"CSS Masking"
],
initial: "none",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecifiedURLsAbsolute",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/clip-path"
},
color: color$3,
"print-color-adjust": {
syntax: "economy | exact",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Color"
],
initial: "economy",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/print-color-adjust"
},
"color-scheme": {
syntax: "normal | [ light | dark | <custom-ident> ]+ && only?",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Color"
],
initial: "normal",
appliesto: "allElementsAndText",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/color-scheme"
},
"column-count": {
syntax: "<integer> | auto",
media: "visual",
inherited: false,
animationType: "integer",
percentages: "no",
groups: [
"CSS Columns"
],
initial: "auto",
appliesto: "blockContainersExceptTableWrappers",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/column-count"
},
"column-fill": {
syntax: "auto | balance | balance-all",
media: "visualInContinuousMediaNoEffectInOverflowColumns",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Columns"
],
initial: "balance",
appliesto: "multicolElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/column-fill"
},
"column-gap": {
syntax: "normal | <length-percentage>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfContentArea",
groups: [
"CSS Box Alignment"
],
initial: "normal",
appliesto: "multiColumnElementsFlexContainersGridContainers",
computed: "asSpecifiedWithLengthsAbsoluteAndNormalComputingToZeroExceptMultiColumn",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/column-gap"
},
"column-rule": {
syntax: "<'column-rule-width'> || <'column-rule-style'> || <'column-rule-color'>",
media: "visual",
inherited: false,
animationType: [
"column-rule-color",
"column-rule-style",
"column-rule-width"
],
percentages: "no",
groups: [
"CSS Columns"
],
initial: [
"column-rule-width",
"column-rule-style",
"column-rule-color"
],
appliesto: "multicolElements",
computed: [
"column-rule-color",
"column-rule-style",
"column-rule-width"
],
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/column-rule"
},
"column-rule-color": {
syntax: "<color>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Columns"
],
initial: "currentcolor",
appliesto: "multicolElements",
computed: "computedColor",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/column-rule-color"
},
"column-rule-style": {
syntax: "<'border-style'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Columns"
],
initial: "none",
appliesto: "multicolElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/column-rule-style"
},
"column-rule-width": {
syntax: "<'border-width'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "no",
groups: [
"CSS Columns"
],
initial: "medium",
appliesto: "multicolElements",
computed: "absoluteLength0IfColumnRuleStyleNoneOrHidden",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/column-rule-width"
},
"column-span": {
syntax: "none | all",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Columns"
],
initial: "none",
appliesto: "inFlowBlockLevelElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/column-span"
},
"column-width": {
syntax: "<length> | auto",
media: "visual",
inherited: false,
animationType: "length",
percentages: "no",
groups: [
"CSS Columns"
],
initial: "auto",
appliesto: "blockContainersExceptTableWrappers",
computed: "absoluteLengthZeroOrLarger",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/column-width"
},
columns: columns,
contain: contain,
content: content,
"content-visibility": {
syntax: "visible | auto | hidden",
media: "all",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Containment"
],
initial: "visible",
appliesto: "elementsForWhichLayoutContainmentCanApply",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/content-visibility"
},
"counter-increment": {
syntax: "[ <counter-name> <integer>? ]+ | none",
media: "all",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Counter Styles"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/counter-increment"
},
"counter-reset": {
syntax: "[ <counter-name> <integer>? | <reversed-counter-name> <integer>? ]+ | none",
media: "all",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Counter Styles"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/counter-reset"
},
"counter-set": {
syntax: "[ <counter-name> <integer>? ]+ | none",
media: "all",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Counter Styles"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/counter-set"
},
cursor: cursor,
direction: direction,
display: display,
"empty-cells": {
syntax: "show | hide",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Table"
],
initial: "show",
appliesto: "tableCellElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/empty-cells"
},
filter: filter,
flex: flex,
"flex-basis": {
syntax: "content | <'width'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToFlexContainersInnerMainSize",
groups: [
"CSS Flexible Box Layout"
],
initial: "auto",
appliesto: "flexItemsAndInFlowPseudos",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "lengthOrPercentageBeforeKeywordIfBothPresent",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/flex-basis"
},
"flex-direction": {
syntax: "row | row-reverse | column | column-reverse",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Flexible Box Layout"
],
initial: "row",
appliesto: "flexContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/flex-direction"
},
"flex-flow": {
syntax: "<'flex-direction'> || <'flex-wrap'>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Flexible Box Layout"
],
initial: [
"flex-direction",
"flex-wrap"
],
appliesto: "flexContainers",
computed: [
"flex-direction",
"flex-wrap"
],
order: "orderOfAppearance",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/flex-flow"
},
"flex-grow": {
syntax: "<number>",
media: "visual",
inherited: false,
animationType: "number",
percentages: "no",
groups: [
"CSS Flexible Box Layout"
],
initial: "0",
appliesto: "flexItemsAndInFlowPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/flex-grow"
},
"flex-shrink": {
syntax: "<number>",
media: "visual",
inherited: false,
animationType: "number",
percentages: "no",
groups: [
"CSS Flexible Box Layout"
],
initial: "1",
appliesto: "flexItemsAndInFlowPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/flex-shrink"
},
"flex-wrap": {
syntax: "nowrap | wrap | wrap-reverse",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Flexible Box Layout"
],
initial: "nowrap",
appliesto: "flexContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/flex-wrap"
},
float: float,
font: font$2,
"font-family": {
syntax: "[ <family-name> | <generic-family> ]#",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "dependsOnUserAgent",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-family"
},
"font-feature-settings": {
syntax: "normal | <feature-tag-value>#",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-feature-settings"
},
"font-kerning": {
syntax: "auto | normal | none",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-kerning"
},
"font-language-override": {
syntax: "normal | <string>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-language-override"
},
"font-optical-sizing": {
syntax: "auto | none",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-optical-sizing"
},
"font-variation-settings": {
syntax: "normal | [ <string> <number> ]#",
media: "visual",
inherited: true,
animationType: "transform",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-variation-settings"
},
"font-size": {
syntax: "<absolute-size> | <relative-size> | <length-percentage>",
media: "visual",
inherited: true,
animationType: "length",
percentages: "referToParentElementsFontSize",
groups: [
"CSS Fonts"
],
initial: "medium",
appliesto: "allElements",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-size"
},
"font-size-adjust": {
syntax: "none | [ ex-height | cap-height | ch-width | ic-width | ic-height ]? [ from-font | <number> ]",
media: "visual",
inherited: true,
animationType: "number",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-size-adjust"
},
"font-smooth": {
syntax: "auto | never | always | <absolute-size> | <length>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-smooth"
},
"font-stretch": {
syntax: "<font-stretch-absolute>",
media: "visual",
inherited: true,
animationType: "fontStretch",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-stretch"
},
"font-style": {
syntax: "normal | italic | oblique <angle>?",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-style"
},
"font-synthesis": {
syntax: "none | [ weight || style || small-caps ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "weight style",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-synthesis"
},
"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 ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-variant"
},
"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> ) ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-variant-alternates"
},
"font-variant-caps": {
syntax: "normal | small-caps | all-small-caps | petite-caps | all-petite-caps | unicase | titling-caps",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-variant-caps"
},
"font-variant-east-asian": {
syntax: "normal | [ <east-asian-variant-values> || <east-asian-width-values> || ruby ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-variant-east-asian"
},
"font-variant-ligatures": {
syntax: "normal | none | [ <common-lig-values> || <discretionary-lig-values> || <historical-lig-values> || <contextual-alt-values> ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-variant-ligatures"
},
"font-variant-numeric": {
syntax: "normal | [ <numeric-figure-values> || <numeric-spacing-values> || <numeric-fraction-values> || ordinal || slashed-zero ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-variant-numeric"
},
"font-variant-position": {
syntax: "normal | sub | super",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-variant-position"
},
"font-weight": {
syntax: "<font-weight-absolute> | bolder | lighter",
media: "visual",
inherited: true,
animationType: "fontWeight",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "keywordOrNumericalValueBolderLighterTransformedToRealValue",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/font-weight"
},
"forced-color-adjust": {
syntax: "auto | none",
media: "visual",
inherited: true,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Color"
],
initial: "auto",
appliesto: "allElementsAndText",
computed: "asSpecified",
order: "perGrammar",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/forced-color-adjust"
},
gap: gap,
grid: grid,
"grid-area": {
syntax: "<grid-line> [ / <grid-line> ]{0,3}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: [
"grid-row-start",
"grid-column-start",
"grid-row-end",
"grid-column-end"
],
appliesto: "gridItemsAndBoxesWithinGridContainer",
computed: [
"grid-row-start",
"grid-column-start",
"grid-row-end",
"grid-column-end"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-area"
},
"grid-auto-columns": {
syntax: "<track-size>+",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "referToDimensionOfContentArea",
groups: [
"CSS Grid Layout"
],
initial: "auto",
appliesto: "gridContainers",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-auto-columns"
},
"grid-auto-flow": {
syntax: "[ row | column ] || dense",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: "row",
appliesto: "gridContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-auto-flow"
},
"grid-auto-rows": {
syntax: "<track-size>+",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "referToDimensionOfContentArea",
groups: [
"CSS Grid Layout"
],
initial: "auto",
appliesto: "gridContainers",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-auto-rows"
},
"grid-column": {
syntax: "<grid-line> [ / <grid-line> ]?",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: [
"grid-column-start",
"grid-column-end"
],
appliesto: "gridItemsAndBoxesWithinGridContainer",
computed: [
"grid-column-start",
"grid-column-end"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-column"
},
"grid-column-end": {
syntax: "<grid-line>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: "auto",
appliesto: "gridItemsAndBoxesWithinGridContainer",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-column-end"
},
"grid-column-gap": {
syntax: "<length-percentage>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToDimensionOfContentArea",
groups: [
"CSS Grid Layout"
],
initial: "0",
appliesto: "gridContainers",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/column-gap"
},
"grid-column-start": {
syntax: "<grid-line>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: "auto",
appliesto: "gridItemsAndBoxesWithinGridContainer",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-column-start"
},
"grid-gap": {
syntax: "<'grid-row-gap'> <'grid-column-gap'>?",
media: "visual",
inherited: false,
animationType: [
"grid-row-gap",
"grid-column-gap"
],
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: [
"grid-row-gap",
"grid-column-gap"
],
appliesto: "gridContainers",
computed: [
"grid-row-gap",
"grid-column-gap"
],
order: "uniqueOrder",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/gap"
},
"grid-row": {
syntax: "<grid-line> [ / <grid-line> ]?",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: [
"grid-row-start",
"grid-row-end"
],
appliesto: "gridItemsAndBoxesWithinGridContainer",
computed: [
"grid-row-start",
"grid-row-end"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-row"
},
"grid-row-end": {
syntax: "<grid-line>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: "auto",
appliesto: "gridItemsAndBoxesWithinGridContainer",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-row-end"
},
"grid-row-gap": {
syntax: "<length-percentage>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToDimensionOfContentArea",
groups: [
"CSS Grid Layout"
],
initial: "0",
appliesto: "gridContainers",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/row-gap"
},
"grid-row-start": {
syntax: "<grid-line>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: "auto",
appliesto: "gridItemsAndBoxesWithinGridContainer",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-row-start"
},
"grid-template": {
syntax: "none | [ <'grid-template-rows'> / <'grid-template-columns'> ] | [ <line-names>? <string> <track-size>? <line-names>? ]+ [ / <explicit-track-list> ]?",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: [
"grid-template-columns",
"grid-template-rows"
],
groups: [
"CSS Grid Layout"
],
initial: [
"grid-template-columns",
"grid-template-rows",
"grid-template-areas"
],
appliesto: "gridContainers",
computed: [
"grid-template-columns",
"grid-template-rows",
"grid-template-areas"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-template"
},
"grid-template-areas": {
syntax: "none | <string>+",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: "none",
appliesto: "gridContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-template-areas"
},
"grid-template-columns": {
syntax: "none | <track-list> | <auto-track-list> | subgrid <line-name-list>?",
media: "visual",
inherited: false,
animationType: "simpleListOfLpcDifferenceLpc",
percentages: "referToDimensionOfContentArea",
groups: [
"CSS Grid Layout"
],
initial: "none",
appliesto: "gridContainers",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-template-columns"
},
"grid-template-rows": {
syntax: "none | <track-list> | <auto-track-list> | subgrid <line-name-list>?",
media: "visual",
inherited: false,
animationType: "simpleListOfLpcDifferenceLpc",
percentages: "referToDimensionOfContentArea",
groups: [
"CSS Grid Layout"
],
initial: "none",
appliesto: "gridContainers",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/grid-template-rows"
},
"hanging-punctuation": {
syntax: "none | [ first || [ force-end | allow-end ] || last ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/hanging-punctuation"
},
height: height,
"hyphenate-character": {
syntax: "auto | <string>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/hyphenate-character"
},
hyphens: hyphens,
"image-orientation": {
syntax: "from-image | <angle> | [ <angle>? flip ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Images"
],
initial: "from-image",
appliesto: "allElements",
computed: "angleRoundedToNextQuarter",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/image-orientation"
},
"image-rendering": {
syntax: "auto | crisp-edges | pixelated",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Images"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/image-rendering"
},
"image-resolution": {
syntax: "[ from-image || <resolution> ] && snap?",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Images"
],
initial: "1dppx",
appliesto: "allElements",
computed: "asSpecifiedWithExceptionOfResolution",
order: "uniqueOrder",
status: "experimental"
},
"ime-mode": {
syntax: "auto | normal | active | inactive | disabled",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "auto",
appliesto: "textFields",
computed: "asSpecified",
order: "uniqueOrder",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/ime-mode"
},
"initial-letter": {
syntax: "normal | [ <number> <integer>? ]",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Inline"
],
initial: "normal",
appliesto: "firstLetterPseudoElementsAndInlineLevelFirstChildren",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/initial-letter"
},
"initial-letter-align": {
syntax: "[ auto | alphabetic | hanging | ideographic ]",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Inline"
],
initial: "auto",
appliesto: "firstLetterPseudoElementsAndInlineLevelFirstChildren",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/initial-letter-align"
},
"inline-size": {
syntax: "<'width'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "inlineSizeOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "auto",
appliesto: "sameAsWidthAndHeight",
computed: "sameAsWidthAndHeight",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/inline-size"
},
"input-security": {
syntax: "auto | none",
media: "interactive",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "auto",
appliesto: "sensitiveTextInputs",
computed: "asSpecified",
order: "perGrammar",
status: "standard"
},
inset: inset,
"inset-block": {
syntax: "<'top'>{1,2}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "logicalHeightOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "auto",
appliesto: "positionedElements",
computed: "sameAsBoxOffsets",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/inset-block"
},
"inset-block-end": {
syntax: "<'top'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "logicalHeightOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "auto",
appliesto: "positionedElements",
computed: "sameAsBoxOffsets",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/inset-block-end"
},
"inset-block-start": {
syntax: "<'top'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "logicalHeightOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "auto",
appliesto: "positionedElements",
computed: "sameAsBoxOffsets",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/inset-block-start"
},
"inset-inline": {
syntax: "<'top'>{1,2}",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "auto",
appliesto: "positionedElements",
computed: "sameAsBoxOffsets",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/inset-inline"
},
"inset-inline-end": {
syntax: "<'top'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "auto",
appliesto: "positionedElements",
computed: "sameAsBoxOffsets",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/inset-inline-end"
},
"inset-inline-start": {
syntax: "<'top'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "auto",
appliesto: "positionedElements",
computed: "sameAsBoxOffsets",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/inset-inline-start"
},
isolation: isolation,
"justify-content": {
syntax: "normal | <content-distribution> | <overflow-position>? [ <content-position> | left | right ]",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Alignment"
],
initial: "normal",
appliesto: "flexContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/justify-content"
},
"justify-items": {
syntax: "normal | stretch | <baseline-position> | <overflow-position>? [ <self-position> | left | right ] | legacy | legacy && [ left | right | center ]",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Alignment"
],
initial: "legacy",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/justify-items"
},
"justify-self": {
syntax: "auto | normal | stretch | <baseline-position> | <overflow-position>? [ <self-position> | left | right ]",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Alignment"
],
initial: "auto",
appliesto: "blockLevelBoxesAndAbsolutelyPositionedBoxesAndGridItems",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/justify-self"
},
"justify-tracks": {
syntax: "[ normal | <content-distribution> | <overflow-position>? [ <content-position> | left | right ] ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: "normal",
appliesto: "gridContainersWithMasonryLayoutInTheirInlineAxis",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/justify-tracks"
},
left: left,
"letter-spacing": {
syntax: "normal | <length>",
media: "visual",
inherited: true,
animationType: "length",
percentages: "no",
groups: [
"CSS Text"
],
initial: "normal",
appliesto: "allElements",
computed: "optimumValueOfAbsoluteLengthOrNormal",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/letter-spacing"
},
"line-break": {
syntax: "auto | loose | normal | strict | anywhere",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/line-break"
},
"line-clamp": {
syntax: "none | <integer>",
media: "visual",
inherited: false,
animationType: "integer",
percentages: "no",
groups: [
"CSS Overflow"
],
initial: "none",
appliesto: "blockContainersExceptMultiColumnContainers",
computed: "asSpecified",
order: "perGrammar",
status: "experimental"
},
"line-height": {
syntax: "normal | <number> | <length> | <percentage>",
media: "visual",
inherited: true,
animationType: "numberOrLength",
percentages: "referToElementFontSize",
groups: [
"CSS Fonts"
],
initial: "normal",
appliesto: "allElements",
computed: "absoluteLengthOrAsSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/line-height"
},
"line-height-step": {
syntax: "<length>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Fonts"
],
initial: "0",
appliesto: "blockContainers",
computed: "absoluteLength",
order: "perGrammar",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/line-height-step"
},
"list-style": {
syntax: "<'list-style-type'> || <'list-style-position'> || <'list-style-image'>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Lists and Counters"
],
initial: [
"list-style-type",
"list-style-position",
"list-style-image"
],
appliesto: "listItems",
computed: [
"list-style-image",
"list-style-position",
"list-style-type"
],
order: "orderOfAppearance",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/list-style"
},
"list-style-image": {
syntax: "<image> | none",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Lists and Counters"
],
initial: "none",
appliesto: "listItems",
computed: "theKeywordListStyleImageNoneOrComputedValue",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/list-style-image"
},
"list-style-position": {
syntax: "inside | outside",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Lists and Counters"
],
initial: "outside",
appliesto: "listItems",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/list-style-position"
},
"list-style-type": {
syntax: "<counter-style> | <string> | none",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Lists and Counters"
],
initial: "disc",
appliesto: "listItems",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/list-style-type"
},
margin: margin,
"margin-block": {
syntax: "<'margin-left'>{1,2}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "dependsOnLayoutModel",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "sameAsMargin",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-block"
},
"margin-block-end": {
syntax: "<'margin-left'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "dependsOnLayoutModel",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "sameAsMargin",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-block-end"
},
"margin-block-start": {
syntax: "<'margin-left'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "dependsOnLayoutModel",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "sameAsMargin",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-block-start"
},
"margin-bottom": {
syntax: "<length> | <percentage> | auto",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "0",
appliesto: "allElementsExceptTableDisplayTypes",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-bottom"
},
"margin-inline": {
syntax: "<'margin-left'>{1,2}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "dependsOnLayoutModel",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "sameAsMargin",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-inline"
},
"margin-inline-end": {
syntax: "<'margin-left'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "dependsOnLayoutModel",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "sameAsMargin",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-inline-end"
},
"margin-inline-start": {
syntax: "<'margin-left'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "dependsOnLayoutModel",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "sameAsMargin",
computed: "lengthAbsolutePercentageAsSpecifiedOtherwiseAuto",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-inline-start"
},
"margin-left": {
syntax: "<length> | <percentage> | auto",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "0",
appliesto: "allElementsExceptTableDisplayTypes",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-left"
},
"margin-right": {
syntax: "<length> | <percentage> | auto",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "0",
appliesto: "allElementsExceptTableDisplayTypes",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-right"
},
"margin-top": {
syntax: "<length> | <percentage> | auto",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "0",
appliesto: "allElementsExceptTableDisplayTypes",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-top"
},
"margin-trim": {
syntax: "none | in-flow | all",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Model"
],
initial: "none",
appliesto: "blockContainersAndMultiColumnContainers",
computed: "asSpecified",
order: "perGrammar",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/margin-trim"
},
mask: mask,
"mask-border": {
syntax: "<'mask-border-source'> || <'mask-border-slice'> [ / <'mask-border-width'>? [ / <'mask-border-outset'> ]? ]? || <'mask-border-repeat'> || <'mask-border-mode'>",
media: "visual",
inherited: false,
animationType: [
"mask-border-mode",
"mask-border-outset",
"mask-border-repeat",
"mask-border-slice",
"mask-border-source",
"mask-border-width"
],
percentages: [
"mask-border-slice",
"mask-border-width"
],
groups: [
"CSS Masking"
],
initial: [
"mask-border-mode",
"mask-border-outset",
"mask-border-repeat",
"mask-border-slice",
"mask-border-source",
"mask-border-width"
],
appliesto: "allElementsSVGContainerElements",
computed: [
"mask-border-mode",
"mask-border-outset",
"mask-border-repeat",
"mask-border-slice",
"mask-border-source",
"mask-border-width"
],
order: "perGrammar",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-border"
},
"mask-border-mode": {
syntax: "luminance | alpha",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "alpha",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-border-mode"
},
"mask-border-outset": {
syntax: "[ <length> | <number> ]{1,4}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "0",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-border-outset"
},
"mask-border-repeat": {
syntax: "[ stretch | repeat | round | space ]{1,2}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "stretch",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-border-repeat"
},
"mask-border-slice": {
syntax: "<number-percentage>{1,4} fill?",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "referToSizeOfMaskBorderImage",
groups: [
"CSS Masking"
],
initial: "0",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-border-slice"
},
"mask-border-source": {
syntax: "none | <image>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "none",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecifiedURLsAbsolute",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-border-source"
},
"mask-border-width": {
syntax: "[ <length-percentage> | <number> | auto ]{1,4}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "relativeToMaskBorderImageArea",
groups: [
"CSS Masking"
],
initial: "auto",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-border-width"
},
"mask-clip": {
syntax: "[ <geometry-box> | no-clip ]#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "border-box",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-clip"
},
"mask-composite": {
syntax: "<compositing-operator>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "add",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-composite"
},
"mask-image": {
syntax: "<mask-reference>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "none",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecifiedURLsAbsolute",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-image"
},
"mask-mode": {
syntax: "<masking-mode>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "match-source",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-mode"
},
"mask-origin": {
syntax: "<geometry-box>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "border-box",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-origin"
},
"mask-position": {
syntax: "<position>#",
media: "visual",
inherited: false,
animationType: "repeatableListOfSimpleListOfLpc",
percentages: "referToSizeOfMaskPaintingArea",
groups: [
"CSS Masking"
],
initial: "center",
appliesto: "allElementsSVGContainerElements",
computed: "consistsOfTwoKeywordsForOriginAndOffsets",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-position"
},
"mask-repeat": {
syntax: "<repeat-style>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "no-repeat",
appliesto: "allElementsSVGContainerElements",
computed: "consistsOfTwoDimensionKeywords",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-repeat"
},
"mask-size": {
syntax: "<bg-size>#",
media: "visual",
inherited: false,
animationType: "repeatableListOfSimpleListOfLpc",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "auto",
appliesto: "allElementsSVGContainerElements",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-size"
},
"mask-type": {
syntax: "luminance | alpha",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Masking"
],
initial: "luminance",
appliesto: "maskElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mask-type"
},
"masonry-auto-flow": {
syntax: "[ pack | next ] || [ definite-first | ordered ]",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Grid Layout"
],
initial: "pack",
appliesto: "gridContainersWithMasonryLayout",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/masonry-auto-flow"
},
"math-style": {
syntax: "normal | compact",
media: "visual",
inherited: true,
animationType: "notAnimatable",
percentages: "no",
groups: [
"MathML"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/math-style"
},
"max-block-size": {
syntax: "<'max-width'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "blockSizeOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "none",
appliesto: "sameAsWidthAndHeight",
computed: "sameAsMaxWidthAndMaxHeight",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/max-block-size"
},
"max-height": {
syntax: "none | <length-percentage> | min-content | max-content | fit-content | fit-content(<length-percentage>)",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "regardingHeightOfGeneratedBoxContainingBlockPercentagesNone",
groups: [
"CSS Box Model"
],
initial: "none",
appliesto: "allElementsButNonReplacedAndTableColumns",
computed: "percentageAsSpecifiedAbsoluteLengthOrNone",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/max-height"
},
"max-inline-size": {
syntax: "<'max-width'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "inlineSizeOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "none",
appliesto: "sameAsWidthAndHeight",
computed: "sameAsMaxWidthAndMaxHeight",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/max-inline-size"
},
"max-lines": {
syntax: "none | <integer>",
media: "visual",
inherited: false,
animationType: "integer",
percentages: "no",
groups: [
"CSS Overflow"
],
initial: "none",
appliesto: "blockContainersExceptMultiColumnContainers",
computed: "asSpecified",
order: "perGrammar",
status: "experimental"
},
"max-width": {
syntax: "none | <length-percentage> | min-content | max-content | fit-content | fit-content(<length-percentage>)",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "none",
appliesto: "allElementsButNonReplacedAndTableRows",
computed: "percentageAsSpecifiedAbsoluteLengthOrNone",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/max-width"
},
"min-block-size": {
syntax: "<'min-width'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "blockSizeOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "sameAsWidthAndHeight",
computed: "sameAsMinWidthAndMinHeight",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/min-block-size"
},
"min-height": {
syntax: "auto | <length> | <percentage> | min-content | max-content | fit-content | fit-content(<length-percentage>)",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "regardingHeightOfGeneratedBoxContainingBlockPercentages0",
groups: [
"CSS Box Model"
],
initial: "auto",
appliesto: "allElementsButNonReplacedAndTableColumns",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/min-height"
},
"min-inline-size": {
syntax: "<'min-width'>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "inlineSizeOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "sameAsWidthAndHeight",
computed: "sameAsMinWidthAndMinHeight",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/min-inline-size"
},
"min-width": {
syntax: "auto | <length> | <percentage> | min-content | max-content | fit-content | fit-content(<length-percentage>)",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "auto",
appliesto: "allElementsButNonReplacedAndTableRows",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/min-width"
},
"mix-blend-mode": {
syntax: "<blend-mode> | plus-lighter",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Compositing and Blending"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/mix-blend-mode"
},
"object-fit": {
syntax: "fill | contain | cover | none | scale-down",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Images"
],
initial: "fill",
appliesto: "replacedElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/object-fit"
},
"object-position": {
syntax: "<position>",
media: "visual",
inherited: true,
animationType: "repeatableListOfSimpleListOfLpc",
percentages: "referToWidthAndHeightOfElement",
groups: [
"CSS Images"
],
initial: "50% 50%",
appliesto: "replacedElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/object-position"
},
offset: offset,
"offset-anchor": {
syntax: "auto | <position>",
media: "visual",
inherited: false,
animationType: "position",
percentages: "relativeToWidthAndHeight",
groups: [
"CSS Motion Path"
],
initial: "auto",
appliesto: "transformableElements",
computed: "forLengthAbsoluteValueOtherwisePercentage",
order: "perGrammar",
status: "standard"
},
"offset-distance": {
syntax: "<length-percentage>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToTotalPathLength",
groups: [
"CSS Motion Path"
],
initial: "0",
appliesto: "transformableElements",
computed: "forLengthAbsoluteValueOtherwisePercentage",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/offset-distance"
},
"offset-path": {
syntax: "none | ray( [ <angle> && <size> && contain? ] ) | <path()> | <url> | [ <basic-shape> || <geometry-box> ]",
media: "visual",
inherited: false,
animationType: "angleOrBasicShapeOrPath",
percentages: "no",
groups: [
"CSS Motion Path"
],
initial: "none",
appliesto: "transformableElements",
computed: "asSpecified",
order: "perGrammar",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/offset-path"
},
"offset-position": {
syntax: "auto | <position>",
media: "visual",
inherited: false,
animationType: "position",
percentages: "referToSizeOfContainingBlock",
groups: [
"CSS Motion Path"
],
initial: "auto",
appliesto: "transformableElements",
computed: "forLengthAbsoluteValueOtherwisePercentage",
order: "perGrammar",
status: "experimental"
},
"offset-rotate": {
syntax: "[ auto | reverse ] || <angle>",
media: "visual",
inherited: false,
animationType: "angleOrBasicShapeOrPath",
percentages: "no",
groups: [
"CSS Motion Path"
],
initial: "auto",
appliesto: "transformableElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/offset-rotate"
},
opacity: opacity,
order: order,
orphans: orphans,
outline: outline,
"outline-color": {
syntax: "<color> | invert",
media: [
"visual",
"interactive"
],
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "invertOrCurrentColor",
appliesto: "allElements",
computed: "invertForTranslucentColorRGBAOtherwiseRGB",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/outline-color"
},
"outline-offset": {
syntax: "<length>",
media: [
"visual",
"interactive"
],
inherited: false,
animationType: "length",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/outline-offset"
},
"outline-style": {
syntax: "auto | <'border-style'>",
media: [
"visual",
"interactive"
],
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/outline-style"
},
"outline-width": {
syntax: "<line-width>",
media: [
"visual",
"interactive"
],
inherited: false,
animationType: "length",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "medium",
appliesto: "allElements",
computed: "absoluteLength0ForNone",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/outline-width"
},
overflow: overflow,
"overflow-anchor": {
syntax: "auto | none",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Scroll Anchoring"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard"
},
"overflow-block": {
syntax: "visible | hidden | clip | scroll | auto",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Overflow"
],
initial: "auto",
appliesto: "blockContainersFlexContainersGridContainers",
computed: "asSpecifiedButVisibleOrClipReplacedToAutoOrHiddenIfOtherValueDifferent",
order: "perGrammar",
status: "standard"
},
"overflow-clip-box": {
syntax: "padding-box | content-box",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Mozilla Extensions"
],
initial: "padding-box",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "nonstandard",
mdn_url: "https://developer.mozilla.org/docs/Mozilla/CSS/overflow-clip-box"
},
"overflow-clip-margin": {
syntax: "<visual-box> || <length [0,∞]>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Overflow"
],
initial: "0px",
appliesto: "allElements",
computed: "theComputedLength",
order: "perGrammar",
status: "standard"
},
"overflow-inline": {
syntax: "visible | hidden | clip | scroll | auto",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Overflow"
],
initial: "auto",
appliesto: "blockContainersFlexContainersGridContainers",
computed: "asSpecifiedButVisibleOrClipReplacedToAutoOrHiddenIfOtherValueDifferent",
order: "perGrammar",
status: "standard"
},
"overflow-wrap": {
syntax: "normal | break-word | anywhere",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "normal",
appliesto: "nonReplacedInlineElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/overflow-wrap"
},
"overflow-x": {
syntax: "visible | hidden | clip | scroll | auto",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Overflow"
],
initial: "visible",
appliesto: "blockContainersFlexContainersGridContainers",
computed: "asSpecifiedButVisibleOrClipReplacedToAutoOrHiddenIfOtherValueDifferent",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/overflow-x"
},
"overflow-y": {
syntax: "visible | hidden | clip | scroll | auto",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Overflow"
],
initial: "visible",
appliesto: "blockContainersFlexContainersGridContainers",
computed: "asSpecifiedButVisibleOrClipReplacedToAutoOrHiddenIfOtherValueDifferent",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/overflow-y"
},
"overscroll-behavior": {
syntax: "[ contain | none | auto ]{1,2}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Model"
],
initial: "auto",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: [
"overscroll-behavior-x",
"overscroll-behavior-y"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/overscroll-behavior"
},
"overscroll-behavior-block": {
syntax: "contain | none | auto",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Model"
],
initial: "auto",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/overscroll-behavior-block"
},
"overscroll-behavior-inline": {
syntax: "contain | none | auto",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Model"
],
initial: "auto",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/overscroll-behavior-inline"
},
"overscroll-behavior-x": {
syntax: "contain | none | auto",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Model"
],
initial: "auto",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/overscroll-behavior-x"
},
"overscroll-behavior-y": {
syntax: "contain | none | auto",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Model"
],
initial: "auto",
appliesto: "nonReplacedBlockAndInlineBlockElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/overscroll-behavior-y"
},
padding: padding,
"padding-block": {
syntax: "<'padding-left'>{1,2}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "allElements",
computed: "asLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding-block"
},
"padding-block-end": {
syntax: "<'padding-left'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "allElements",
computed: "asLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding-block-end"
},
"padding-block-start": {
syntax: "<'padding-left'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "allElements",
computed: "asLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding-block-start"
},
"padding-bottom": {
syntax: "<length> | <percentage>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "0",
appliesto: "allElementsExceptInternalTableDisplayTypes",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding-bottom"
},
"padding-inline": {
syntax: "<'padding-left'>{1,2}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "allElements",
computed: "asLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding-inline"
},
"padding-inline-end": {
syntax: "<'padding-left'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "allElements",
computed: "asLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding-inline-end"
},
"padding-inline-start": {
syntax: "<'padding-left'>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "logicalWidthOfContainingBlock",
groups: [
"CSS Logical Properties"
],
initial: "0",
appliesto: "allElements",
computed: "asLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding-inline-start"
},
"padding-left": {
syntax: "<length> | <percentage>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "0",
appliesto: "allElementsExceptInternalTableDisplayTypes",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding-left"
},
"padding-right": {
syntax: "<length> | <percentage>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "0",
appliesto: "allElementsExceptInternalTableDisplayTypes",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding-right"
},
"padding-top": {
syntax: "<length> | <percentage>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Box Model"
],
initial: "0",
appliesto: "allElementsExceptInternalTableDisplayTypes",
computed: "percentageAsSpecifiedOrAbsoluteLength",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/padding-top"
},
"page-break-after": {
syntax: "auto | always | avoid | left | right | recto | verso",
media: [
"visual",
"paged"
],
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Pages"
],
initial: "auto",
appliesto: "blockElementsInNormalFlow",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/page-break-after"
},
"page-break-before": {
syntax: "auto | always | avoid | left | right | recto | verso",
media: [
"visual",
"paged"
],
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Pages"
],
initial: "auto",
appliesto: "blockElementsInNormalFlow",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/page-break-before"
},
"page-break-inside": {
syntax: "auto | avoid",
media: [
"visual",
"paged"
],
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Pages"
],
initial: "auto",
appliesto: "blockElementsInNormalFlow",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/page-break-inside"
},
"paint-order": {
syntax: "normal | [ fill || stroke || markers ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "normal",
appliesto: "textElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/paint-order"
},
perspective: perspective,
"perspective-origin": {
syntax: "<position>",
media: "visual",
inherited: false,
animationType: "simpleListOfLpc",
percentages: "referToSizeOfBoundingBox",
groups: [
"CSS Transforms"
],
initial: "50% 50%",
appliesto: "transformableElements",
computed: "forLengthAbsoluteValueOtherwisePercentage",
order: "oneOrTwoValuesLengthAbsoluteKeywordsPercentages",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/perspective-origin"
},
"place-content": {
syntax: "<'align-content'> <'justify-content'>?",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Alignment"
],
initial: "normal",
appliesto: "multilineFlexContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/place-content"
},
"place-items": {
syntax: "<'align-items'> <'justify-items'>?",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Alignment"
],
initial: [
"align-items",
"justify-items"
],
appliesto: "allElements",
computed: [
"align-items",
"justify-items"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/place-items"
},
"place-self": {
syntax: "<'align-self'> <'justify-self'>?",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Box Alignment"
],
initial: [
"align-self",
"justify-self"
],
appliesto: "blockLevelBoxesAndAbsolutelyPositionedBoxesAndGridItems",
computed: [
"align-self",
"justify-self"
],
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/place-self"
},
"pointer-events": {
syntax: "auto | none | visiblePainted | visibleFill | visibleStroke | visible | painted | fill | stroke | all | inherit",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/pointer-events"
},
position: position$1,
quotes: quotes,
resize: resize,
right: right,
rotate: rotate,
"row-gap": {
syntax: "normal | <length-percentage>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToDimensionOfContentArea",
groups: [
"CSS Box Alignment"
],
initial: "normal",
appliesto: "multiColumnElementsFlexContainersGridContainers",
computed: "asSpecifiedWithLengthsAbsoluteAndNormalComputingToZeroExceptMultiColumn",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/row-gap"
},
"ruby-align": {
syntax: "start | center | space-between | space-around",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Ruby"
],
initial: "space-around",
appliesto: "rubyBasesAnnotationsBaseAnnotationContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/ruby-align"
},
"ruby-merge": {
syntax: "separate | collapse | auto",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Ruby"
],
initial: "separate",
appliesto: "rubyAnnotationsContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental"
},
"ruby-position": {
syntax: "[ alternate || [ over | under ] ] | inter-character",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Ruby"
],
initial: "alternate",
appliesto: "rubyAnnotationsContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/ruby-position"
},
scale: scale,
"scrollbar-color": {
syntax: "auto | <color>{2}",
media: "visual",
inherited: true,
animationType: "color",
percentages: "no",
groups: [
"CSS Scrollbars"
],
initial: "auto",
appliesto: "scrollingBoxes",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scrollbar-color"
},
"scrollbar-gutter": {
syntax: "auto | stable && both-edges?",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Overflow"
],
initial: "auto",
appliesto: "scrollingBoxes",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scrollbar-gutter"
},
"scrollbar-width": {
syntax: "auto | thin | none",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Scrollbars"
],
initial: "auto",
appliesto: "scrollingBoxes",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scrollbar-width"
},
"scroll-behavior": {
syntax: "auto | smooth",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSSOM View"
],
initial: "auto",
appliesto: "scrollingBoxes",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-behavior"
},
"scroll-margin": {
syntax: "<length>{1,4}",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin"
},
"scroll-margin-block": {
syntax: "<length>{1,2}",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin-block"
},
"scroll-margin-block-start": {
syntax: "<length>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin-block-start"
},
"scroll-margin-block-end": {
syntax: "<length>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin-block-end"
},
"scroll-margin-bottom": {
syntax: "<length>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin-bottom"
},
"scroll-margin-inline": {
syntax: "<length>{1,2}",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin-inline"
},
"scroll-margin-inline-start": {
syntax: "<length>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin-inline-start"
},
"scroll-margin-inline-end": {
syntax: "<length>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin-inline-end"
},
"scroll-margin-left": {
syntax: "<length>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin-left"
},
"scroll-margin-right": {
syntax: "<length>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin-right"
},
"scroll-margin-top": {
syntax: "<length>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "0",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-margin-top"
},
"scroll-padding": {
syntax: "[ auto | <length-percentage> ]{1,4}",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: "auto",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding"
},
"scroll-padding-block": {
syntax: "[ auto | <length-percentage> ]{1,2}",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: "auto",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding-block"
},
"scroll-padding-block-start": {
syntax: "auto | <length-percentage>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: "auto",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding-block-start"
},
"scroll-padding-block-end": {
syntax: "auto | <length-percentage>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: "auto",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding-block-end"
},
"scroll-padding-bottom": {
syntax: "auto | <length-percentage>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: "auto",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding-bottom"
},
"scroll-padding-inline": {
syntax: "[ auto | <length-percentage> ]{1,2}",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: "auto",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding-inline"
},
"scroll-padding-inline-start": {
syntax: "auto | <length-percentage>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: "auto",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding-inline-start"
},
"scroll-padding-inline-end": {
syntax: "auto | <length-percentage>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: "auto",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding-inline-end"
},
"scroll-padding-left": {
syntax: "auto | <length-percentage>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: "auto",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding-left"
},
"scroll-padding-right": {
syntax: "auto | <length-percentage>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: "auto",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding-right"
},
"scroll-padding-top": {
syntax: "auto | <length-percentage>",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "relativeToTheScrollContainersScrollport",
groups: [
"CSS Scroll Snap"
],
initial: "auto",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-padding-top"
},
"scroll-snap-align": {
syntax: "[ none | start | end | center ]{1,2}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-snap-align"
},
"scroll-snap-coordinate": {
syntax: "none | <position>#",
media: "interactive",
inherited: false,
animationType: "position",
percentages: "referToBorderBox",
groups: [
"CSS Scroll Snap"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-snap-coordinate"
},
"scroll-snap-destination": {
syntax: "<position>",
media: "interactive",
inherited: false,
animationType: "position",
percentages: "relativeToScrollContainerPaddingBoxAxis",
groups: [
"CSS Scroll Snap"
],
initial: "0px 0px",
appliesto: "scrollContainers",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-snap-destination"
},
"scroll-snap-points-x": {
syntax: "none | repeat( <length-percentage> )",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "relativeToScrollContainerPaddingBoxAxis",
groups: [
"CSS Scroll Snap"
],
initial: "none",
appliesto: "scrollContainers",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-snap-points-x"
},
"scroll-snap-points-y": {
syntax: "none | repeat( <length-percentage> )",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "relativeToScrollContainerPaddingBoxAxis",
groups: [
"CSS Scroll Snap"
],
initial: "none",
appliesto: "scrollContainers",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-snap-points-y"
},
"scroll-snap-stop": {
syntax: "normal | always",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-snap-stop"
},
"scroll-snap-type": {
syntax: "none | [ x | y | block | inline | both ] [ mandatory | proximity ]?",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-snap-type"
},
"scroll-snap-type-x": {
syntax: "none | mandatory | proximity",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "none",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-snap-type-x"
},
"scroll-snap-type-y": {
syntax: "none | mandatory | proximity",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Scroll Snap"
],
initial: "none",
appliesto: "scrollContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "obsolete",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/scroll-snap-type-y"
},
"shape-image-threshold": {
syntax: "<alpha-value>",
media: "visual",
inherited: false,
animationType: "number",
percentages: "no",
groups: [
"CSS Shapes"
],
initial: "0.0",
appliesto: "floats",
computed: "specifiedValueNumberClipped0To1",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/shape-image-threshold"
},
"shape-margin": {
syntax: "<length-percentage>",
media: "visual",
inherited: false,
animationType: "lpc",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Shapes"
],
initial: "0",
appliesto: "floats",
computed: "asSpecifiedRelativeToAbsoluteLengths",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/shape-margin"
},
"shape-outside": {
syntax: "none | [ <shape-box> || <basic-shape> ] | <image>",
media: "visual",
inherited: false,
animationType: "basicShapeOtherwiseNo",
percentages: "no",
groups: [
"CSS Shapes"
],
initial: "none",
appliesto: "floats",
computed: "asDefinedForBasicShapeWithAbsoluteURIOtherwiseAsSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/shape-outside"
},
"tab-size": {
syntax: "<integer> | <length>",
media: "visual",
inherited: true,
animationType: "length",
percentages: "no",
groups: [
"CSS Text"
],
initial: "8",
appliesto: "blockContainers",
computed: "specifiedIntegerOrAbsoluteLength",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/tab-size"
},
"table-layout": {
syntax: "auto | fixed",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Table"
],
initial: "auto",
appliesto: "tableElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/table-layout"
},
"text-align": {
syntax: "start | end | left | right | center | justify | match-parent",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "startOrNamelessValueIfLTRRightIfRTL",
appliesto: "blockContainers",
computed: "asSpecifiedExceptMatchParent",
order: "orderOfAppearance",
alsoAppliesTo: [
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-align"
},
"text-align-last": {
syntax: "auto | start | end | left | right | center | justify",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "auto",
appliesto: "blockContainers",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-align-last"
},
"text-combine-upright": {
syntax: "none | all | [ digits <integer>? ]",
media: "visual",
inherited: true,
animationType: "notAnimatable",
percentages: "no",
groups: [
"CSS Writing Modes"
],
initial: "none",
appliesto: "nonReplacedInlineElements",
computed: "keywordPlusIntegerIfDigits",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-combine-upright"
},
"text-decoration": {
syntax: "<'text-decoration-line'> || <'text-decoration-style'> || <'text-decoration-color'> || <'text-decoration-thickness'>",
media: "visual",
inherited: false,
animationType: [
"text-decoration-color",
"text-decoration-style",
"text-decoration-line",
"text-decoration-thickness"
],
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: [
"text-decoration-color",
"text-decoration-style",
"text-decoration-line"
],
appliesto: "allElements",
computed: [
"text-decoration-line",
"text-decoration-style",
"text-decoration-color",
"text-decoration-thickness"
],
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-decoration"
},
"text-decoration-color": {
syntax: "<color>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-decoration-color"
},
"text-decoration-line": {
syntax: "none | [ underline || overline || line-through || blink ] | spelling-error | grammar-error",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-decoration-line"
},
"text-decoration-skip": {
syntax: "none | [ objects || [ spaces | [ leading-spaces || trailing-spaces ] ] || edges || box-decoration ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: "objects",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-decoration-skip"
},
"text-decoration-skip-ink": {
syntax: "auto | all | none",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-decoration-skip-ink"
},
"text-decoration-style": {
syntax: "solid | double | dotted | dashed | wavy",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: "solid",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-decoration-style"
},
"text-decoration-thickness": {
syntax: "auto | from-font | <length> | <percentage> ",
media: "visual",
inherited: false,
animationType: "byComputedValueType",
percentages: "referToElementFontSize",
groups: [
"CSS Text Decoration"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-decoration-thickness"
},
"text-emphasis": {
syntax: "<'text-emphasis-style'> || <'text-emphasis-color'>",
media: "visual",
inherited: false,
animationType: [
"text-emphasis-color",
"text-emphasis-style"
],
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: [
"text-emphasis-style",
"text-emphasis-color"
],
appliesto: "allElements",
computed: [
"text-emphasis-style",
"text-emphasis-color"
],
order: "orderOfAppearance",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-emphasis"
},
"text-emphasis-color": {
syntax: "<color>",
media: "visual",
inherited: false,
animationType: "color",
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: "currentcolor",
appliesto: "allElements",
computed: "computedColor",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-emphasis-color"
},
"text-emphasis-position": {
syntax: "[ over | under ] && [ right | left ]",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: "over right",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-emphasis-position"
},
"text-emphasis-style": {
syntax: "none | [ [ filled | open ] || [ dot | circle | double-circle | triangle | sesame ] ] | <string>",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-emphasis-style"
},
"text-indent": {
syntax: "<length-percentage> && hanging? && each-line?",
media: "visual",
inherited: true,
animationType: "lpc",
percentages: "referToWidthOfContainingBlock",
groups: [
"CSS Text"
],
initial: "0",
appliesto: "blockContainers",
computed: "percentageOrAbsoluteLengthPlusKeywords",
order: "lengthOrPercentageBeforeKeywords",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-indent"
},
"text-justify": {
syntax: "auto | inter-character | inter-word | none",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "auto",
appliesto: "inlineLevelAndTableCellElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-justify"
},
"text-orientation": {
syntax: "mixed | upright | sideways",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Writing Modes"
],
initial: "mixed",
appliesto: "allElementsExceptTableRowGroupsRowsColumnGroupsAndColumns",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-orientation"
},
"text-overflow": {
syntax: "[ clip | ellipsis | <string> ]{1,2}",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "clip",
appliesto: "blockContainerElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-overflow"
},
"text-rendering": {
syntax: "auto | optimizeSpeed | optimizeLegibility | geometricPrecision",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Miscellaneous"
],
initial: "auto",
appliesto: "textElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-rendering"
},
"text-shadow": {
syntax: "none | <shadow-t>#",
media: "visual",
inherited: true,
animationType: "shadowList",
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: "none",
appliesto: "allElements",
computed: "colorPlusThreeAbsoluteLengths",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-shadow"
},
"text-size-adjust": {
syntax: "none | auto | <percentage>",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "referToSizeOfFont",
groups: [
"CSS Text"
],
initial: "autoForSmartphoneBrowsersSupportingInflation",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "experimental",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-size-adjust"
},
"text-transform": {
syntax: "none | capitalize | uppercase | lowercase | full-width | full-size-kana",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "none",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-transform"
},
"text-underline-offset": {
syntax: "auto | <length> | <percentage> ",
media: "visual",
inherited: true,
animationType: "byComputedValueType",
percentages: "referToElementFontSize",
groups: [
"CSS Text Decoration"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-underline-offset"
},
"text-underline-position": {
syntax: "auto | from-font | [ under || [ left | right ] ]",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text Decoration"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "orderOfAppearance",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/text-underline-position"
},
top: top,
"touch-action": {
syntax: "auto | none | [ [ pan-x | pan-left | pan-right ] || [ pan-y | pan-up | pan-down ] || pinch-zoom ] | manipulation",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"Pointer Events"
],
initial: "auto",
appliesto: "allElementsExceptNonReplacedInlineElementsTableRowsColumnsRowColumnGroups",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/touch-action"
},
transform: transform,
"transform-box": {
syntax: "content-box | border-box | fill-box | stroke-box | view-box",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Transforms"
],
initial: "view-box",
appliesto: "transformableElements",
computed: "asSpecified",
order: "perGrammar",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/transform-box"
},
"transform-origin": {
syntax: "[ <length-percentage> | left | center | right | top | bottom ] | [ [ <length-percentage> | left | center | right ] && [ <length-percentage> | top | center | bottom ] ] <length>?",
media: "visual",
inherited: false,
animationType: "simpleListOfLpc",
percentages: "referToSizeOfBoundingBox",
groups: [
"CSS Transforms"
],
initial: "50% 50% 0",
appliesto: "transformableElements",
computed: "forLengthAbsoluteValueOtherwisePercentage",
order: "oneOrTwoValuesLengthAbsoluteKeywordsPercentages",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/transform-origin"
},
"transform-style": {
syntax: "flat | preserve-3d",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Transforms"
],
initial: "flat",
appliesto: "transformableElements",
computed: "asSpecified",
order: "uniqueOrder",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/transform-style"
},
transition: transition,
"transition-delay": {
syntax: "<time>#",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Transitions"
],
initial: "0s",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/transition-delay"
},
"transition-duration": {
syntax: "<time>#",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Transitions"
],
initial: "0s",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/transition-duration"
},
"transition-property": {
syntax: "none | <single-transition-property>#",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Transitions"
],
initial: "all",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/transition-property"
},
"transition-timing-function": {
syntax: "<easing-function>#",
media: "interactive",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Transitions"
],
initial: "ease",
appliesto: "allElementsAndPseudos",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/transition-timing-function"
},
translate: translate,
"unicode-bidi": {
syntax: "normal | embed | isolate | bidi-override | isolate-override | plaintext",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Writing Modes"
],
initial: "normal",
appliesto: "allElementsSomeValuesNoEffectOnNonInlineElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/unicode-bidi"
},
"user-select": {
syntax: "auto | text | none | contain | all",
media: "visual",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Basic User Interface"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/user-select"
},
"vertical-align": {
syntax: "baseline | sub | super | text-top | text-bottom | middle | top | bottom | <percentage> | <length>",
media: "visual",
inherited: false,
animationType: "length",
percentages: "referToLineHeight",
groups: [
"CSS Table"
],
initial: "baseline",
appliesto: "inlineLevelAndTableCellElements",
computed: "absoluteLengthOrKeyword",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/vertical-align"
},
visibility: visibility,
"white-space": {
syntax: "normal | pre | nowrap | pre-wrap | pre-line | break-spaces",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/white-space"
},
widows: widows,
width: width,
"will-change": {
syntax: "auto | <animateable-feature>#",
media: "all",
inherited: false,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Will Change"
],
initial: "auto",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/will-change"
},
"word-break": {
syntax: "normal | break-all | keep-all | break-word",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "normal",
appliesto: "allElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/word-break"
},
"word-spacing": {
syntax: "normal | <length>",
media: "visual",
inherited: true,
animationType: "length",
percentages: "referToWidthOfAffectedGlyph",
groups: [
"CSS Text"
],
initial: "normal",
appliesto: "allElements",
computed: "optimumMinAndMaxValueOfAbsoluteLengthPercentageOrNormal",
order: "uniqueOrder",
alsoAppliesTo: [
"::first-letter",
"::first-line",
"::placeholder"
],
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/word-spacing"
},
"word-wrap": {
syntax: "normal | break-word",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Text"
],
initial: "normal",
appliesto: "nonReplacedInlineElements",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/overflow-wrap"
},
"writing-mode": {
syntax: "horizontal-tb | vertical-rl | vertical-lr | sideways-rl | sideways-lr",
media: "visual",
inherited: true,
animationType: "discrete",
percentages: "no",
groups: [
"CSS Writing Modes"
],
initial: "horizontal-tb",
appliesto: "allElementsExceptTableRowColumnGroupsTableRowsColumns",
computed: "asSpecified",
order: "uniqueOrder",
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/writing-mode"
},
"z-index": {
syntax: "auto | <integer>",
media: "visual",
inherited: false,
animationType: "integer",
percentages: "no",
groups: [
"CSS Positioning"
],
initial: "auto",
appliesto: "positionedElements",
computed: "asSpecified",
order: "uniqueOrder",
stacking: true,
status: "standard",
mdn_url: "https://developer.mozilla.org/docs/Web/CSS/z-index"
},
zoom: zoom
};
const attachment = {
syntax: "scroll | fixed | local"
};
const box = {
syntax: "border-box | padding-box | content-box"
};
const color$2 = {
syntax: "<rgb()> | <rgba()> | <hsl()> | <hsla()> | <hwb()> | <lab()> | <lch()> | <hex-color> | <named-color> | currentcolor | <deprecated-system-color>"
};
const combinator = {
syntax: "'>' | '+' | '~' | [ '||' ]"
};
const counter = {
syntax: "<counter()> | <counters()>"
};
const gradient = {
syntax: "<linear-gradient()> | <repeating-linear-gradient()> | <radial-gradient()> | <repeating-radial-gradient()> | <conic-gradient()> | <repeating-conic-gradient()>"
};
const hue = {
syntax: "<number> | <angle>"
};
const image = {
syntax: "<url> | <image()> | <image-set()> | <element()> | <paint()> | <cross-fade()> | <gradient>"
};
const nth$1 = {
syntax: "<an-plus-b> | even | odd"
};
const 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> ] ]"
};
const quote = {
syntax: "open-quote | close-quote | no-open-quote | no-close-quote"
};
const shadow = {
syntax: "inset? && <length>{2,4} && <color>?"
};
const shape = {
syntax: "rect(<top>, <right>, <bottom>, <left>)"
};
const size = {
syntax: "closest-side | farthest-side | closest-corner | farthest-corner | <length> | <length-percentage>{2}"
};
const symbol = {
syntax: "<string> | <image> | <custom-ident>"
};
const target = {
syntax: "<target-counter()> | <target-counters()> | <target-text()>"
};
const require$$3 = {
"absolute-size": {
syntax: "xx-small | x-small | small | medium | large | x-large | xx-large | xxx-large"
},
"alpha-value": {
syntax: "<number> | <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>"
},
attachment: attachment,
"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>?"
},
"baseline-position": {
syntax: "[ first | last ]? baseline"
},
"basic-shape": {
syntax: "<inset()> | <circle()> | <ellipse()> | <polygon()> | <path()>"
},
"bg-image": {
syntax: "none | <image>"
},
"bg-layer": {
syntax: "<bg-image> || <bg-position> [ / <bg-size> ]? || <repeat-style> || <attachment> || <box> || <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"
},
"blur()": {
syntax: "blur( <length> )"
},
"blend-mode": {
syntax: "normal | multiply | screen | overlay | darken | lighten | color-dodge | color-burn | hard-light | soft-light | difference | exclusion | hue | saturation | color | luminosity"
},
box: box,
"brightness()": {
syntax: "brightness( <number-percentage> )"
},
"calc()": {
syntax: "calc( <calc-sum> )"
},
"calc-sum": {
syntax: "<calc-product> [ [ '+' | '-' ] <calc-product> ]*"
},
"calc-product": {
syntax: "<calc-value> [ '*' <calc-value> | '/' <number> ]*"
},
"calc-value": {
syntax: "<number> | <dimension> | <percentage> | ( <calc-sum> )"
},
"cf-final-image": {
syntax: "<image> | <color>"
},
"cf-mixing-image": {
syntax: "<percentage>? && <image>"
},
"circle()": {
syntax: "circle( [ <shape-radius> ]? [ at <position> ]? )"
},
"clamp()": {
syntax: "clamp( <calc-sum>#{3} )"
},
"class-selector": {
syntax: "'.' <ident-token>"
},
"clip-source": {
syntax: "<url>"
},
color: color$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>"
},
combinator: combinator,
"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"
},
"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>#"
},
"complex-selector": {
syntax: "<compound-selector> [ <combinator>? <compound-selector> ]*"
},
"complex-selector-list": {
syntax: "<complex-selector>#"
},
"conic-gradient()": {
syntax: "conic-gradient( [ from <angle> ]? [ at <position> ]?, <angular-color-stop-list> )"
},
"contextual-alt-values": {
syntax: "[ contextual | no-contextual ]"
},
"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>"
},
"contrast()": {
syntax: "contrast( [ <number-percentage> ] )"
},
counter: counter,
"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>)"
},
"deprecated-system-color": {
syntax: "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"
},
"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( <length>{2,3} <color>? )"
},
"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( [ <shape-radius>{2} ]? [ at <position> ]? )"
},
"ending-shape": {
syntax: "circle | ellipse"
},
"env()": {
syntax: "env( <custom-ident> , <declaration-value>? )"
},
"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>"
},
"fill-rule": {
syntax: "nonzero | evenodd"
},
"filter-function": {
syntax: "<blur()> | <brightness()> | <contrast()> | <drop-shadow()> | <grayscale()> | <hue-rotate()> | <invert()> | <opacity()> | <saturate()> | <sepia()>"
},
"filter-function-list": {
syntax: "[ <filter-function> | <url> ]+"
},
"final-bg-layer": {
syntax: "<'background-color'> || <bg-image> || <bg-position> [ / <bg-size> ]? || <repeat-style> || <attachment> || <box> || <box>"
},
"fit-content()": {
syntax: "fit-content( [ <length> | <percentage> ] )"
},
"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: 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>, <percentage>, <percentage>, <alpha-value>? )"
},
"hsla()": {
syntax: "hsla( <hue> <percentage> <percentage> [ / <alpha-value> ]? ) | hsla( <hue>, <percentage>, <percentage>, <alpha-value>? )"
},
hue: hue,
"hue-rotate()": {
syntax: "hue-rotate( <angle> )"
},
"hwb()": {
syntax: "hwb( [<hue> | none] [<percentage> | none] [<percentage> | none] [ / [<alpha-value> | none] ]? )"
},
"id-selector": {
syntax: "<hash-token>"
},
image: image,
"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> )"
},
"keyframes-name": {
syntax: "<custom-ident> | <string>"
},
"keyframe-block": {
syntax: "<keyframe-selector># {\n <declaration-list>\n}"
},
"keyframe-block-list": {
syntax: "<keyframe-block>+"
},
"keyframe-selector": {
syntax: "from | to | <percentage>"
},
"layer()": {
syntax: "layer( <layer-name> )"
},
"layer-name": {
syntax: "<ident> [ '.' <ident> ]*"
},
"leader()": {
syntax: "leader( <leader-type> )"
},
"leader-type": {
syntax: "dotted | solid | space | <string>"
},
"length-percentage": {
syntax: "<length> | <percentage>"
},
"line-names": {
syntax: "'[' <custom-ident>* ']'"
},
"line-name-list": {
syntax: "[ <line-names> | <name-repeat> ]+"
},
"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-stop-list> )"
},
"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 ] )"
},
"name-repeat": {
syntax: "repeat( [ <integer [1,∞]> | auto-fill ], <line-names>+ )"
},
"named-color": {
syntax: "transparent | 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 ]"
},
nth: nth$1,
"opacity()": {
syntax: "opacity( [ <number-percentage> ] )"
},
"overflow-position": {
syntax: "unsafe | safe"
},
"outline-radius": {
syntax: "<length> | <percentage>"
},
"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-list": {
syntax: "[ <page-selector># ]?"
},
"page-selector": {
syntax: "<pseudo-page>+ | <ident> <pseudo-page>*"
},
"page-size": {
syntax: "A5 | A4 | A3 | B5 | B4 | JIS-B5 | JIS-B4 | letter | legal | ledger"
},
"path()": {
syntax: "path( [ <fill-rule>, ]? <string> )"
},
"paint()": {
syntax: "paint( <ident>, <declaration-value>? )"
},
"perspective()": {
syntax: "perspective( <length> )"
},
"polygon()": {
syntax: "polygon( <fill-rule>? , [ <length-percentage> <length-percentage> ]# )"
},
position: position,
"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: quote,
"radial-gradient()": {
syntax: "radial-gradient( [ <ending-shape> || <size> ]? [ at <position> ]? , <color-stop-list> )"
},
"relative-selector": {
syntax: "<combinator>? <complex-selector>"
},
"relative-selector-list": {
syntax: "<relative-selector>#"
},
"relative-size": {
syntax: "larger | smaller"
},
"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> )"
},
"rgb()": {
syntax: "rgb( <percentage>{3} [ / <alpha-value> ]? ) | rgb( <number>{3} [ / <alpha-value> ]? ) | rgb( <percentage>#{3} , <alpha-value>? ) | rgb( <number>#{3} , <alpha-value>? )"
},
"rgba()": {
syntax: "rgba( <percentage>{3} [ / <alpha-value> ]? ) | rgba( <number>{3} [ / <alpha-value> ]? ) | rgba( <percentage>#{3} , <alpha-value>? ) | rgba( <number>#{3} , <alpha-value>? )"
},
"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> ] )"
},
"saturate()": {
syntax: "saturate( <number-percentage> )"
},
"scale()": {
syntax: "scale( <number> , <number>? )"
},
"scale3d()": {
syntax: "scale3d( <number> , <number> , <number> )"
},
"scaleX()": {
syntax: "scaleX( <number> )"
},
"scaleY()": {
syntax: "scaleY( <number> )"
},
"scaleZ()": {
syntax: "scaleZ( <number> )"
},
"self-position": {
syntax: "center | start | end | self-start | self-end | flex-start | flex-end"
},
"shape-radius": {
syntax: "<length-percentage> | closest-side | farthest-side"
},
"skew()": {
syntax: "skew( [ <angle> | <zero> ] , [ <angle> | <zero> ]? )"
},
"skewX()": {
syntax: "skewX( [ <angle> | <zero> ] )"
},
"skewY()": {
syntax: "skewY( [ <angle> | <zero> ] )"
},
"sepia()": {
syntax: "sepia( <number-percentage> )"
},
shadow: shadow,
"shadow-t": {
syntax: "[ <length>{2,3} && <color>? ]"
},
shape: shape,
"shape-box": {
syntax: "<box> | margin-box"
},
"side-or-corner": {
syntax: "[ left | right ] || [ top | bottom ]"
},
"single-animation": {
syntax: "<time> || <easing-function> || <time> || <single-animation-iteration-count> || <single-animation-direction> || <single-animation-fill-mode> || <single-animation-play-state> || [ none | <keyframes-name> ]"
},
"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 | <timeline-name>"
},
"single-transition": {
syntax: "[ none | <single-transition-property> ] || <time> || <easing-function> || <time>"
},
"single-transition-property": {
syntax: "all | <custom-ident>"
},
size: size,
"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-in-parens": {
syntax: "( <supports-condition> ) | <supports-feature> | <general-enclosed>"
},
"supports-feature": {
syntax: "<supports-decl> | <supports-selector-fn>"
},
"supports-decl": {
syntax: "( <declaration> )"
},
"supports-selector-fn": {
syntax: "selector( <complex-selector> )"
},
symbol: symbol,
target: target,
"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 ]? )"
},
"time-percentage": {
syntax: "<time> | <percentage>"
},
"timeline-name": {
syntax: "<custom-ident> | <string>"
},
"easing-function": {
syntax: "linear | <cubic-bezier-timing-function> | <step-timing-function>"
},
"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>+"
},
"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> )"
},
"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>? )"
},
"viewport-length": {
syntax: "auto | <length-percentage>"
},
"visual-box": {
syntax: "content-box | padding-box | border-box"
},
"wq-name": {
syntax: "<ns-prefix>? <ident-token>"
}
};
const dataPatch = dataPatch$1;
const mdnAtrules = require$$1;
const mdnProperties = require$$2;
const mdnSyntaxes = require$$3;
const extendSyntax = /^\s*\|\s*/;
function preprocessAtrules(dict) {
const result = Object.create(null);
for (const atruleName in dict) {
const atrule = dict[atruleName];
let descriptors = null;
if (atrule.descriptors) {
descriptors = Object.create(null);
for (const descriptor in atrule.descriptors) {
descriptors[descriptor] = atrule.descriptors[descriptor].syntax;
}
}
result[atruleName.substr(1)] = {
prelude: atrule.syntax.trim().replace(/\{(.|\s)+\}/, '').match(/^@\S+\s+([^;\{]*)/)[1].trim() || null,
descriptors
};
}
return result;
}
function patchDictionary(dict, patchDict) {
const result = {};
// copy all syntaxes for an original dict
for (const key in dict) {
result[key] = dict[key].syntax || dict[key];
}
// apply a patch
for (const key in patchDict) {
if (key in dict) {
if (patchDict[key].syntax) {
result[key] = extendSyntax.test(patchDict[key].syntax)
? result[key] + ' ' + patchDict[key].syntax.trim()
: patchDict[key].syntax;
} else {
delete result[key];
}
} else {
if (patchDict[key].syntax) {
result[key] = patchDict[key].syntax.replace(extendSyntax, '');
}
}
}
return result;
}
function patchAtrules(dict, patchDict) {
const result = {};
// copy all syntaxes for an original dict
for (const key in dict) {
const patchDescriptors = (patchDict[key] && patchDict[key].descriptors) || null;
result[key] = {
prelude: key in patchDict && 'prelude' in patchDict[key]
? patchDict[key].prelude
: dict[key].prelude || null,
descriptors: patchDictionary(dict[key].descriptors || {}, patchDescriptors || {})
};
}
// apply a patch
for (const key in patchDict) {
if (!hasOwnProperty.call(dict, key)) {
result[key] = {
prelude: patchDict[key].prelude || null,
descriptors: patchDict[key].descriptors && patchDictionary({}, patchDict[key].descriptors)
};
}
}
return result;
}
const definitions = {
types: patchDictionary(mdnSyntaxes, dataPatch.types),
atrules: patchAtrules(preprocessAtrules(mdnAtrules), dataPatch.atrules),
properties: patchDictionary(mdnProperties, dataPatch.properties)
};
var data$1 = definitions;
var node = {};
var AnPlusB$2 = {};
const types$G = types$S;
const charCodeDefinitions$5 = charCodeDefinitions$c;
const PLUSSIGN$5 = 0x002B; // U+002B PLUS SIGN (+)
const HYPHENMINUS$2 = 0x002D; // U+002D HYPHEN-MINUS (-)
const N = 0x006E; // U+006E LATIN SMALL LETTER N (n)
const DISALLOW_SIGN = true;
const ALLOW_SIGN = false;
function checkInteger(offset, disallowSign) {
let pos = this.tokenStart + offset;
const code = this.charCodeAt(pos);
if (code === PLUSSIGN$5 || code === HYPHENMINUS$2) {
if (disallowSign) {
this.error('Number sign is not allowed');
}
pos++;
}
for (; pos < this.tokenEnd; pos++) {
if (!charCodeDefinitions$5.isDigit(this.charCodeAt(pos))) {
this.error('Integer is expected', pos);
}
}
}
function checkTokenIsInteger(disallowSign) {
return checkInteger.call(this, 0, disallowSign);
}
function expectCharCode(offset, code) {
if (!this.cmpChar(this.tokenStart + offset, code)) {
let msg = '';
switch (code) {
case N:
msg = 'N is expected';
break;
case HYPHENMINUS$2:
msg = 'HyphenMinus is expected';
break;
}
this.error(msg, this.tokenStart + offset);
}
}
// ... <signed-integer>
// ... ['+' | '-'] <signless-integer>
function consumeB() {
let offset = 0;
let sign = 0;
let type = this.tokenType;
while (type === types$G.WhiteSpace || type === types$G.Comment) {
type = this.lookupType(++offset);
}
if (type !== types$G.Number) {
if (this.isDelim(PLUSSIGN$5, offset) ||
this.isDelim(HYPHENMINUS$2, offset)) {
sign = this.isDelim(PLUSSIGN$5, offset) ? PLUSSIGN$5 : HYPHENMINUS$2;
do {
type = this.lookupType(++offset);
} while (type === types$G.WhiteSpace || type === types$G.Comment);
if (type !== types$G.Number) {
this.skip(offset);
checkTokenIsInteger.call(this, DISALLOW_SIGN);
}
} else {
return null;
}
}
if (offset > 0) {
this.skip(offset);
}
if (sign === 0) {
type = this.charCodeAt(this.tokenStart);
if (type !== PLUSSIGN$5 && type !== HYPHENMINUS$2) {
this.error('Number sign is expected');
}
}
checkTokenIsInteger.call(this, sign !== 0);
return sign === HYPHENMINUS$2 ? '-' + this.consume(types$G.Number) : this.consume(types$G.Number);
}
// An+B microsyntax https://www.w3.org/TR/css-syntax-3/#anb
const name$E = 'AnPlusB';
const structure$D = {
a: [String, null],
b: [String, null]
};
function parse$H() {
/* eslint-disable brace-style*/
const start = this.tokenStart;
let a = null;
let b = null;
// <integer>
if (this.tokenType === types$G.Number) {
checkTokenIsInteger.call(this, ALLOW_SIGN);
b = this.consume(types$G.Number);
}
// -n
// -n <signed-integer>
// -n ['+' | '-'] <signless-integer>
// -n- <signless-integer>
// <dashndashdigit-ident>
else if (this.tokenType === types$G.Ident && this.cmpChar(this.tokenStart, HYPHENMINUS$2)) {
a = '-1';
expectCharCode.call(this, 1, N);
switch (this.tokenEnd - this.tokenStart) {
// -n
// -n <signed-integer>
// -n ['+' | '-'] <signless-integer>
case 2:
this.next();
b = consumeB.call(this);
break;
// -n- <signless-integer>
case 3:
expectCharCode.call(this, 2, HYPHENMINUS$2);
this.next();
this.skipSC();
checkTokenIsInteger.call(this, DISALLOW_SIGN);
b = '-' + this.consume(types$G.Number);
break;
// <dashndashdigit-ident>
default:
expectCharCode.call(this, 2, HYPHENMINUS$2);
checkInteger.call(this, 3, DISALLOW_SIGN);
this.next();
b = this.substrToCursor(start + 2);
}
}
// '+'? n
// '+'? n <signed-integer>
// '+'? n ['+' | '-'] <signless-integer>
// '+'? n- <signless-integer>
// '+'? <ndashdigit-ident>
else if (this.tokenType === types$G.Ident || (this.isDelim(PLUSSIGN$5) && this.lookupType(1) === types$G.Ident)) {
let sign = 0;
a = '1';
// just ignore a plus
if (this.isDelim(PLUSSIGN$5)) {
sign = 1;
this.next();
}
expectCharCode.call(this, 0, N);
switch (this.tokenEnd - this.tokenStart) {
// '+'? n
// '+'? n <signed-integer>
// '+'? n ['+' | '-'] <signless-integer>
case 1:
this.next();
b = consumeB.call(this);
break;
// '+'? n- <signless-integer>
case 2:
expectCharCode.call(this, 1, HYPHENMINUS$2);
this.next();
this.skipSC();
checkTokenIsInteger.call(this, DISALLOW_SIGN);
b = '-' + this.consume(types$G.Number);
break;
// '+'? <ndashdigit-ident>
default:
expectCharCode.call(this, 1, HYPHENMINUS$2);
checkInteger.call(this, 2, DISALLOW_SIGN);
this.next();
b = this.substrToCursor(start + sign + 1);
}
}
// <ndashdigit-dimension>
// <ndash-dimension> <signless-integer>
// <n-dimension>
// <n-dimension> <signed-integer>
// <n-dimension> ['+' | '-'] <signless-integer>
else if (this.tokenType === types$G.Dimension) {
const code = this.charCodeAt(this.tokenStart);
const sign = code === PLUSSIGN$5 || code === HYPHENMINUS$2;
let i = this.tokenStart + sign;
for (; i < this.tokenEnd; i++) {
if (!charCodeDefinitions$5.isDigit(this.charCodeAt(i))) {
break;
}
}
if (i === this.tokenStart + sign) {
this.error('Integer is expected', this.tokenStart + sign);
}
expectCharCode.call(this, i - this.tokenStart, N);
a = this.substring(start, i);
// <n-dimension>
// <n-dimension> <signed-integer>
// <n-dimension> ['+' | '-'] <signless-integer>
if (i + 1 === this.tokenEnd) {
this.next();
b = consumeB.call(this);
} else {
expectCharCode.call(this, i - this.tokenStart + 1, HYPHENMINUS$2);
// <ndash-dimension> <signless-integer>
if (i + 2 === this.tokenEnd) {
this.next();
this.skipSC();
checkTokenIsInteger.call(this, DISALLOW_SIGN);
b = '-' + this.consume(types$G.Number);
}
// <ndashdigit-dimension>
else {
checkInteger.call(this, i - this.tokenStart + 2, DISALLOW_SIGN);
this.next();
b = this.substrToCursor(i + 1);
}
}
} else {
this.error();
}
if (a !== null && a.charCodeAt(0) === PLUSSIGN$5) {
a = a.substr(1);
}
if (b !== null && b.charCodeAt(0) === PLUSSIGN$5) {
b = b.substr(1);
}
return {
type: 'AnPlusB',
loc: this.getLocation(start, this.tokenStart),
a,
b
};
}
function generate$H(node) {
if (node.a) {
const a =
node.a === '+1' && 'n' ||
node.a === '1' && 'n' ||
node.a === '-1' && '-n' ||
node.a + 'n';
if (node.b) {
const b = node.b[0] === '-' || node.b[0] === '+'
? node.b
: '+' + node.b;
this.tokenize(a + b);
} else {
this.tokenize(a);
}
} else {
this.tokenize(node.b);
}
}
AnPlusB$2.generate = generate$H;
AnPlusB$2.name = name$E;
AnPlusB$2.parse = parse$H;
AnPlusB$2.structure = structure$D;
var Atrule$6 = {};
const types$F = types$S;
function consumeRaw$5(startToken) {
return this.Raw(startToken, this.consumeUntilLeftCurlyBracketOrSemicolon, true);
}
function isDeclarationBlockAtrule() {
for (let offset = 1, type; type = this.lookupType(offset); offset++) {
if (type === types$F.RightCurlyBracket) {
return true;
}
if (type === types$F.LeftCurlyBracket ||
type === types$F.AtKeyword) {
return false;
}
}
return false;
}
const name$D = 'Atrule';
const walkContext$9 = 'atrule';
const structure$C = {
name: String,
prelude: ['AtrulePrelude', 'Raw', null],
block: ['Block', null]
};
function parse$G() {
const start = this.tokenStart;
let name;
let nameLowerCase;
let prelude = null;
let block = null;
this.eat(types$F.AtKeyword);
name = this.substrToCursor(start + 1);
nameLowerCase = name.toLowerCase();
this.skipSC();
// parse prelude
if (this.eof === false &&
this.tokenType !== types$F.LeftCurlyBracket &&
this.tokenType !== types$F.Semicolon) {
if (this.parseAtrulePrelude) {
prelude = this.parseWithFallback(this.AtrulePrelude.bind(this, name), consumeRaw$5);
} else {
prelude = consumeRaw$5.call(this, this.tokenIndex);
}
this.skipSC();
}
switch (this.tokenType) {
case types$F.Semicolon:
this.next();
break;
case types$F.LeftCurlyBracket:
if (hasOwnProperty.call(this.atrule, nameLowerCase) &&
typeof this.atrule[nameLowerCase].block === 'function') {
block = this.atrule[nameLowerCase].block.call(this);
} else {
// TODO: should consume block content as Raw?
block = this.Block(isDeclarationBlockAtrule.call(this));
}
break;
}
return {
type: 'Atrule',
loc: this.getLocation(start, this.tokenStart),
name,
prelude,
block
};
}
function generate$G(node) {
this.token(types$F.AtKeyword, '@' + node.name);
if (node.prelude !== null) {
this.node(node.prelude);
}
if (node.block) {
this.node(node.block);
} else {
this.token(types$F.Semicolon, ';');
}
}
Atrule$6.generate = generate$G;
Atrule$6.name = name$D;
Atrule$6.parse = parse$G;
Atrule$6.structure = structure$C;
Atrule$6.walkContext = walkContext$9;
var AtrulePrelude$2 = {};
const types$E = types$S;
const name$C = 'AtrulePrelude';
const walkContext$8 = 'atrulePrelude';
const structure$B = {
children: [[]]
};
function parse$F(name) {
let children = null;
if (name !== null) {
name = name.toLowerCase();
}
this.skipSC();
if (hasOwnProperty.call(this.atrule, name) &&
typeof this.atrule[name].prelude === 'function') {
// custom consumer
children = this.atrule[name].prelude.call(this);
} else {
// default consumer
children = this.readSequence(this.scope.AtrulePrelude);
}
this.skipSC();
if (this.eof !== true &&
this.tokenType !== types$E.LeftCurlyBracket &&
this.tokenType !== types$E.Semicolon) {
this.error('Semicolon or block is expected');
}
return {
type: 'AtrulePrelude',
loc: this.getLocationFromList(children),
children
};
}
function generate$F(node) {
this.children(node);
}
AtrulePrelude$2.generate = generate$F;
AtrulePrelude$2.name = name$C;
AtrulePrelude$2.parse = parse$F;
AtrulePrelude$2.structure = structure$B;
AtrulePrelude$2.walkContext = walkContext$8;
var AttributeSelector$4 = {};
const types$D = types$S;
const DOLLARSIGN$1 = 0x0024; // U+0024 DOLLAR SIGN ($)
const ASTERISK$5 = 0x002A; // U+002A ASTERISK (*)
const EQUALSSIGN = 0x003D; // U+003D EQUALS SIGN (=)
const CIRCUMFLEXACCENT = 0x005E; // U+005E (^)
const VERTICALLINE$2 = 0x007C; // U+007C VERTICAL LINE (|)
const TILDE$2 = 0x007E; // U+007E TILDE (~)
function getAttributeName() {
if (this.eof) {
this.error('Unexpected end of input');
}
const start = this.tokenStart;
let expectIdent = false;
if (this.isDelim(ASTERISK$5)) {
expectIdent = true;
this.next();
} else if (!this.isDelim(VERTICALLINE$2)) {
this.eat(types$D.Ident);
}
if (this.isDelim(VERTICALLINE$2)) {
if (this.charCodeAt(this.tokenStart + 1) !== EQUALSSIGN) {
this.next();
this.eat(types$D.Ident);
} else if (expectIdent) {
this.error('Identifier is expected', this.tokenEnd);
}
} else if (expectIdent) {
this.error('Vertical line is expected');
}
return {
type: 'Identifier',
loc: this.getLocation(start, this.tokenStart),
name: this.substrToCursor(start)
};
}
function getOperator() {
const start = this.tokenStart;
const code = this.charCodeAt(start);
if (code !== EQUALSSIGN && // =
code !== TILDE$2 && // ~=
code !== CIRCUMFLEXACCENT && // ^=
code !== DOLLARSIGN$1 && // $=
code !== ASTERISK$5 && // *=
code !== VERTICALLINE$2 // |=
) {
this.error('Attribute selector (=, ~=, ^=, $=, *=, |=) is expected');
}
this.next();
if (code !== EQUALSSIGN) {
if (!this.isDelim(EQUALSSIGN)) {
this.error('Equal sign is expected');
}
this.next();
}
return this.substrToCursor(start);
}
// '[' <wq-name> ']'
// '[' <wq-name> <attr-matcher> [ <string-token> | <ident-token> ] <attr-modifier>? ']'
const name$B = 'AttributeSelector';
const structure$A = {
name: 'Identifier',
matcher: [String, null],
value: ['String', 'Identifier', null],
flags: [String, null]
};
function parse$E() {
const start = this.tokenStart;
let name;
let matcher = null;
let value = null;
let flags = null;
this.eat(types$D.LeftSquareBracket);
this.skipSC();
name = getAttributeName.call(this);
this.skipSC();
if (this.tokenType !== types$D.RightSquareBracket) {
// avoid case `[name i]`
if (this.tokenType !== types$D.Ident) {
matcher = getOperator.call(this);
this.skipSC();
value = this.tokenType === types$D.String
? this.String()
: this.Identifier();
this.skipSC();
}
// attribute flags
if (this.tokenType === types$D.Ident) {
flags = this.consume(types$D.Ident);
this.skipSC();
}
}
this.eat(types$D.RightSquareBracket);
return {
type: 'AttributeSelector',
loc: this.getLocation(start, this.tokenStart),
name,
matcher,
value,
flags
};
}
function generate$E(node) {
this.token(types$D.Delim, '[');
this.node(node.name);
if (node.matcher !== null) {
this.tokenize(node.matcher);
this.node(node.value);
}
if (node.flags !== null) {
this.token(types$D.Ident, node.flags);
}
this.token(types$D.Delim, ']');
}
AttributeSelector$4.generate = generate$E;
AttributeSelector$4.name = name$B;
AttributeSelector$4.parse = parse$E;
AttributeSelector$4.structure = structure$A;
var Block$2 = {};
const types$C = types$S;
function consumeRaw$4(startToken) {
return this.Raw(startToken, null, true);
}
function consumeRule() {
return this.parseWithFallback(this.Rule, consumeRaw$4);
}
function consumeRawDeclaration(startToken) {
return this.Raw(startToken, this.consumeUntilSemicolonIncluded, true);
}
function consumeDeclaration() {
if (this.tokenType === types$C.Semicolon) {
return consumeRawDeclaration.call(this, this.tokenIndex);
}
const node = this.parseWithFallback(this.Declaration, consumeRawDeclaration);
if (this.tokenType === types$C.Semicolon) {
this.next();
}
return node;
}
const name$A = 'Block';
const walkContext$7 = 'block';
const structure$z = {
children: [[
'Atrule',
'Rule',
'Declaration'
]]
};
function parse$D(isDeclaration) {
const consumer = isDeclaration ? consumeDeclaration : consumeRule;
const start = this.tokenStart;
let children = this.createList();
this.eat(types$C.LeftCurlyBracket);
scan:
while (!this.eof) {
switch (this.tokenType) {
case types$C.RightCurlyBracket:
break scan;
case types$C.WhiteSpace:
case types$C.Comment:
this.next();
break;
case types$C.AtKeyword:
children.push(this.parseWithFallback(this.Atrule, consumeRaw$4));
break;
default:
children.push(consumer.call(this));
}
}
if (!this.eof) {
this.eat(types$C.RightCurlyBracket);
}
return {
type: 'Block',
loc: this.getLocation(start, this.tokenStart),
children
};
}
function generate$D(node) {
this.token(types$C.LeftCurlyBracket, '{');
this.children(node, prev => {
if (prev.type === 'Declaration') {
this.token(types$C.Semicolon, ';');
}
});
this.token(types$C.RightCurlyBracket, '}');
}
Block$2.generate = generate$D;
Block$2.name = name$A;
Block$2.parse = parse$D;
Block$2.structure = structure$z;
Block$2.walkContext = walkContext$7;
var Brackets$2 = {};
const types$B = types$S;
const name$z = 'Brackets';
const structure$y = {
children: [[]]
};
function parse$C(readSequence, recognizer) {
const start = this.tokenStart;
let children = null;
this.eat(types$B.LeftSquareBracket);
children = readSequence.call(this, recognizer);
if (!this.eof) {
this.eat(types$B.RightSquareBracket);
}
return {
type: 'Brackets',
loc: this.getLocation(start, this.tokenStart),
children
};
}
function generate$C(node) {
this.token(types$B.Delim, '[');
this.children(node);
this.token(types$B.Delim, ']');
}
Brackets$2.generate = generate$C;
Brackets$2.name = name$z;
Brackets$2.parse = parse$C;
Brackets$2.structure = structure$y;
var CDC$2 = {};
const types$A = types$S;
const name$y = 'CDC';
const structure$x = [];
function parse$B() {
const start = this.tokenStart;
this.eat(types$A.CDC); // -->
return {
type: 'CDC',
loc: this.getLocation(start, this.tokenStart)
};
}
function generate$B() {
this.token(types$A.CDC, '-->');
}
CDC$2.generate = generate$B;
CDC$2.name = name$y;
CDC$2.parse = parse$B;
CDC$2.structure = structure$x;
var CDO$2 = {};
const types$z = types$S;
const name$x = 'CDO';
const structure$w = [];
function parse$A() {
const start = this.tokenStart;
this.eat(types$z.CDO); // <!--
return {
type: 'CDO',
loc: this.getLocation(start, this.tokenStart)
};
}
function generate$A() {
this.token(types$z.CDO, '<!--');
}
CDO$2.generate = generate$A;
CDO$2.name = name$x;
CDO$2.parse = parse$A;
CDO$2.structure = structure$w;
var ClassSelector$2 = {};
const types$y = types$S;
const FULLSTOP$2 = 0x002E; // U+002E FULL STOP (.)
// '.' ident
const name$w = 'ClassSelector';
const structure$v = {
name: String
};
function parse$z() {
this.eatDelim(FULLSTOP$2);
return {
type: 'ClassSelector',
loc: this.getLocation(this.tokenStart - 1, this.tokenEnd),
name: this.consume(types$y.Ident)
};
}
function generate$z(node) {
this.token(types$y.Delim, '.');
this.token(types$y.Ident, node.name);
}
ClassSelector$2.generate = generate$z;
ClassSelector$2.name = name$w;
ClassSelector$2.parse = parse$z;
ClassSelector$2.structure = structure$v;
var Combinator$2 = {};
const types$x = types$S;
const PLUSSIGN$4 = 0x002B; // U+002B PLUS SIGN (+)
const SOLIDUS$5 = 0x002F; // U+002F SOLIDUS (/)
const GREATERTHANSIGN$1 = 0x003E; // U+003E GREATER-THAN SIGN (>)
const TILDE$1 = 0x007E; // U+007E TILDE (~)
const name$v = 'Combinator';
const structure$u = {
name: String
};
// + | > | ~ | /deep/
function parse$y() {
const start = this.tokenStart;
let name;
switch (this.tokenType) {
case types$x.WhiteSpace:
name = ' ';
break;
case types$x.Delim:
switch (this.charCodeAt(this.tokenStart)) {
case GREATERTHANSIGN$1:
case PLUSSIGN$4:
case TILDE$1:
this.next();
break;
case SOLIDUS$5:
this.next();
this.eatIdent('deep');
this.eatDelim(SOLIDUS$5);
break;
default:
this.error('Combinator is expected');
}
name = this.substrToCursor(start);
break;
}
return {
type: 'Combinator',
loc: this.getLocation(start, this.tokenStart),
name
};
}
function generate$y(node) {
this.tokenize(node.name);
}
Combinator$2.generate = generate$y;
Combinator$2.name = name$v;
Combinator$2.parse = parse$y;
Combinator$2.structure = structure$u;
var Comment$4 = {};
const types$w = types$S;
const ASTERISK$4 = 0x002A; // U+002A ASTERISK (*)
const SOLIDUS$4 = 0x002F; // U+002F SOLIDUS (/)
const name$u = 'Comment';
const structure$t = {
value: String
};
function parse$x() {
const start = this.tokenStart;
let end = this.tokenEnd;
this.eat(types$w.Comment);
if ((end - start + 2) >= 2 &&
this.charCodeAt(end - 2) === ASTERISK$4 &&
this.charCodeAt(end - 1) === SOLIDUS$4) {
end -= 2;
}
return {
type: 'Comment',
loc: this.getLocation(start, this.tokenStart),
value: this.substring(start + 2, end)
};
}
function generate$x(node) {
this.token(types$w.Comment, '/*' + node.value + '*/');
}
Comment$4.generate = generate$x;
Comment$4.name = name$u;
Comment$4.parse = parse$x;
Comment$4.structure = structure$t;
var Declaration$4 = {};
const names$2 = names$4;
const types$v = types$S;
const EXCLAMATIONMARK$1 = 0x0021; // U+0021 EXCLAMATION MARK (!)
const NUMBERSIGN$2 = 0x0023; // U+0023 NUMBER SIGN (#)
const DOLLARSIGN = 0x0024; // U+0024 DOLLAR SIGN ($)
const AMPERSAND = 0x0026; // U+0026 AMPERSAND (&)
const ASTERISK$3 = 0x002A; // U+002A ASTERISK (*)
const PLUSSIGN$3 = 0x002B; // U+002B PLUS SIGN (+)
const SOLIDUS$3 = 0x002F; // U+002F SOLIDUS (/)
function consumeValueRaw(startToken) {
return this.Raw(startToken, this.consumeUntilExclamationMarkOrSemicolon, true);
}
function consumeCustomPropertyRaw(startToken) {
return this.Raw(startToken, this.consumeUntilExclamationMarkOrSemicolon, false);
}
function consumeValue() {
const startValueToken = this.tokenIndex;
const value = this.Value();
if (value.type !== 'Raw' &&
this.eof === false &&
this.tokenType !== types$v.Semicolon &&
this.isDelim(EXCLAMATIONMARK$1) === false &&
this.isBalanceEdge(startValueToken) === false) {
this.error();
}
return value;
}
const name$t = 'Declaration';
const walkContext$6 = 'declaration';
const structure$s = {
important: [Boolean, String],
property: String,
value: ['Value', 'Raw']
};
function parse$w() {
const start = this.tokenStart;
const startToken = this.tokenIndex;
const property = readProperty.call(this);
const customProperty = names$2.isCustomProperty(property);
const parseValue = customProperty ? this.parseCustomProperty : this.parseValue;
const consumeRaw = customProperty ? consumeCustomPropertyRaw : consumeValueRaw;
let important = false;
let value;
this.skipSC();
this.eat(types$v.Colon);
const valueStart = this.tokenIndex;
if (!customProperty) {
this.skipSC();
}
if (parseValue) {
value = this.parseWithFallback(consumeValue, consumeRaw);
} else {
value = consumeRaw.call(this, this.tokenIndex);
}
if (customProperty && value.type === 'Value' && value.children.isEmpty) {
for (let offset = valueStart - this.tokenIndex; offset <= 0; offset++) {
if (this.lookupType(offset) === types$v.WhiteSpace) {
value.children.appendData({
type: 'WhiteSpace',
loc: null,
value: ' '
});
break;
}
}
}
if (this.isDelim(EXCLAMATIONMARK$1)) {
important = getImportant.call(this);
this.skipSC();
}
// Do not include semicolon to range per spec
// https://drafts.csswg.org/css-syntax/#declaration-diagram
if (this.eof === false &&
this.tokenType !== types$v.Semicolon &&
this.isBalanceEdge(startToken) === false) {
this.error();
}
return {
type: 'Declaration',
loc: this.getLocation(start, this.tokenStart),
important,
property,
value
};
}
function generate$w(node) {
this.token(types$v.Ident, node.property);
this.token(types$v.Colon, ':');
this.node(node.value);
if (node.important) {
this.token(types$v.Delim, '!');
this.token(types$v.Ident, node.important === true ? 'important' : node.important);
}
}
function readProperty() {
const start = this.tokenStart;
// hacks
if (this.tokenType === types$v.Delim) {
switch (this.charCodeAt(this.tokenStart)) {
case ASTERISK$3:
case DOLLARSIGN:
case PLUSSIGN$3:
case NUMBERSIGN$2:
case AMPERSAND:
this.next();
break;
// TODO: not sure we should support this hack
case SOLIDUS$3:
this.next();
if (this.isDelim(SOLIDUS$3)) {
this.next();
}
break;
}
}
if (this.tokenType === types$v.Hash) {
this.eat(types$v.Hash);
} else {
this.eat(types$v.Ident);
}
return this.substrToCursor(start);
}
// ! ws* important
function getImportant() {
this.eat(types$v.Delim);
this.skipSC();
const important = this.consume(types$v.Ident);
// store original value in case it differ from `important`
// for better original source restoring and hacks like `!ie` support
return important === 'important' ? true : important;
}
Declaration$4.generate = generate$w;
Declaration$4.name = name$t;
Declaration$4.parse = parse$w;
Declaration$4.structure = structure$s;
Declaration$4.walkContext = walkContext$6;
var DeclarationList$2 = {};
const types$u = types$S;
function consumeRaw$3(startToken) {
return this.Raw(startToken, this.consumeUntilSemicolonIncluded, true);
}
const name$s = 'DeclarationList';
const structure$r = {
children: [[
'Declaration'
]]
};
function parse$v() {
const children = this.createList();
while (!this.eof) {
switch (this.tokenType) {
case types$u.WhiteSpace:
case types$u.Comment:
case types$u.Semicolon:
this.next();
break;
default:
children.push(this.parseWithFallback(this.Declaration, consumeRaw$3));
}
}
return {
type: 'DeclarationList',
loc: this.getLocationFromList(children),
children
};
}
function generate$v(node) {
this.children(node, prev => {
if (prev.type === 'Declaration') {
this.token(types$u.Semicolon, ';');
}
});
}
DeclarationList$2.generate = generate$v;
DeclarationList$2.name = name$s;
DeclarationList$2.parse = parse$v;
DeclarationList$2.structure = structure$r;
var Dimension$4 = {};
const types$t = types$S;
const name$r = 'Dimension';
const structure$q = {
value: String,
unit: String
};
function parse$u() {
const start = this.tokenStart;
const value = this.consumeNumber(types$t.Dimension);
return {
type: 'Dimension',
loc: this.getLocation(start, this.tokenStart),
value,
unit: this.substring(start + value.length, this.tokenStart)
};
}
function generate$u(node) {
this.token(types$t.Dimension, node.value + node.unit);
}
Dimension$4.generate = generate$u;
Dimension$4.name = name$r;
Dimension$4.parse = parse$u;
Dimension$4.structure = structure$q;
var _Function = {};
const types$s = types$S;
const name$q = 'Function';
const walkContext$5 = 'function';
const structure$p = {
name: String,
children: [[]]
};
// <function-token> <sequence> )
function parse$t(readSequence, recognizer) {
const start = this.tokenStart;
const name = this.consumeFunctionName();
const nameLowerCase = name.toLowerCase();
let children;
children = recognizer.hasOwnProperty(nameLowerCase)
? recognizer[nameLowerCase].call(this, recognizer)
: readSequence.call(this, recognizer);
if (!this.eof) {
this.eat(types$s.RightParenthesis);
}
return {
type: 'Function',
loc: this.getLocation(start, this.tokenStart),
name,
children
};
}
function generate$t(node) {
this.token(types$s.Function, node.name + '(');
this.children(node);
this.token(types$s.RightParenthesis, ')');
}
_Function.generate = generate$t;
_Function.name = name$q;
_Function.parse = parse$t;
_Function.structure = structure$p;
_Function.walkContext = walkContext$5;
var Hash$2 = {};
const types$r = types$S;
// '#' ident
const xxx = 'XXX';
const name$p = 'Hash';
const structure$o = {
value: String
};
function parse$s() {
const start = this.tokenStart;
this.eat(types$r.Hash);
return {
type: 'Hash',
loc: this.getLocation(start, this.tokenStart),
value: this.substrToCursor(start + 1)
};
}
function generate$s(node) {
this.token(types$r.Hash, '#' + node.value);
}
Hash$2.generate = generate$s;
Hash$2.name = name$p;
Hash$2.parse = parse$s;
Hash$2.structure = structure$o;
Hash$2.xxx = xxx;
var Identifier$2 = {};
const types$q = types$S;
const name$o = 'Identifier';
const structure$n = {
name: String
};
function parse$r() {
return {
type: 'Identifier',
loc: this.getLocation(this.tokenStart, this.tokenEnd),
name: this.consume(types$q.Ident)
};
}
function generate$r(node) {
this.token(types$q.Ident, node.name);
}
Identifier$2.generate = generate$r;
Identifier$2.name = name$o;
Identifier$2.parse = parse$r;
Identifier$2.structure = structure$n;
var IdSelector$2 = {};
const types$p = types$S;
const name$n = 'IdSelector';
const structure$m = {
name: String
};
function parse$q() {
const start = this.tokenStart;
// TODO: check value is an ident
this.eat(types$p.Hash);
return {
type: 'IdSelector',
loc: this.getLocation(start, this.tokenStart),
name: this.substrToCursor(start + 1)
};
}
function generate$q(node) {
// Using Delim instead of Hash is a hack to avoid for a whitespace between ident and id-selector
// in safe mode (e.g. "a#id"), because IE11 doesn't allow a sequence <ident-token> <hash-token>
// without a whitespace in values (e.g. "1px solid#000")
this.token(types$p.Delim, '#' + node.name);
}
IdSelector$2.generate = generate$q;
IdSelector$2.name = name$n;
IdSelector$2.parse = parse$q;
IdSelector$2.structure = structure$m;
var MediaFeature$2 = {};
const types$o = types$S;
const name$m = 'MediaFeature';
const structure$l = {
name: String,
value: ['Identifier', 'Number', 'Dimension', 'Ratio', null]
};
function parse$p() {
const start = this.tokenStart;
let name;
let value = null;
this.eat(types$o.LeftParenthesis);
this.skipSC();
name = this.consume(types$o.Ident);
this.skipSC();
if (this.tokenType !== types$o.RightParenthesis) {
this.eat(types$o.Colon);
this.skipSC();
switch (this.tokenType) {
case types$o.Number:
if (this.lookupNonWSType(1) === types$o.Delim) {
value = this.Ratio();
} else {
value = this.Number();
}
break;
case types$o.Dimension:
value = this.Dimension();
break;
case types$o.Ident:
value = this.Identifier();
break;
default:
this.error('Number, dimension, ratio or identifier is expected');
}
this.skipSC();
}
this.eat(types$o.RightParenthesis);
return {
type: 'MediaFeature',
loc: this.getLocation(start, this.tokenStart),
name,
value
};
}
function generate$p(node) {
this.token(types$o.LeftParenthesis, '(');
this.token(types$o.Ident, node.name);
if (node.value !== null) {
this.token(types$o.Colon, ':');
this.node(node.value);
}
this.token(types$o.RightParenthesis, ')');
}
MediaFeature$2.generate = generate$p;
MediaFeature$2.name = name$m;
MediaFeature$2.parse = parse$p;
MediaFeature$2.structure = structure$l;
var MediaQuery$2 = {};
const types$n = types$S;
const name$l = 'MediaQuery';
const structure$k = {
children: [[
'Identifier',
'MediaFeature',
'WhiteSpace'
]]
};
function parse$o() {
const children = this.createList();
let child = null;
this.skipSC();
scan:
while (!this.eof) {
switch (this.tokenType) {
case types$n.Comment:
case types$n.WhiteSpace:
this.next();
continue;
case types$n.Ident:
child = this.Identifier();
break;
case types$n.LeftParenthesis:
child = this.MediaFeature();
break;
default:
break scan;
}
children.push(child);
}
if (child === null) {
this.error('Identifier or parenthesis is expected');
}
return {
type: 'MediaQuery',
loc: this.getLocationFromList(children),
children
};
}
function generate$o(node) {
this.children(node);
}
MediaQuery$2.generate = generate$o;
MediaQuery$2.name = name$l;
MediaQuery$2.parse = parse$o;
MediaQuery$2.structure = structure$k;
var MediaQueryList$2 = {};
const types$m = types$S;
const name$k = 'MediaQueryList';
const structure$j = {
children: [[
'MediaQuery'
]]
};
function parse$n() {
const children = this.createList();
this.skipSC();
while (!this.eof) {
children.push(this.MediaQuery());
if (this.tokenType !== types$m.Comma) {
break;
}
this.next();
}
return {
type: 'MediaQueryList',
loc: this.getLocationFromList(children),
children
};
}
function generate$n(node) {
this.children(node, () => this.token(types$m.Comma, ','));
}
MediaQueryList$2.generate = generate$n;
MediaQueryList$2.name = name$k;
MediaQueryList$2.parse = parse$n;
MediaQueryList$2.structure = structure$j;
var Nth$2 = {};
const types$l = types$S;
const name$j = 'Nth';
const structure$i = {
nth: ['AnPlusB', 'Identifier'],
selector: ['SelectorList', null]
};
function parse$m() {
this.skipSC();
const start = this.tokenStart;
let end = start;
let selector = null;
let nth;
if (this.lookupValue(0, 'odd') || this.lookupValue(0, 'even')) {
nth = this.Identifier();
} else {
nth = this.AnPlusB();
}
end = this.tokenStart;
this.skipSC();
if (this.lookupValue(0, 'of')) {
this.next();
selector = this.SelectorList();
end = this.tokenStart;
}
return {
type: 'Nth',
loc: this.getLocation(start, end),
nth,
selector
};
}
function generate$m(node) {
this.node(node.nth);
if (node.selector !== null) {
this.token(types$l.Ident, 'of');
this.node(node.selector);
}
}
Nth$2.generate = generate$m;
Nth$2.name = name$j;
Nth$2.parse = parse$m;
Nth$2.structure = structure$i;
var _Number$5 = {};
const types$k = types$S;
const name$i = 'Number';
const structure$h = {
value: String
};
function parse$l() {
return {
type: 'Number',
loc: this.getLocation(this.tokenStart, this.tokenEnd),
value: this.consume(types$k.Number)
};
}
function generate$l(node) {
this.token(types$k.Number, node.value);
}
_Number$5.generate = generate$l;
_Number$5.name = name$i;
_Number$5.parse = parse$l;
_Number$5.structure = structure$h;
var Operator$2 = {};
// '/' | '*' | ',' | ':' | '+' | '-'
const name$h = 'Operator';
const structure$g = {
value: String
};
function parse$k() {
const start = this.tokenStart;
this.next();
return {
type: 'Operator',
loc: this.getLocation(start, this.tokenStart),
value: this.substrToCursor(start)
};
}
function generate$k(node) {
this.tokenize(node.value);
}
Operator$2.generate = generate$k;
Operator$2.name = name$h;
Operator$2.parse = parse$k;
Operator$2.structure = structure$g;
var Parentheses$2 = {};
const types$j = types$S;
const name$g = 'Parentheses';
const structure$f = {
children: [[]]
};
function parse$j(readSequence, recognizer) {
const start = this.tokenStart;
let children = null;
this.eat(types$j.LeftParenthesis);
children = readSequence.call(this, recognizer);
if (!this.eof) {
this.eat(types$j.RightParenthesis);
}
return {
type: 'Parentheses',
loc: this.getLocation(start, this.tokenStart),
children
};
}
function generate$j(node) {
this.token(types$j.LeftParenthesis, '(');
this.children(node);
this.token(types$j.RightParenthesis, ')');
}
Parentheses$2.generate = generate$j;
Parentheses$2.name = name$g;
Parentheses$2.parse = parse$j;
Parentheses$2.structure = structure$f;
var Percentage$4 = {};
const types$i = types$S;
const name$f = 'Percentage';
const structure$e = {
value: String
};
function parse$i() {
return {
type: 'Percentage',
loc: this.getLocation(this.tokenStart, this.tokenEnd),
value: this.consumeNumber(types$i.Percentage)
};
}
function generate$i(node) {
this.token(types$i.Percentage, node.value + '%');
}
Percentage$4.generate = generate$i;
Percentage$4.name = name$f;
Percentage$4.parse = parse$i;
Percentage$4.structure = structure$e;
var PseudoClassSelector$2 = {};
const types$h = types$S;
const name$e = 'PseudoClassSelector';
const walkContext$4 = 'function';
const structure$d = {
name: String,
children: [['Raw'], null]
};
// : [ <ident> | <function-token> <any-value>? ) ]
function parse$h() {
const start = this.tokenStart;
let children = null;
let name;
let nameLowerCase;
this.eat(types$h.Colon);
if (this.tokenType === types$h.Function) {
name = this.consumeFunctionName();
nameLowerCase = name.toLowerCase();
if (hasOwnProperty.call(this.pseudo, nameLowerCase)) {
this.skipSC();
children = this.pseudo[nameLowerCase].call(this);
this.skipSC();
} else {
children = this.createList();
children.push(
this.Raw(this.tokenIndex, null, false)
);
}
this.eat(types$h.RightParenthesis);
} else {
name = this.consume(types$h.Ident);
}
return {
type: 'PseudoClassSelector',
loc: this.getLocation(start, this.tokenStart),
name,
children
};
}
function generate$h(node) {
this.token(types$h.Colon, ':');
if (node.children === null) {
this.token(types$h.Ident, node.name);
} else {
this.token(types$h.Function, node.name + '(');
this.children(node);
this.token(types$h.RightParenthesis, ')');
}
}
PseudoClassSelector$2.generate = generate$h;
PseudoClassSelector$2.name = name$e;
PseudoClassSelector$2.parse = parse$h;
PseudoClassSelector$2.structure = structure$d;
PseudoClassSelector$2.walkContext = walkContext$4;
var PseudoElementSelector$2 = {};
const types$g = types$S;
const name$d = 'PseudoElementSelector';
const walkContext$3 = 'function';
const structure$c = {
name: String,
children: [['Raw'], null]
};
// :: [ <ident> | <function-token> <any-value>? ) ]
function parse$g() {
const start = this.tokenStart;
let children = null;
let name;
let nameLowerCase;
this.eat(types$g.Colon);
this.eat(types$g.Colon);
if (this.tokenType === types$g.Function) {
name = this.consumeFunctionName();
nameLowerCase = name.toLowerCase();
if (hasOwnProperty.call(this.pseudo, nameLowerCase)) {
this.skipSC();
children = this.pseudo[nameLowerCase].call(this);
this.skipSC();
} else {
children = this.createList();
children.push(
this.Raw(this.tokenIndex, null, false)
);
}
this.eat(types$g.RightParenthesis);
} else {
name = this.consume(types$g.Ident);
}
return {
type: 'PseudoElementSelector',
loc: this.getLocation(start, this.tokenStart),
name,
children
};
}
function generate$g(node) {
this.token(types$g.Colon, ':');
this.token(types$g.Colon, ':');
if (node.children === null) {
this.token(types$g.Ident, node.name);
} else {
this.token(types$g.Function, node.name + '(');
this.children(node);
this.token(types$g.RightParenthesis, ')');
}
}
PseudoElementSelector$2.generate = generate$g;
PseudoElementSelector$2.name = name$d;
PseudoElementSelector$2.parse = parse$g;
PseudoElementSelector$2.structure = structure$c;
PseudoElementSelector$2.walkContext = walkContext$3;
var Ratio$2 = {};
const types$f = types$S;
const charCodeDefinitions$4 = charCodeDefinitions$c;
const SOLIDUS$2 = 0x002F; // U+002F SOLIDUS (/)
const FULLSTOP$1 = 0x002E; // U+002E FULL STOP (.)
// Terms of <ratio> should be a positive numbers (not zero or negative)
// (see https://drafts.csswg.org/mediaqueries-3/#values)
// However, -o-min-device-pixel-ratio takes fractional values as a ratio's term
// and this is using by various sites. Therefore we relax checking on parse
// to test a term is unsigned number without an exponent part.
// Additional checking may be applied on lexer validation.
function consumeNumber() {
this.skipSC();
const value = this.consume(types$f.Number);
for (let i = 0; i < value.length; i++) {
const code = value.charCodeAt(i);
if (!charCodeDefinitions$4.isDigit(code) && code !== FULLSTOP$1) {
this.error('Unsigned number is expected', this.tokenStart - value.length + i);
}
}
if (Number(value) === 0) {
this.error('Zero number is not allowed', this.tokenStart - value.length);
}
return value;
}
const name$c = 'Ratio';
const structure$b = {
left: String,
right: String
};
// <positive-integer> S* '/' S* <positive-integer>
function parse$f() {
const start = this.tokenStart;
const left = consumeNumber.call(this);
let right;
this.skipSC();
this.eatDelim(SOLIDUS$2);
right = consumeNumber.call(this);
return {
type: 'Ratio',
loc: this.getLocation(start, this.tokenStart),
left,
right
};
}
function generate$f(node) {
this.token(types$f.Number, node.left);
this.token(types$f.Delim, '/');
this.token(types$f.Number, node.right);
}
Ratio$2.generate = generate$f;
Ratio$2.name = name$c;
Ratio$2.parse = parse$f;
Ratio$2.structure = structure$b;
var Raw$4 = {};
const types$e = types$S;
function getOffsetExcludeWS() {
if (this.tokenIndex > 0) {
if (this.lookupType(-1) === types$e.WhiteSpace) {
return this.tokenIndex > 1
? this.getTokenStart(this.tokenIndex - 1)
: this.firstCharOffset;
}
}
return this.tokenStart;
}
const name$b = 'Raw';
const structure$a = {
value: String
};
function parse$e(startToken, consumeUntil, excludeWhiteSpace) {
const startOffset = this.getTokenStart(startToken);
let endOffset;
this.skipUntilBalanced(startToken, consumeUntil || this.consumeUntilBalanceEnd);
if (excludeWhiteSpace && this.tokenStart > startOffset) {
endOffset = getOffsetExcludeWS.call(this);
} else {
endOffset = this.tokenStart;
}
return {
type: 'Raw',
loc: this.getLocation(startOffset, endOffset),
value: this.substring(startOffset, endOffset)
};
}
function generate$e(node) {
this.tokenize(node.value);
}
Raw$4.generate = generate$e;
Raw$4.name = name$b;
Raw$4.parse = parse$e;
Raw$4.structure = structure$a;
var Rule$4 = {};
const types$d = types$S;
function consumeRaw$2(startToken) {
return this.Raw(startToken, this.consumeUntilLeftCurlyBracket, true);
}
function consumePrelude() {
const prelude = this.SelectorList();
if (prelude.type !== 'Raw' &&
this.eof === false &&
this.tokenType !== types$d.LeftCurlyBracket) {
this.error();
}
return prelude;
}
const name$a = 'Rule';
const walkContext$2 = 'rule';
const structure$9 = {
prelude: ['SelectorList', 'Raw'],
block: ['Block']
};
function parse$d() {
const startToken = this.tokenIndex;
const startOffset = this.tokenStart;
let prelude;
let block;
if (this.parseRulePrelude) {
prelude = this.parseWithFallback(consumePrelude, consumeRaw$2);
} else {
prelude = consumeRaw$2.call(this, startToken);
}
block = this.Block(true);
return {
type: 'Rule',
loc: this.getLocation(startOffset, this.tokenStart),
prelude,
block
};
}
function generate$d(node) {
this.node(node.prelude);
this.node(node.block);
}
Rule$4.generate = generate$d;
Rule$4.name = name$a;
Rule$4.parse = parse$d;
Rule$4.structure = structure$9;
Rule$4.walkContext = walkContext$2;
var Selector$3 = {};
const name$9 = 'Selector';
const structure$8 = {
children: [[
'TypeSelector',
'IdSelector',
'ClassSelector',
'AttributeSelector',
'PseudoClassSelector',
'PseudoElementSelector',
'Combinator',
'WhiteSpace'
]]
};
function parse$c() {
const children = this.readSequence(this.scope.Selector);
// nothing were consumed
if (this.getFirstListNode(children) === null) {
this.error('Selector is expected');
}
return {
type: 'Selector',
loc: this.getLocationFromList(children),
children
};
}
function generate$c(node) {
this.children(node);
}
Selector$3.generate = generate$c;
Selector$3.name = name$9;
Selector$3.parse = parse$c;
Selector$3.structure = structure$8;
var SelectorList$2 = {};
const types$c = types$S;
const name$8 = 'SelectorList';
const walkContext$1 = 'selector';
const structure$7 = {
children: [[
'Selector',
'Raw'
]]
};
function parse$b() {
const children = this.createList();
while (!this.eof) {
children.push(this.Selector());
if (this.tokenType === types$c.Comma) {
this.next();
continue;
}
break;
}
return {
type: 'SelectorList',
loc: this.getLocationFromList(children),
children
};
}
function generate$b(node) {
this.children(node, () => this.token(types$c.Comma, ','));
}
SelectorList$2.generate = generate$b;
SelectorList$2.name = name$8;
SelectorList$2.parse = parse$b;
SelectorList$2.structure = structure$7;
SelectorList$2.walkContext = walkContext$1;
var _String = {};
var string$3 = {};
const charCodeDefinitions$3 = charCodeDefinitions$c;
const utils$d = utils$k;
const REVERSE_SOLIDUS$2 = 0x005c; // U+005C REVERSE SOLIDUS (\)
const QUOTATION_MARK$1 = 0x0022; // "
const APOSTROPHE$1 = 0x0027; // '
function decode$2(str) {
const len = str.length;
const firstChar = str.charCodeAt(0);
const start = firstChar === QUOTATION_MARK$1 || firstChar === APOSTROPHE$1 ? 1 : 0;
const end = start === 1 && len > 1 && str.charCodeAt(len - 1) === firstChar ? len - 2 : len - 1;
let decoded = '';
for (let i = start; i <= end; i++) {
let code = str.charCodeAt(i);
if (code === REVERSE_SOLIDUS$2) {
// special case at the ending
if (i === end) {
// if the next input code point is EOF, do nothing
// otherwise include last quote as escaped
if (i !== len - 1) {
decoded = str.substr(i + 1);
}
break;
}
code = str.charCodeAt(++i);
// consume escaped
if (charCodeDefinitions$3.isValidEscape(REVERSE_SOLIDUS$2, code)) {
const escapeStart = i - 1;
const escapeEnd = utils$d.consumeEscaped(str, escapeStart);
i = escapeEnd - 1;
decoded += utils$d.decodeEscaped(str.substring(escapeStart + 1, escapeEnd));
} else {
// \r\n
if (code === 0x000d && str.charCodeAt(i + 1) === 0x000a) {
i++;
}
}
} else {
decoded += str[i];
}
}
return decoded;
}
// https://drafts.csswg.org/cssom/#serialize-a-string
// § 2.1. Common Serializing Idioms
function encode$2(str, apostrophe) {
const quote = apostrophe ? '\'' : '"';
const quoteCode = apostrophe ? APOSTROPHE$1 : QUOTATION_MARK$1;
let encoded = '';
let wsBeforeHexIsNeeded = false;
for (let i = 0; i < str.length; i++) {
const code = str.charCodeAt(i);
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER (U+FFFD).
if (code === 0x0000) {
encoded += '\uFFFD';
continue;
}
// If the character is in the range [\1-\1f] (U+0001 to U+001F) or is U+007F,
// the character escaped as code point.
// Note: Do not compare with 0x0001 since 0x0000 is precessed before
if (code <= 0x001f || code === 0x007F) {
encoded += '\\' + code.toString(16);
wsBeforeHexIsNeeded = true;
continue;
}
// If the character is '"' (U+0022) or "\" (U+005C), the escaped character.
if (code === quoteCode || code === REVERSE_SOLIDUS$2) {
encoded += '\\' + str.charAt(i);
wsBeforeHexIsNeeded = false;
} else {
if (wsBeforeHexIsNeeded && (charCodeDefinitions$3.isHexDigit(code) || charCodeDefinitions$3.isWhiteSpace(code))) {
encoded += ' ';
}
// Otherwise, the character itself.
encoded += str.charAt(i);
wsBeforeHexIsNeeded = false;
}
}
return quote + encoded + quote;
}
string$3.decode = decode$2;
string$3.encode = encode$2;
const string$2 = string$3;
const types$b = types$S;
const name$7 = 'String';
const structure$6 = {
value: String
};
function parse$a() {
return {
type: 'String',
loc: this.getLocation(this.tokenStart, this.tokenEnd),
value: string$2.decode(this.consume(types$b.String))
};
}
function generate$a(node) {
this.token(types$b.String, string$2.encode(node.value));
}
_String.generate = generate$a;
_String.name = name$7;
_String.parse = parse$a;
_String.structure = structure$6;
var StyleSheet$2 = {};
const types$a = types$S;
const EXCLAMATIONMARK = 0x0021; // U+0021 EXCLAMATION MARK (!)
function consumeRaw$1(startToken) {
return this.Raw(startToken, null, false);
}
const name$6 = 'StyleSheet';
const walkContext = 'stylesheet';
const structure$5 = {
children: [[
'Comment',
'CDO',
'CDC',
'Atrule',
'Rule',
'Raw'
]]
};
function parse$9() {
const start = this.tokenStart;
const children = this.createList();
let child;
while (!this.eof) {
switch (this.tokenType) {
case types$a.WhiteSpace:
this.next();
continue;
case types$a.Comment:
// ignore comments except exclamation comments (i.e. /*! .. */) on top level
if (this.charCodeAt(this.tokenStart + 2) !== EXCLAMATIONMARK) {
this.next();
continue;
}
child = this.Comment();
break;
case types$a.CDO: // <!--
child = this.CDO();
break;
case types$a.CDC: // -->
child = this.CDC();
break;
// CSS Syntax Module Level 3
// §2.2 Error handling
// At the "top level" of a stylesheet, an <at-keyword-token> starts an at-rule.
case types$a.AtKeyword:
child = this.parseWithFallback(this.Atrule, consumeRaw$1);
break;
// Anything else starts a qualified rule ...
default:
child = this.parseWithFallback(this.Rule, consumeRaw$1);
}
children.push(child);
}
return {
type: 'StyleSheet',
loc: this.getLocation(start, this.tokenStart),
children
};
}
function generate$9(node) {
this.children(node);
}
StyleSheet$2.generate = generate$9;
StyleSheet$2.name = name$6;
StyleSheet$2.parse = parse$9;
StyleSheet$2.structure = structure$5;
StyleSheet$2.walkContext = walkContext;
var TypeSelector$4 = {};
const types$9 = types$S;
const ASTERISK$2 = 0x002A; // U+002A ASTERISK (*)
const VERTICALLINE$1 = 0x007C; // U+007C VERTICAL LINE (|)
function eatIdentifierOrAsterisk() {
if (this.tokenType !== types$9.Ident &&
this.isDelim(ASTERISK$2) === false) {
this.error('Identifier or asterisk is expected');
}
this.next();
}
const name$5 = 'TypeSelector';
const structure$4 = {
name: String
};
// ident
// ident|ident
// ident|*
// *
// *|ident
// *|*
// |ident
// |*
function parse$8() {
const start = this.tokenStart;
if (this.isDelim(VERTICALLINE$1)) {
this.next();
eatIdentifierOrAsterisk.call(this);
} else {
eatIdentifierOrAsterisk.call(this);
if (this.isDelim(VERTICALLINE$1)) {
this.next();
eatIdentifierOrAsterisk.call(this);
}
}
return {
type: 'TypeSelector',
loc: this.getLocation(start, this.tokenStart),
name: this.substrToCursor(start)
};
}
function generate$8(node) {
this.tokenize(node.name);
}
TypeSelector$4.generate = generate$8;
TypeSelector$4.name = name$5;
TypeSelector$4.parse = parse$8;
TypeSelector$4.structure = structure$4;
var UnicodeRange$2 = {};
const types$8 = types$S;
const charCodeDefinitions$2 = charCodeDefinitions$c;
const PLUSSIGN$2 = 0x002B; // U+002B PLUS SIGN (+)
const HYPHENMINUS$1 = 0x002D; // U+002D HYPHEN-MINUS (-)
const QUESTIONMARK = 0x003F; // U+003F QUESTION MARK (?)
function eatHexSequence(offset, allowDash) {
let len = 0;
for (let pos = this.tokenStart + offset; pos < this.tokenEnd; pos++) {
const code = this.charCodeAt(pos);
if (code === HYPHENMINUS$1 && allowDash && len !== 0) {
eatHexSequence.call(this, offset + len + 1, false);
return -1;
}
if (!charCodeDefinitions$2.isHexDigit(code)) {
this.error(
allowDash && len !== 0
? 'Hyphen minus' + (len < 6 ? ' or hex digit' : '') + ' is expected'
: (len < 6 ? 'Hex digit is expected' : 'Unexpected input'),
pos
);
}
if (++len > 6) {
this.error('Too many hex digits', pos);
} }
this.next();
return len;
}
function eatQuestionMarkSequence(max) {
let count = 0;
while (this.isDelim(QUESTIONMARK)) {
if (++count > max) {
this.error('Too many question marks');
}
this.next();
}
}
function startsWith(code) {
if (this.charCodeAt(this.tokenStart) !== code) {
this.error((code === PLUSSIGN$2 ? 'Plus sign' : 'Hyphen minus') + ' is expected');
}
}
// https://drafts.csswg.org/css-syntax/#urange
// Informally, the <urange> production has three forms:
// U+0001
// Defines a range consisting of a single code point, in this case the code point "1".
// U+0001-00ff
// Defines a range of codepoints between the first and the second value, in this case
// the range between "1" and "ff" (255 in decimal) inclusive.
// U+00??
// Defines a range of codepoints where the "?" characters range over all hex digits,
// in this case defining the same as the value U+0000-00ff.
// In each form, a maximum of 6 digits is allowed for each hexadecimal number (if you treat "?" as a hexadecimal digit).
//
// <urange> =
// u '+' <ident-token> '?'* |
// u <dimension-token> '?'* |
// u <number-token> '?'* |
// u <number-token> <dimension-token> |
// u <number-token> <number-token> |
// u '+' '?'+
function scanUnicodeRange() {
let hexLength = 0;
switch (this.tokenType) {
case types$8.Number:
// u <number-token> '?'*
// u <number-token> <dimension-token>
// u <number-token> <number-token>
hexLength = eatHexSequence.call(this, 1, true);
if (this.isDelim(QUESTIONMARK)) {
eatQuestionMarkSequence.call(this, 6 - hexLength);
break;
}
if (this.tokenType === types$8.Dimension ||
this.tokenType === types$8.Number) {
startsWith.call(this, HYPHENMINUS$1);
eatHexSequence.call(this, 1, false);
break;
}
break;
case types$8.Dimension:
// u <dimension-token> '?'*
hexLength = eatHexSequence.call(this, 1, true);
if (hexLength > 0) {
eatQuestionMarkSequence.call(this, 6 - hexLength);
}
break;
default:
// u '+' <ident-token> '?'*
// u '+' '?'+
this.eatDelim(PLUSSIGN$2);
if (this.tokenType === types$8.Ident) {
hexLength = eatHexSequence.call(this, 0, true);
if (hexLength > 0) {
eatQuestionMarkSequence.call(this, 6 - hexLength);
}
break;
}
if (this.isDelim(QUESTIONMARK)) {
this.next();
eatQuestionMarkSequence.call(this, 5);
break;
}
this.error('Hex digit or question mark is expected');
}
}
const name$4 = 'UnicodeRange';
const structure$3 = {
value: String
};
function parse$7() {
const start = this.tokenStart;
// U or u
this.eatIdent('u');
scanUnicodeRange.call(this);
return {
type: 'UnicodeRange',
loc: this.getLocation(start, this.tokenStart),
value: this.substrToCursor(start)
};
}
function generate$7(node) {
this.tokenize(node.value);
}
UnicodeRange$2.generate = generate$7;
UnicodeRange$2.name = name$4;
UnicodeRange$2.parse = parse$7;
UnicodeRange$2.structure = structure$3;
var Url$4 = {};
var url$2 = {};
const charCodeDefinitions$1 = charCodeDefinitions$c;
const utils$c = utils$k;
const SPACE$1 = 0x0020; // U+0020 SPACE
const REVERSE_SOLIDUS$1 = 0x005c; // U+005C REVERSE SOLIDUS (\)
const QUOTATION_MARK = 0x0022; // "
const APOSTROPHE = 0x0027; // '
const LEFTPARENTHESIS = 0x0028; // U+0028 LEFT PARENTHESIS (()
const RIGHTPARENTHESIS = 0x0029; // U+0029 RIGHT PARENTHESIS ())
function decode$1(str) {
const len = str.length;
let start = 4; // length of "url("
let end = str.charCodeAt(len - 1) === RIGHTPARENTHESIS ? len - 2 : len - 1;
let decoded = '';
while (start < end && charCodeDefinitions$1.isWhiteSpace(str.charCodeAt(start))) {
start++;
}
while (start < end && charCodeDefinitions$1.isWhiteSpace(str.charCodeAt(end))) {
end--;
}
for (let i = start; i <= end; i++) {
let code = str.charCodeAt(i);
if (code === REVERSE_SOLIDUS$1) {
// special case at the ending
if (i === end) {
// if the next input code point is EOF, do nothing
// otherwise include last left parenthesis as escaped
if (i !== len - 1) {
decoded = str.substr(i + 1);
}
break;
}
code = str.charCodeAt(++i);
// consume escaped
if (charCodeDefinitions$1.isValidEscape(REVERSE_SOLIDUS$1, code)) {
const escapeStart = i - 1;
const escapeEnd = utils$c.consumeEscaped(str, escapeStart);
i = escapeEnd - 1;
decoded += utils$c.decodeEscaped(str.substring(escapeStart + 1, escapeEnd));
} else {
// \r\n
if (code === 0x000d && str.charCodeAt(i + 1) === 0x000a) {
i++;
}
}
} else {
decoded += str[i];
}
}
return decoded;
}
function encode$1(str) {
let encoded = '';
let wsBeforeHexIsNeeded = false;
for (let i = 0; i < str.length; i++) {
const code = str.charCodeAt(i);
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER (U+FFFD).
if (code === 0x0000) {
encoded += '\uFFFD';
continue;
}
// If the character is in the range [\1-\1f] (U+0001 to U+001F) or is U+007F,
// the character escaped as code point.
// Note: Do not compare with 0x0001 since 0x0000 is precessed before
if (code <= 0x001f || code === 0x007F) {
encoded += '\\' + code.toString(16);
wsBeforeHexIsNeeded = true;
continue;
}
if (code === SPACE$1 ||
code === REVERSE_SOLIDUS$1 ||
code === QUOTATION_MARK ||
code === APOSTROPHE ||
code === LEFTPARENTHESIS ||
code === RIGHTPARENTHESIS) {
encoded += '\\' + str.charAt(i);
wsBeforeHexIsNeeded = false;
} else {
if (wsBeforeHexIsNeeded && charCodeDefinitions$1.isHexDigit(code)) {
encoded += ' ';
}
encoded += str.charAt(i);
wsBeforeHexIsNeeded = false;
}
}
return 'url(' + encoded + ')';
}
url$2.decode = decode$1;
url$2.encode = encode$1;
const url$1 = url$2;
const string$1 = string$3;
const types$7 = types$S;
const name$3 = 'Url';
const structure$2 = {
value: String
};
// <url-token> | <function-token> <string> )
function parse$6() {
const start = this.tokenStart;
let value;
switch (this.tokenType) {
case types$7.Url:
value = url$1.decode(this.consume(types$7.Url));
break;
case types$7.Function:
if (!this.cmpStr(this.tokenStart, this.tokenEnd, 'url(')) {
this.error('Function name must be `url`');
}
this.eat(types$7.Function);
this.skipSC();
value = string$1.decode(this.consume(types$7.String));
this.skipSC();
if (!this.eof) {
this.eat(types$7.RightParenthesis);
}
break;
default:
this.error('Url or Function is expected');
}
return {
type: 'Url',
loc: this.getLocation(start, this.tokenStart),
value
};
}
function generate$6(node) {
this.token(types$7.Url, url$1.encode(node.value));
}
Url$4.generate = generate$6;
Url$4.name = name$3;
Url$4.parse = parse$6;
Url$4.structure = structure$2;
var Value$4 = {};
const name$2 = 'Value';
const structure$1 = {
children: [[]]
};
function parse$5() {
const start = this.tokenStart;
const children = this.readSequence(this.scope.Value);
return {
type: 'Value',
loc: this.getLocation(start, this.tokenStart),
children
};
}
function generate$5(node) {
this.children(node);
}
Value$4.generate = generate$5;
Value$4.name = name$2;
Value$4.parse = parse$5;
Value$4.structure = structure$1;
var WhiteSpace$4 = {};
const types$6 = types$S;
const SPACE = Object.freeze({
type: 'WhiteSpace',
loc: null,
value: ' '
});
const name$1 = 'WhiteSpace';
const structure = {
value: String
};
function parse$4() {
this.eat(types$6.WhiteSpace);
return SPACE;
// return {
// type: 'WhiteSpace',
// loc: this.getLocation(this.tokenStart, this.tokenEnd),
// value: this.consume(WHITESPACE)
// };
}
function generate$4(node) {
this.token(types$6.WhiteSpace, node.value);
}
WhiteSpace$4.generate = generate$4;
WhiteSpace$4.name = name$1;
WhiteSpace$4.parse = parse$4;
WhiteSpace$4.structure = structure;
const AnPlusB$1 = AnPlusB$2;
const Atrule$5 = Atrule$6;
const AtrulePrelude$1 = AtrulePrelude$2;
const AttributeSelector$3 = AttributeSelector$4;
const Block$1 = Block$2;
const Brackets$1 = Brackets$2;
const CDC$1 = CDC$2;
const CDO$1 = CDO$2;
const ClassSelector$1 = ClassSelector$2;
const Combinator$1 = Combinator$2;
const Comment$3 = Comment$4;
const Declaration$3 = Declaration$4;
const DeclarationList$1 = DeclarationList$2;
const Dimension$3 = Dimension$4;
const Function$1 = _Function;
const Hash$1 = Hash$2;
const Identifier$1 = Identifier$2;
const IdSelector$1 = IdSelector$2;
const MediaFeature$1 = MediaFeature$2;
const MediaQuery$1 = MediaQuery$2;
const MediaQueryList$1 = MediaQueryList$2;
const Nth$1 = Nth$2;
const Number$1$1 = _Number$5;
const Operator$1 = Operator$2;
const Parentheses$1 = Parentheses$2;
const Percentage$3 = Percentage$4;
const PseudoClassSelector$1 = PseudoClassSelector$2;
const PseudoElementSelector$1 = PseudoElementSelector$2;
const Ratio$1 = Ratio$2;
const Raw$3 = Raw$4;
const Rule$3 = Rule$4;
const Selector$2 = Selector$3;
const SelectorList$1 = SelectorList$2;
const String$1$1 = _String;
const StyleSheet$1 = StyleSheet$2;
const TypeSelector$3 = TypeSelector$4;
const UnicodeRange$1 = UnicodeRange$2;
const Url$3 = Url$4;
const Value$3 = Value$4;
const WhiteSpace$3 = WhiteSpace$4;
node.AnPlusB = AnPlusB$1;
node.Atrule = Atrule$5;
node.AtrulePrelude = AtrulePrelude$1;
node.AttributeSelector = AttributeSelector$3;
node.Block = Block$1;
node.Brackets = Brackets$1;
node.CDC = CDC$1;
node.CDO = CDO$1;
node.ClassSelector = ClassSelector$1;
node.Combinator = Combinator$1;
node.Comment = Comment$3;
node.Declaration = Declaration$3;
node.DeclarationList = DeclarationList$1;
node.Dimension = Dimension$3;
node.Function = Function$1;
node.Hash = Hash$1;
node.Identifier = Identifier$1;
node.IdSelector = IdSelector$1;
node.MediaFeature = MediaFeature$1;
node.MediaQuery = MediaQuery$1;
node.MediaQueryList = MediaQueryList$1;
node.Nth = Nth$1;
node.Number = Number$1$1;
node.Operator = Operator$1;
node.Parentheses = Parentheses$1;
node.Percentage = Percentage$3;
node.PseudoClassSelector = PseudoClassSelector$1;
node.PseudoElementSelector = PseudoElementSelector$1;
node.Ratio = Ratio$1;
node.Raw = Raw$3;
node.Rule = Rule$3;
node.Selector = Selector$2;
node.SelectorList = SelectorList$1;
node.String = String$1$1;
node.StyleSheet = StyleSheet$1;
node.TypeSelector = TypeSelector$3;
node.UnicodeRange = UnicodeRange$1;
node.Url = Url$3;
node.Value = Value$3;
node.WhiteSpace = WhiteSpace$3;
const data = data$1;
const index$7 = node;
const lexerConfig = {
generic: true,
...data,
node: index$7
};
var lexer$3 = lexerConfig;
var scope = {};
const types$5 = types$S;
const NUMBERSIGN$1 = 0x0023; // U+0023 NUMBER SIGN (#)
const ASTERISK$1 = 0x002A; // U+002A ASTERISK (*)
const PLUSSIGN$1 = 0x002B; // U+002B PLUS SIGN (+)
const HYPHENMINUS = 0x002D; // U+002D HYPHEN-MINUS (-)
const SOLIDUS$1 = 0x002F; // U+002F SOLIDUS (/)
const U = 0x0075; // U+0075 LATIN SMALL LETTER U (u)
function defaultRecognizer(context) {
switch (this.tokenType) {
case types$5.Hash:
return this.Hash();
case types$5.Comma:
return this.Operator();
case types$5.LeftParenthesis:
return this.Parentheses(this.readSequence, context.recognizer);
case types$5.LeftSquareBracket:
return this.Brackets(this.readSequence, context.recognizer);
case types$5.String:
return this.String();
case types$5.Dimension:
return this.Dimension();
case types$5.Percentage:
return this.Percentage();
case types$5.Number:
return this.Number();
case types$5.Function:
return this.cmpStr(this.tokenStart, this.tokenEnd, 'url(')
? this.Url()
: this.Function(this.readSequence, context.recognizer);
case types$5.Url:
return this.Url();
case types$5.Ident:
// check for unicode range, it should start with u+ or U+
if (this.cmpChar(this.tokenStart, U) &&
this.cmpChar(this.tokenStart + 1, PLUSSIGN$1)) {
return this.UnicodeRange();
} else {
return this.Identifier();
}
case types$5.Delim: {
const code = this.charCodeAt(this.tokenStart);
if (code === SOLIDUS$1 ||
code === ASTERISK$1 ||
code === PLUSSIGN$1 ||
code === HYPHENMINUS) {
return this.Operator(); // TODO: replace with Delim
}
// TODO: produce a node with Delim node type
if (code === NUMBERSIGN$1) {
this.error('Hex or identifier is expected', this.tokenStart + 1);
}
break;
}
}
}
var _default$2 = defaultRecognizer;
const _default$1 = _default$2;
const atrulePrelude$1 = {
getNode: _default$1
};
var atrulePrelude_1 = atrulePrelude$1;
const types$4 = types$S;
const NUMBERSIGN = 0x0023; // U+0023 NUMBER SIGN (#)
const ASTERISK = 0x002A; // U+002A ASTERISK (*)
const PLUSSIGN = 0x002B; // U+002B PLUS SIGN (+)
const SOLIDUS = 0x002F; // U+002F SOLIDUS (/)
const FULLSTOP = 0x002E; // U+002E FULL STOP (.)
const GREATERTHANSIGN = 0x003E; // U+003E GREATER-THAN SIGN (>)
const VERTICALLINE = 0x007C; // U+007C VERTICAL LINE (|)
const TILDE = 0x007E; // U+007E TILDE (~)
function onWhiteSpace(next, children) {
if (children.last !== null && children.last.type !== 'Combinator' &&
next !== null && next.type !== 'Combinator') {
children.push({ // FIXME: this.Combinator() should be used instead
type: 'Combinator',
loc: null,
name: ' '
});
}
}
function getNode() {
switch (this.tokenType) {
case types$4.LeftSquareBracket:
return this.AttributeSelector();
case types$4.Hash:
return this.IdSelector();
case types$4.Colon:
if (this.lookupType(1) === types$4.Colon) {
return this.PseudoElementSelector();
} else {
return this.PseudoClassSelector();
}
case types$4.Ident:
return this.TypeSelector();
case types$4.Number:
case types$4.Percentage:
return this.Percentage();
case types$4.Dimension:
// throws when .123ident
if (this.charCodeAt(this.tokenStart) === FULLSTOP) {
this.error('Identifier is expected', this.tokenStart + 1);
}
break;
case types$4.Delim: {
const code = this.charCodeAt(this.tokenStart);
switch (code) {
case PLUSSIGN:
case GREATERTHANSIGN:
case TILDE:
case SOLIDUS: // /deep/
return this.Combinator();
case FULLSTOP:
return this.ClassSelector();
case ASTERISK:
case VERTICALLINE:
return this.TypeSelector();
case NUMBERSIGN:
return this.IdSelector();
}
break;
}
}
}
const Selector$1 = {
onWhiteSpace,
getNode
};
var selector$2 = Selector$1;
// legacy IE function
// expression( <any-value> )
function expressionFn() {
return this.createSingleNodeList(
this.Raw(this.tokenIndex, null, false)
);
}
var expression$1 = expressionFn;
const types$3 = types$S;
// var( <ident> , <value>? )
function varFn() {
const children = this.createList();
this.skipSC();
// NOTE: Don't check more than a first argument is an ident, rest checks are for lexer
children.push(this.Identifier());
this.skipSC();
if (this.tokenType === types$3.Comma) {
children.push(this.Operator());
const startIndex = this.tokenIndex;
const value = this.parseCustomProperty
? this.Value(null)
: this.Raw(this.tokenIndex, this.consumeUntilExclamationMarkOrSemicolon, false);
if (value.type === 'Value' && value.children.isEmpty) {
for (let offset = startIndex - this.tokenIndex; offset <= 0; offset++) {
if (this.lookupType(offset) === types$3.WhiteSpace) {
value.children.appendData({
type: 'WhiteSpace',
loc: null,
value: ' '
});
break;
}
}
}
children.push(value);
}
return children;
}
var _var$1 = varFn;
const _default = _default$2;
const expression = expression$1;
const _var = _var$1;
function isPlusMinusOperator(node) {
return (
node !== null &&
node.type === 'Operator' &&
(node.value[node.value.length - 1] === '-' || node.value[node.value.length - 1] === '+')
);
}
const value$1 = {
getNode: _default,
onWhiteSpace(next, children) {
if (isPlusMinusOperator(next)) {
next.value = ' ' + next.value;
}
if (isPlusMinusOperator(children.last)) {
children.last.value += ' ';
}
},
'expression': expression,
'var': _var
};
var value_1 = value$1;
const atrulePrelude = atrulePrelude_1;
const selector$1 = selector$2;
const value = value_1;
scope.AtrulePrelude = atrulePrelude;
scope.Selector = selector$1;
scope.Value = value;
const fontFace$1 = {
parse: {
prelude: null,
block() {
return this.Block(true);
}
}
};
var fontFace_1 = fontFace$1;
const types$2 = types$S;
const importAtrule = {
parse: {
prelude() {
const children = this.createList();
this.skipSC();
switch (this.tokenType) {
case types$2.String:
children.push(this.String());
break;
case types$2.Url:
case types$2.Function:
children.push(this.Url());
break;
default:
this.error('String or url() is expected');
}
if (this.lookupNonWSType(0) === types$2.Ident ||
this.lookupNonWSType(0) === types$2.LeftParenthesis) {
children.push(this.MediaQueryList());
}
return children;
},
block: null
}
};
var _import$1 = importAtrule;
const media$1 = {
parse: {
prelude() {
return this.createSingleNodeList(
this.MediaQueryList()
);
},
block() {
return this.Block(false);
}
}
};
var media_1 = media$1;
const page$1 = {
parse: {
prelude() {
return this.createSingleNodeList(
this.SelectorList()
);
},
block() {
return this.Block(true);
}
}
};
var page_1 = page$1;
const types$1 = types$S;
function consumeRaw() {
return this.createSingleNodeList(
this.Raw(this.tokenIndex, null, false)
);
}
function parentheses() {
this.skipSC();
if (this.tokenType === types$1.Ident &&
this.lookupNonWSType(1) === types$1.Colon) {
return this.createSingleNodeList(
this.Declaration()
);
}
return readSequence.call(this);
}
function readSequence() {
const children = this.createList();
let child;
this.skipSC();
scan:
while (!this.eof) {
switch (this.tokenType) {
case types$1.Comment:
case types$1.WhiteSpace:
this.next();
continue;
case types$1.Function:
child = this.Function(consumeRaw, this.scope.AtrulePrelude);
break;
case types$1.Ident:
child = this.Identifier();
break;
case types$1.LeftParenthesis:
child = this.Parentheses(parentheses, this.scope.AtrulePrelude);
break;
default:
break scan;
}
children.push(child);
}
return children;
}
const supports$1 = {
parse: {
prelude() {
const children = readSequence.call(this);
if (this.getFirstListNode(children) === null) {
this.error('Condition is expected');
}
return children;
},
block() {
return this.Block(false);
}
}
};
var supports_1 = supports$1;
const fontFace = fontFace_1;
const _import = _import$1;
const media = media_1;
const page = page_1;
const supports = supports_1;
const atrule = {
'font-face': fontFace,
'import': _import,
media,
page,
supports
};
var atrule_1 = atrule;
const selectorList = {
parse() {
return this.createSingleNodeList(
this.SelectorList()
);
}
};
const selector = {
parse() {
return this.createSingleNodeList(
this.Selector()
);
}
};
const identList = {
parse() {
return this.createSingleNodeList(
this.Identifier()
);
}
};
const nth = {
parse() {
return this.createSingleNodeList(
this.Nth()
);
}
};
const pseudo = {
'dir': identList,
'has': selectorList,
'lang': identList,
'matches': selectorList,
'is': selectorList,
'-moz-any': selectorList,
'-webkit-any': selectorList,
'where': selectorList,
'not': selectorList,
'nth-child': nth,
'nth-last-child': nth,
'nth-last-of-type': nth,
'nth-of-type': nth,
'slotted': selector
};
var pseudo_1 = pseudo;
var indexParse$1 = {};
const AnPlusB = AnPlusB$2;
const Atrule$4 = Atrule$6;
const AtrulePrelude = AtrulePrelude$2;
const AttributeSelector$2 = AttributeSelector$4;
const Block = Block$2;
const Brackets = Brackets$2;
const CDC = CDC$2;
const CDO = CDO$2;
const ClassSelector = ClassSelector$2;
const Combinator = Combinator$2;
const Comment$2 = Comment$4;
const Declaration$2 = Declaration$4;
const DeclarationList = DeclarationList$2;
const Dimension$2 = Dimension$4;
const Function = _Function;
const Hash = Hash$2;
const Identifier = Identifier$2;
const IdSelector = IdSelector$2;
const MediaFeature = MediaFeature$2;
const MediaQuery = MediaQuery$2;
const MediaQueryList = MediaQueryList$2;
const Nth = Nth$2;
const Number$2 = _Number$5;
const Operator = Operator$2;
const Parentheses = Parentheses$2;
const Percentage$2 = Percentage$4;
const PseudoClassSelector = PseudoClassSelector$2;
const PseudoElementSelector = PseudoElementSelector$2;
const Ratio = Ratio$2;
const Raw$2 = Raw$4;
const Rule$2 = Rule$4;
const Selector = Selector$3;
const SelectorList = SelectorList$2;
const String$1 = _String;
const StyleSheet = StyleSheet$2;
const TypeSelector$2 = TypeSelector$4;
const UnicodeRange = UnicodeRange$2;
const Url$2 = Url$4;
const Value$2 = Value$4;
const WhiteSpace$2 = WhiteSpace$4;
indexParse$1.AnPlusB = AnPlusB.parse;
indexParse$1.Atrule = Atrule$4.parse;
indexParse$1.AtrulePrelude = AtrulePrelude.parse;
indexParse$1.AttributeSelector = AttributeSelector$2.parse;
indexParse$1.Block = Block.parse;
indexParse$1.Brackets = Brackets.parse;
indexParse$1.CDC = CDC.parse;
indexParse$1.CDO = CDO.parse;
indexParse$1.ClassSelector = ClassSelector.parse;
indexParse$1.Combinator = Combinator.parse;
indexParse$1.Comment = Comment$2.parse;
indexParse$1.Declaration = Declaration$2.parse;
indexParse$1.DeclarationList = DeclarationList.parse;
indexParse$1.Dimension = Dimension$2.parse;
indexParse$1.Function = Function.parse;
indexParse$1.Hash = Hash.parse;
indexParse$1.Identifier = Identifier.parse;
indexParse$1.IdSelector = IdSelector.parse;
indexParse$1.MediaFeature = MediaFeature.parse;
indexParse$1.MediaQuery = MediaQuery.parse;
indexParse$1.MediaQueryList = MediaQueryList.parse;
indexParse$1.Nth = Nth.parse;
indexParse$1.Number = Number$2.parse;
indexParse$1.Operator = Operator.parse;
indexParse$1.Parentheses = Parentheses.parse;
indexParse$1.Percentage = Percentage$2.parse;
indexParse$1.PseudoClassSelector = PseudoClassSelector.parse;
indexParse$1.PseudoElementSelector = PseudoElementSelector.parse;
indexParse$1.Ratio = Ratio.parse;
indexParse$1.Raw = Raw$2.parse;
indexParse$1.Rule = Rule$2.parse;
indexParse$1.Selector = Selector.parse;
indexParse$1.SelectorList = SelectorList.parse;
indexParse$1.String = String$1.parse;
indexParse$1.StyleSheet = StyleSheet.parse;
indexParse$1.TypeSelector = TypeSelector$2.parse;
indexParse$1.UnicodeRange = UnicodeRange.parse;
indexParse$1.Url = Url$2.parse;
indexParse$1.Value = Value$2.parse;
indexParse$1.WhiteSpace = WhiteSpace$2.parse;
const index$6 = scope;
const index$1$2 = atrule_1;
const index$2$1 = pseudo_1;
const indexParse = indexParse$1;
const config$1 = {
parseContext: {
default: 'StyleSheet',
stylesheet: 'StyleSheet',
atrule: 'Atrule',
atrulePrelude(options) {
return this.AtrulePrelude(options.atrule ? String(options.atrule) : null);
},
mediaQueryList: 'MediaQueryList',
mediaQuery: 'MediaQuery',
rule: 'Rule',
selectorList: 'SelectorList',
selector: 'Selector',
block() {
return this.Block(true);
},
declarationList: 'DeclarationList',
declaration: 'Declaration',
value: 'Value'
},
scope: index$6,
atrule: index$1$2,
pseudo: index$2$1,
node: indexParse
};
var parser$1 = config$1;
const index$5 = node;
const config = {
node: index$5
};
var walker$1 = config;
const create$1 = create_1;
const lexer$2 = lexer$3;
const parser = parser$1;
const walker = walker$1;
const syntax$1 = create$1({
...lexer$2,
...parser,
...walker
});
var syntax_1 = syntax$1;
var version$4 = {};
const name = "css-tree";
const version$3 = "2.2.1";
const description = "A tool set for CSS: fast detailed parser (CSS → AST), walker (AST traversal), generator (AST → CSS) and lexer (validation and matching) based on specs and browser implementations";
const author = "Roman Dvornov <rdvornov@gmail.com> (https://github.com/lahmatiy)";
const license = "MIT";
const repository = "csstree/csstree";
const keywords = [
"css",
"ast",
"tokenizer",
"parser",
"walker",
"lexer",
"generator",
"utils",
"syntax",
"validation"
];
const type = "module";
const module = "./lib/index.js";
const main = "./cjs/index.cjs";
const exports = {
".": {
"import": "./lib/index.js",
require: "./cjs/index.cjs"
},
"./dist/*": "./dist/*.js",
"./package.json": "./package.json",
"./tokenizer": {
"import": "./lib/tokenizer/index.js",
require: "./cjs/tokenizer/index.cjs"
},
"./parser": {
"import": "./lib/parser/index.js",
require: "./cjs/parser/index.cjs"
},
"./selector-parser": {
"import": "./lib/parser/parse-selector.js",
require: "./cjs/parser/parse-selector.cjs"
},
"./generator": {
"import": "./lib/generator/index.js",
require: "./cjs/generator/index.cjs"
},
"./walker": {
"import": "./lib/walker/index.js",
require: "./cjs/walker/index.cjs"
},
"./convertor": {
"import": "./lib/convertor/index.js",
require: "./cjs/convertor/index.cjs"
},
"./lexer": {
"import": "./lib/lexer/index.js",
require: "./cjs/lexer/index.cjs"
},
"./definition-syntax": {
"import": "./lib/definition-syntax/index.js",
require: "./cjs/definition-syntax/index.cjs"
},
"./definition-syntax-data": {
"import": "./lib/data.js",
require: "./cjs/data.cjs"
},
"./definition-syntax-data-patch": {
"import": "./lib/data-patch.js",
require: "./cjs/data-patch.cjs"
},
"./utils": {
"import": "./lib/utils/index.js",
require: "./cjs/utils/index.cjs"
}
};
const browser = {
"./cjs/data.cjs": "./dist/data.cjs",
"./cjs/version.cjs": "./dist/version.cjs",
"./lib/data.js": "./dist/data.js",
"./lib/version.js": "./dist/version.js"
};
const unpkg = "dist/csstree.esm.js";
const jsdelivr = "dist/csstree.esm.js";
const scripts = {
watch: "npm run build -- --watch",
build: "npm run bundle && npm run esm-to-cjs --",
"build-and-test": "npm run build && npm run test:dist && npm run test:cjs",
bundle: "node scripts/bundle",
"bundle-and-test": "npm run bundle && npm run test:dist",
"esm-to-cjs": "node scripts/esm-to-cjs.cjs",
"esm-to-cjs-and-test": "npm run esm-to-cjs && npm run test:cjs",
lint: "eslint lib scripts && node scripts/review-syntax-patch --lint && node scripts/update-docs --lint",
"lint-and-test": "npm run lint && npm test",
"update:docs": "node scripts/update-docs",
"review:syntax-patch": "node scripts/review-syntax-patch",
test: "mocha lib/__tests --reporter ${REPORTER:-progress}",
"test:cjs": "mocha cjs/__tests --reporter ${REPORTER:-progress}",
"test:dist": "mocha dist/__tests --reporter ${REPORTER:-progress}",
coverage: "c8 --exclude lib/__tests --reporter=lcovonly npm test",
prepublishOnly: "npm run lint-and-test && npm run build-and-test",
hydrogen: "node --trace-hydrogen --trace-phase=Z --trace-deopt --code-comments --hydrogen-track-positions --redirect-code-traces --redirect-code-traces-to=code.asm --trace_hydrogen_file=code.cfg --print-opt-code bin/parse --stat -o /dev/null"
};
const dependencies = {
"mdn-data": "2.0.28",
"source-map-js": "^1.0.1"
};
const devDependencies = {
c8: "^7.7.1",
clap: "^2.0.1",
esbuild: "^0.14.53",
eslint: "^8.4.1",
"json-to-ast": "^2.1.0",
mocha: "^9.1.4",
rollup: "^2.68.0"
};
const engines = {
node: "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
npm: ">=7.0.0"
};
const files = [
"data",
"dist",
"cjs",
"!cjs/__tests",
"lib",
"!lib/__tests"
];
const require$$0 = {
name: name,
version: version$3,
description: description,
author: author,
license: license,
repository: repository,
keywords: keywords,
type: type,
module: module,
main: main,
exports: exports,
browser: browser,
unpkg: unpkg,
jsdelivr: jsdelivr,
scripts: scripts,
dependencies: dependencies,
devDependencies: devDependencies,
engines: engines,
files: files
};
const { version: version$2 } = require$$0;
version$4.version = version$2;
var definitionSyntax = {};
const SyntaxError$1 = _SyntaxError;
const generate$3 = generate$L;
const parse$3 = parse$L;
const walk$2 = walk$5;
definitionSyntax.SyntaxError = SyntaxError$1.SyntaxError;
definitionSyntax.generate = generate$3.generate;
definitionSyntax.parse = parse$3.parse;
definitionSyntax.walk = walk$2.walk;
var clone$2 = {};
const List$1 = List$7;
function clone$1(node) {
const result = {};
for (const key in node) {
let value = node[key];
if (value) {
if (Array.isArray(value) || value instanceof List$1.List) {
value = value.map(clone$1);
} else if (value.constructor === Object) {
value = clone$1(value);
}
}
result[key] = value;
}
return result;
}
clone$2.clone = clone$1;
var ident$1 = {};
const charCodeDefinitions = charCodeDefinitions$c;
const utils$b = utils$k;
const REVERSE_SOLIDUS = 0x005c; // U+005C REVERSE SOLIDUS (\)
function decode(str) {
const end = str.length - 1;
let decoded = '';
for (let i = 0; i < str.length; i++) {
let code = str.charCodeAt(i);
if (code === REVERSE_SOLIDUS) {
// special case at the ending
if (i === end) {
// if the next input code point is EOF, do nothing
break;
}
code = str.charCodeAt(++i);
// consume escaped
if (charCodeDefinitions.isValidEscape(REVERSE_SOLIDUS, code)) {
const escapeStart = i - 1;
const escapeEnd = utils$b.consumeEscaped(str, escapeStart);
i = escapeEnd - 1;
decoded += utils$b.decodeEscaped(str.substring(escapeStart + 1, escapeEnd));
} else {
// \r\n
if (code === 0x000d && str.charCodeAt(i + 1) === 0x000a) {
i++;
}
}
} else {
decoded += str[i];
}
}
return decoded;
}
// https://drafts.csswg.org/cssom/#serialize-an-identifier
// § 2.1. Common Serializing Idioms
function encode(str) {
let encoded = '';
// If the character is the first character and is a "-" (U+002D),
// and there is no second character, then the escaped character.
// Note: That's means a single dash string "-" return as escaped dash,
// so move the condition out of the main loop
if (str.length === 1 && str.charCodeAt(0) === 0x002D) {
return '\\-';
}
// To serialize an identifier means to create a string represented
// by the concatenation of, for each character of the identifier:
for (let i = 0; i < str.length; i++) {
const code = str.charCodeAt(i);
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER (U+FFFD).
if (code === 0x0000) {
encoded += '\uFFFD';
continue;
}
if (
// If the character is in the range [\1-\1f] (U+0001 to U+001F) or is U+007F ...
// Note: Do not compare with 0x0001 since 0x0000 is precessed before
code <= 0x001F || code === 0x007F ||
// [or] ... is in the range [0-9] (U+0030 to U+0039),
(code >= 0x0030 && code <= 0x0039 && (
// If the character is the first character ...
i === 0 ||
// If the character is the second character ... and the first character is a "-" (U+002D)
i === 1 && str.charCodeAt(0) === 0x002D
))
) {
// ... then the character escaped as code point.
encoded += '\\' + code.toString(16) + ' ';
continue;
}
// If the character is not handled by one of the above rules and is greater
// than or equal to U+0080, is "-" (U+002D) or "_" (U+005F), or is in one
// of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to U+005A),
// or \[a-z] (U+0061 to U+007A), then the character itself.
if (charCodeDefinitions.isName(code)) {
encoded += str.charAt(i);
} else {
// Otherwise, the escaped character.
encoded += '\\' + str.charAt(i);
}
}
return encoded;
}
ident$1.decode = decode;
ident$1.encode = encode;
const index$1$1 = syntax_1;
const version$1 = version$4;
const create = create_1;
const List = List$7;
const Lexer = Lexer$3;
const index$4 = definitionSyntax;
const clone = clone$2;
const names$1 = names$4;
const ident = ident$1;
const string = string$3;
const url = url$2;
const types = types$S;
const names = names$8;
const TokenStream = TokenStream$4;
const {
tokenize: tokenize$1,
parse: parse$2,
generate: generate$2,
lexer: lexer$1,
createLexer,
walk: walk$1,
find: find$1,
findLast: findLast$1,
findAll: findAll$1,
toPlainObject: toPlainObject$1,
fromPlainObject: fromPlainObject$1,
fork
} = index$1$1;
cjs.version = version$1.version;
cjs.createSyntax = create;
cjs.List = List.List;
cjs.Lexer = Lexer.Lexer;
cjs.definitionSyntax = index$4;
cjs.clone = clone.clone;
cjs.isCustomProperty = names$1.isCustomProperty;
cjs.keyword = names$1.keyword;
cjs.property = names$1.property;
cjs.vendorPrefix = names$1.vendorPrefix;
cjs.ident = ident;
cjs.string = string;
cjs.url = url;
cjs.tokenTypes = types;
cjs.tokenNames = names;
cjs.TokenStream = TokenStream.TokenStream;
cjs.createLexer = createLexer;
cjs.find = find$1;
cjs.findAll = findAll$1;
cjs.findLast = findLast$1;
cjs.fork = fork;
cjs.fromPlainObject = fromPlainObject$1;
cjs.generate = generate$2;
cjs.lexer = lexer$1;
cjs.parse = parse$2;
cjs.toPlainObject = toPlainObject$1;
cjs.tokenize = tokenize$1;
cjs.walk = walk$1;
var usage$1 = {};
const { hasOwnProperty: hasOwnProperty$4 } = Object.prototype;
function buildMap(list, caseInsensitive) {
const map = Object.create(null);
if (!Array.isArray(list)) {
return null;
}
for (let name of list) {
if (caseInsensitive) {
name = name.toLowerCase();
}
map[name] = true;
}
return map;
}
function buildList(data) {
if (!data) {
return null;
}
const tags = buildMap(data.tags, true);
const ids = buildMap(data.ids);
const classes = buildMap(data.classes);
if (tags === null &&
ids === null &&
classes === null) {
return null;
}
return {
tags,
ids,
classes
};
}
function buildIndex(data) {
let scopes = false;
if (data.scopes && Array.isArray(data.scopes)) {
scopes = Object.create(null);
for (let i = 0; i < data.scopes.length; i++) {
const list = data.scopes[i];
if (!list || !Array.isArray(list)) {
throw new Error('Wrong usage format');
}
for (const name of list) {
if (hasOwnProperty$4.call(scopes, name)) {
throw new Error(`Class can't be used for several scopes: ${name}`);
}
scopes[name] = i + 1;
}
}
}
return {
whitelist: buildList(data),
blacklist: buildList(data.blacklist),
scopes
};
}
usage$1.buildIndex = buildIndex;
var utils$a = {};
function hasNoChildren(node) {
return !node || !node.children || node.children.isEmpty;
}
function isNodeChildrenList(node, list) {
return node !== null && node.children === list;
}
utils$a.hasNoChildren = hasNoChildren;
utils$a.isNodeChildrenList = isNodeChildrenList;
const cssTree$m = cjs;
const utils$9 = utils$a;
function cleanAtrule(node, item, list) {
if (node.block) {
// otherwise removed at-rule don't prevent @import for removal
if (this.stylesheet !== null) {
this.stylesheet.firstAtrulesAllowed = false;
}
if (utils$9.hasNoChildren(node.block)) {
list.remove(item);
return;
}
}
switch (node.name) {
case 'charset':
if (utils$9.hasNoChildren(node.prelude)) {
list.remove(item);
return;
}
// if there is any rule before @charset -> remove it
if (item.prev) {
list.remove(item);
return;
}
break;
case 'import':
if (this.stylesheet === null || !this.stylesheet.firstAtrulesAllowed) {
list.remove(item);
return;
}
// if there are some rules that not an @import or @charset before @import
// remove it
list.prevUntil(item.prev, function(rule) {
if (rule.type === 'Atrule') {
if (rule.name === 'import' || rule.name === 'charset') {
return;
}
}
this.root.firstAtrulesAllowed = false;
list.remove(item);
return true;
}, this);
break;
default: {
const name = cssTree$m.keyword(node.name).basename;
if (name === 'keyframes' ||
name === 'media' ||
name === 'supports') {
// drop at-rule with no prelude
if (utils$9.hasNoChildren(node.prelude) || utils$9.hasNoChildren(node.block)) {
list.remove(item);
}
}
}
}
}
var Atrule$3 = cleanAtrule;
function cleanComment(data, item, list) {
list.remove(item);
}
var Comment$1 = cleanComment;
const cssTree$l = cjs;
function cleanDeclartion(node, item, list) {
if (node.value.children && node.value.children.isEmpty) {
list.remove(item);
return;
}
if (cssTree$l.property(node.property).custom) {
if (/\S/.test(node.value.value)) {
node.value.value = node.value.value.trim();
}
}
}
var Declaration$1 = cleanDeclartion;
const utils$8 = utils$a;
function cleanRaw(node, item, list) {
// raw in stylesheet or block children
if (utils$8.isNodeChildrenList(this.stylesheet, list) ||
utils$8.isNodeChildrenList(this.block, list)) {
list.remove(item);
}
}
var Raw$1 = cleanRaw;
const cssTree$k = cjs;
const utils$7 = utils$a;
const { hasOwnProperty: hasOwnProperty$3 } = Object.prototype;
const skipUsageFilteringAtrule = new Set(['keyframes']);
function cleanUnused(selectorList, usageData) {
selectorList.children.forEach((selector, item, list) => {
let shouldRemove = false;
cssTree$k.walk(selector, function(node) {
// ignore nodes in nested selectors
if (this.selector === null || this.selector === selectorList) {
switch (node.type) {
case 'SelectorList':
// TODO: remove toLowerCase when pseudo selectors will be normalized
// ignore selectors inside :not()
if (this.function === null || this.function.name.toLowerCase() !== 'not') {
if (cleanUnused(node, usageData)) {
shouldRemove = true;
}
}
break;
case 'ClassSelector':
if (usageData.whitelist !== null &&
usageData.whitelist.classes !== null &&
!hasOwnProperty$3.call(usageData.whitelist.classes, node.name)) {
shouldRemove = true;
}
if (usageData.blacklist !== null &&
usageData.blacklist.classes !== null &&
hasOwnProperty$3.call(usageData.blacklist.classes, node.name)) {
shouldRemove = true;
}
break;
case 'IdSelector':
if (usageData.whitelist !== null &&
usageData.whitelist.ids !== null &&
!hasOwnProperty$3.call(usageData.whitelist.ids, node.name)) {
shouldRemove = true;
}
if (usageData.blacklist !== null &&
usageData.blacklist.ids !== null &&
hasOwnProperty$3.call(usageData.blacklist.ids, node.name)) {
shouldRemove = true;
}
break;
case 'TypeSelector':
// TODO: remove toLowerCase when type selectors will be normalized
// ignore universal selectors
if (node.name.charAt(node.name.length - 1) !== '*') {
if (usageData.whitelist !== null &&
usageData.whitelist.tags !== null &&
!hasOwnProperty$3.call(usageData.whitelist.tags, node.name.toLowerCase())) {
shouldRemove = true;
}
if (usageData.blacklist !== null &&
usageData.blacklist.tags !== null &&
hasOwnProperty$3.call(usageData.blacklist.tags, node.name.toLowerCase())) {
shouldRemove = true;
}
}
break;
}
}
});
if (shouldRemove) {
list.remove(item);
}
});
return selectorList.children.isEmpty;
}
function cleanRule(node, item, list, options) {
if (utils$7.hasNoChildren(node.prelude) || utils$7.hasNoChildren(node.block)) {
list.remove(item);
return;
}
// avoid usage filtering for some at-rules
if (this.atrule && skipUsageFilteringAtrule.has(cssTree$k.keyword(this.atrule.name).basename)) {
return;
}
const { usage } = options;
if (usage && (usage.whitelist !== null || usage.blacklist !== null)) {
cleanUnused(node.prelude, usage);
if (utils$7.hasNoChildren(node.prelude)) {
list.remove(item);
return;
}
}
}
var Rule$1 = cleanRule;
// remove useless universal selector
function cleanTypeSelector(node, item, list) {
const name = item.data.name;
// check it's a non-namespaced universal selector
if (name !== '*') {
return;
}
// remove when universal selector before other selectors
const nextType = item.next && item.next.data.type;
if (nextType === 'IdSelector' ||
nextType === 'ClassSelector' ||
nextType === 'AttributeSelector' ||
nextType === 'PseudoClassSelector' ||
nextType === 'PseudoElementSelector') {
list.remove(item);
}
}
var TypeSelector$1 = cleanTypeSelector;
function cleanWhitespace(node, item, list) {
list.remove(item);
}
var WhiteSpace$1 = cleanWhitespace;
const cssTree$j = cjs;
const Atrule$2 = Atrule$3;
const Comment = Comment$1;
const Declaration = Declaration$1;
const Raw = Raw$1;
const Rule = Rule$1;
const TypeSelector = TypeSelector$1;
const WhiteSpace = WhiteSpace$1;
const handlers$2 = {
Atrule: Atrule$2,
Comment,
Declaration,
Raw,
Rule,
TypeSelector,
WhiteSpace
};
function clean(ast, options) {
cssTree$j.walk(ast, {
leave(node, item, list) {
if (handlers$2.hasOwnProperty(node.type)) {
handlers$2[node.type].call(this, node, item, list, options);
}
}
});
}
var clean_1 = clean;
function compressKeyframes(node) {
node.block.children.forEach((rule) => {
rule.prelude.children.forEach((simpleselector) => {
simpleselector.children.forEach((data, item) => {
if (data.type === 'Percentage' && data.value === '100') {
item.data = {
type: 'TypeSelector',
loc: data.loc,
name: 'to'
};
} else if (data.type === 'TypeSelector' && data.name === 'from') {
item.data = {
type: 'Percentage',
loc: data.loc,
value: '0'
};
}
});
});
});
}
var keyframes$1 = compressKeyframes;
const cssTree$i = cjs;
const keyframes = keyframes$1;
function Atrule$1(node) {
// compress @keyframe selectors
if (cssTree$i.keyword(node.name).basename === 'keyframes') {
keyframes(node);
}
}
var Atrule_1 = Atrule$1;
// Can unquote attribute detection
// Adopted implementation of Mathias Bynens
// https://github.com/mathiasbynens/mothereff.in/blob/master/unquoted-attributes/eff.js
const blockUnquoteRx = /^(-?\d|--)|[\u0000-\u002c\u002e\u002f\u003A-\u0040\u005B-\u005E\u0060\u007B-\u009f]/;
function canUnquote(value) {
if (value === '' || value === '-') {
return false;
}
return !blockUnquoteRx.test(value);
}
function AttributeSelector$1(node) {
const attrValue = node.value;
if (!attrValue || attrValue.type !== 'String') {
return;
}
if (canUnquote(attrValue.value)) {
node.value = {
type: 'Identifier',
loc: attrValue.loc,
name: attrValue.value
};
}
}
var AttributeSelector_1 = AttributeSelector$1;
function compressFont(node) {
const list = node.children;
list.forEachRight(function(node, item) {
if (node.type === 'Identifier') {
if (node.name === 'bold') {
item.data = {
type: 'Number',
loc: node.loc,
value: '700'
};
} else if (node.name === 'normal') {
const prev = item.prev;
if (prev && prev.data.type === 'Operator' && prev.data.value === '/') {
this.remove(prev);
}
this.remove(item);
}
}
});
if (list.isEmpty) {
list.insert(list.createItem({
type: 'Identifier',
name: 'normal'
}));
}
}
var font$1 = compressFont;
function compressFontWeight(node) {
const value = node.children.head.data;
if (value.type === 'Identifier') {
switch (value.name) {
case 'normal':
node.children.head.data = {
type: 'Number',
loc: value.loc,
value: '400'
};
break;
case 'bold':
node.children.head.data = {
type: 'Number',
loc: value.loc,
value: '700'
};
break;
}
}
}
var fontWeight$1 = compressFontWeight;
const cssTree$h = cjs;
function compressBackground(node) {
function flush() {
if (!buffer.length) {
buffer.unshift(
{
type: 'Number',
loc: null,
value: '0'
},
{
type: 'Number',
loc: null,
value: '0'
}
);
}
newValue.push.apply(newValue, buffer);
buffer = [];
}
let newValue = [];
let buffer = [];
node.children.forEach((node) => {
if (node.type === 'Operator' && node.value === ',') {
flush();
newValue.push(node);
return;
}
// remove defaults
if (node.type === 'Identifier') {
if (node.name === 'transparent' ||
node.name === 'none' ||
node.name === 'repeat' ||
node.name === 'scroll') {
return;
}
}
buffer.push(node);
});
flush();
node.children = new cssTree$h.List().fromArray(newValue);
}
var background$1 = compressBackground;
function compressBorder(node) {
node.children.forEach((node, item, list) => {
if (node.type === 'Identifier' && node.name.toLowerCase() === 'none') {
if (list.head === list.tail) {
// replace `none` for zero when `none` is a single term
item.data = {
type: 'Number',
loc: node.loc,
value: '0'
};
} else {
list.remove(item);
}
}
});
}
var border$1 = compressBorder;
const cssTree$g = cjs;
const font = font$1;
const fontWeight = fontWeight$1;
const background = background$1;
const border = border$1;
const handlers$1 = {
'font': font,
'font-weight': fontWeight,
'background': background,
'border': border,
'outline': border
};
function compressValue(node) {
if (!this.declaration) {
return;
}
const property = cssTree$g.property(this.declaration.property);
if (handlers$1.hasOwnProperty(property.basename)) {
handlers$1[property.basename](node);
}
}
var Value$1 = compressValue;
var _Number$4 = {};
const OMIT_PLUSSIGN = /^(?:\+|(-))?0*(\d*)(?:\.0*|(\.\d*?)0*)?$/;
const KEEP_PLUSSIGN = /^([\+\-])?0*(\d*)(?:\.0*|(\.\d*?)0*)?$/;
const unsafeToRemovePlusSignAfter = new Set([
'Dimension',
'Hash',
'Identifier',
'Number',
'Raw',
'UnicodeRange'
]);
function packNumber(value, item) {
// omit plus sign only if no prev or prev is safe type
const regexp = item && item.prev !== null && unsafeToRemovePlusSignAfter.has(item.prev.data.type)
? KEEP_PLUSSIGN
: OMIT_PLUSSIGN;
// 100 -> '100'
// 00100 -> '100'
// +100 -> '100'
// -100 -> '-100'
// 0.123 -> '.123'
// 0.12300 -> '.123'
// 0.0 -> ''
// 0 -> ''
// -0 -> '-'
value = String(value).replace(regexp, '$1$2$3');
if (value === '' || value === '-') {
value = '0';
}
// FIXME: is it solution simplier?
// value = String(Number(value)).replace(/^(-?)0+\./, '$1.');
return value;
}
function Number$1(node) {
node.value = packNumber(node.value);
}
_Number$4.Number = Number$1;
_Number$4.packNumber = packNumber;
const _Number$3 = _Number$4;
const MATH_FUNCTIONS = new Set([
'calc',
'min',
'max',
'clamp'
]);
const LENGTH_UNIT = new Set([
// absolute length units
'px',
'mm',
'cm',
'in',
'pt',
'pc',
// relative length units
'em',
'ex',
'ch',
'rem',
// viewport-percentage lengths
'vh',
'vw',
'vmin',
'vmax',
'vm'
]);
function compressDimension(node, item) {
const value = _Number$3.packNumber(node.value);
node.value = value;
if (value === '0' && this.declaration !== null && this.atrulePrelude === null) {
const unit = node.unit.toLowerCase();
// only length values can be compressed
if (!LENGTH_UNIT.has(unit)) {
return;
}
// issue #362: shouldn't remove unit in -ms-flex since it breaks flex in IE10/11
// issue #200: shouldn't remove unit in flex since it breaks flex in IE10/11
if (this.declaration.property === '-ms-flex' ||
this.declaration.property === 'flex') {
return;
}
// issue #222: don't remove units inside calc
if (this.function && MATH_FUNCTIONS.has(this.function.name)) {
return;
}
item.data = {
type: 'Number',
loc: node.loc,
value
};
}
}
var Dimension$1 = compressDimension;
const cssTree$f = cjs;
const _Number$2 = _Number$4;
const blacklist = new Set([
// see https://github.com/jakubpawlowicz/clean-css/issues/957
'width',
'min-width',
'max-width',
'height',
'min-height',
'max-height',
// issue #410: Dont remove units in flex-basis value for (-ms-)flex shorthand
// issue #362: shouldn't remove unit in -ms-flex since it breaks flex in IE10/11
// issue #200: shouldn't remove unit in flex since it breaks flex in IE10/11
'flex',
'-ms-flex'
]);
function compressPercentage(node, item) {
node.value = _Number$2.packNumber(node.value);
if (node.value === '0' && this.declaration && !blacklist.has(this.declaration.property)) {
// try to convert a number
item.data = {
type: 'Number',
loc: node.loc,
value: node.value
};
// that's ok only when new value matches on length
if (!cssTree$f.lexer.matchDeclaration(this.declaration).isType(item.data, 'length')) {
// otherwise rollback changes
item.data = node;
}
}
}
var Percentage$1 = compressPercentage;
function Url$1(node) {
// convert `\\` to `/`
node.value = node.value.replace(/\\/g, '/');
}
var Url_1 = Url$1;
var color$1 = {};
const cssTree$e = cjs;
const _Number$1 = _Number$4;
// http://www.w3.org/TR/css3-color/#svg-color
const NAME_TO_HEX = {
'aliceblue': 'f0f8ff',
'antiquewhite': 'faebd7',
'aqua': '0ff',
'aquamarine': '7fffd4',
'azure': 'f0ffff',
'beige': 'f5f5dc',
'bisque': 'ffe4c4',
'black': '000',
'blanchedalmond': 'ffebcd',
'blue': '00f',
'blueviolet': '8a2be2',
'brown': 'a52a2a',
'burlywood': 'deb887',
'cadetblue': '5f9ea0',
'chartreuse': '7fff00',
'chocolate': 'd2691e',
'coral': 'ff7f50',
'cornflowerblue': '6495ed',
'cornsilk': 'fff8dc',
'crimson': 'dc143c',
'cyan': '0ff',
'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': 'f0f',
'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': '789',
'lightslategrey': '789',
'lightsteelblue': 'b0c4de',
'lightyellow': 'ffffe0',
'lime': '0f0',
'limegreen': '32cd32',
'linen': 'faf0e6',
'magenta': 'f0f',
'maroon': '800000',
'mediumaquamarine': '66cdaa',
'mediumblue': '0000cd',
'mediumorchid': 'ba55d3',
'mediumpurple': '9370db',
'mediumseagreen': '3cb371',
'mediumslateblue': '7b68ee',
'mediumspringgreen': '00fa9a',
'mediumturquoise': '48d1cc',
'mediumvioletred': 'c71585',
'midnightblue': '191970',
'mintcream': 'f5fffa',
'mistyrose': 'ffe4e1',
'moccasin': 'ffe4b5',
'navajowhite': 'ffdead',
'navy': '000080',
'oldlace': 'fdf5e6',
'olive': '808000',
'olivedrab': '6b8e23',
'orange': 'ffa500',
'orangered': 'ff4500',
'orchid': 'da70d6',
'palegoldenrod': 'eee8aa',
'palegreen': '98fb98',
'paleturquoise': 'afeeee',
'palevioletred': 'db7093',
'papayawhip': 'ffefd5',
'peachpuff': 'ffdab9',
'peru': 'cd853f',
'pink': 'ffc0cb',
'plum': 'dda0dd',
'powderblue': 'b0e0e6',
'purple': '800080',
'rebeccapurple': '639',
'red': 'f00',
'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': 'fff',
'whitesmoke': 'f5f5f5',
'yellow': 'ff0',
'yellowgreen': '9acd32'
};
const HEX_TO_NAME = {
'800000': 'maroon',
'800080': 'purple',
'808000': 'olive',
'808080': 'gray',
'00ffff': 'cyan',
'f0ffff': 'azure',
'f5f5dc': 'beige',
'ffe4c4': 'bisque',
'000000': 'black',
'0000ff': 'blue',
'a52a2a': 'brown',
'ff7f50': 'coral',
'ffd700': 'gold',
'008000': 'green',
'4b0082': 'indigo',
'fffff0': 'ivory',
'f0e68c': 'khaki',
'00ff00': 'lime',
'faf0e6': 'linen',
'000080': 'navy',
'ffa500': 'orange',
'da70d6': 'orchid',
'cd853f': 'peru',
'ffc0cb': 'pink',
'dda0dd': 'plum',
'f00': 'red',
'ff0000': 'red',
'fa8072': 'salmon',
'a0522d': 'sienna',
'c0c0c0': 'silver',
'fffafa': 'snow',
'd2b48c': 'tan',
'008080': 'teal',
'ff6347': 'tomato',
'ee82ee': 'violet',
'f5deb3': 'wheat',
'ffffff': 'white',
'ffff00': 'yellow'
};
function hueToRgb(p, q, t) {
if (t < 0) {
t += 1;
}
if (t > 1) {
t -= 1;
}
if (t < 1 / 6) {
return p + (q - p) * 6 * t;
}
if (t < 1 / 2) {
return q;
}
if (t < 2 / 3) {
return p + (q - p) * (2 / 3 - t) * 6;
}
return p;
}
function hslToRgb(h, s, l, a) {
let r;
let g;
let b;
if (s === 0) {
r = g = b = l; // achromatic
} else {
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
r = hueToRgb(p, q, h + 1 / 3);
g = hueToRgb(p, q, h);
b = hueToRgb(p, q, h - 1 / 3);
}
return [
Math.round(r * 255),
Math.round(g * 255),
Math.round(b * 255),
a
];
}
function toHex(value) {
value = value.toString(16);
return value.length === 1 ? '0' + value : value;
}
function parseFunctionArgs(functionArgs, count, rgb) {
let cursor = functionArgs.head;
let args = [];
let wasValue = false;
while (cursor !== null) {
const { type, value } = cursor.data;
switch (type) {
case 'Number':
case 'Percentage':
if (wasValue) {
return;
}
wasValue = true;
args.push({
type,
value: Number(value)
});
break;
case 'Operator':
if (value === ',') {
if (!wasValue) {
return;
}
wasValue = false;
} else if (wasValue || value !== '+') {
return;
}
break;
default:
// something we couldn't understand
return;
}
cursor = cursor.next;
}
if (args.length !== count) {
// invalid arguments count
// TODO: remove those tokens
return;
}
if (args.length === 4) {
if (args[3].type !== 'Number') {
// 4th argument should be a number
// TODO: remove those tokens
return;
}
args[3].type = 'Alpha';
}
if (rgb) {
if (args[0].type !== args[1].type || args[0].type !== args[2].type) {
// invalid color, numbers and percentage shouldn't be mixed
// TODO: remove those tokens
return;
}
} else {
if (args[0].type !== 'Number' ||
args[1].type !== 'Percentage' ||
args[2].type !== 'Percentage') {
// invalid color, for hsl values should be: number, percentage, percentage
// TODO: remove those tokens
return;
}
args[0].type = 'Angle';
}
return args.map(function(arg) {
let value = Math.max(0, arg.value);
switch (arg.type) {
case 'Number':
// fit value to [0..255] range
value = Math.min(value, 255);
break;
case 'Percentage':
// convert 0..100% to value in [0..255] range
value = Math.min(value, 100) / 100;
if (!rgb) {
return value;
}
value = 255 * value;
break;
case 'Angle':
// fit value to (-360..360) range
return (((value % 360) + 360) % 360) / 360;
case 'Alpha':
// fit value to [0..1] range
return Math.min(value, 1);
}
return Math.round(value);
});
}
function compressFunction(node, item) {
let functionName = node.name;
let args;
if (functionName === 'rgba' || functionName === 'hsla') {
args = parseFunctionArgs(node.children, 4, functionName === 'rgba');
if (!args) {
// something went wrong
return;
}
if (functionName === 'hsla') {
args = hslToRgb(...args);
node.name = 'rgba';
}
if (args[3] === 0) {
// try to replace `rgba(x, x, x, 0)` to `transparent`
// always replace `rgba(0, 0, 0, 0)` to `transparent`
// otherwise avoid replacement in gradients since it may break color transition
// http://stackoverflow.com/questions/11829410/css3-gradient-rendering-issues-from-transparent-to-white
const scopeFunctionName = this.function && this.function.name;
if ((args[0] === 0 && args[1] === 0 && args[2] === 0) ||
!/^(?:to|from|color-stop)$|gradient$/i.test(scopeFunctionName)) {
item.data = {
type: 'Identifier',
loc: node.loc,
name: 'transparent'
};
return;
}
}
if (args[3] !== 1) {
// replace argument values for normalized/interpolated
node.children.forEach((node, item, list) => {
if (node.type === 'Operator') {
if (node.value !== ',') {
list.remove(item);
}
return;
}
item.data = {
type: 'Number',
loc: node.loc,
value: _Number$1.packNumber(args.shift())
};
});
return;
}
// otherwise convert to rgb, i.e. rgba(255, 0, 0, 1) -> rgb(255, 0, 0)
functionName = 'rgb';
}
if (functionName === 'hsl') {
args = args || parseFunctionArgs(node.children, 3, false);
if (!args) {
// something went wrong
return;
}
// convert to rgb
args = hslToRgb(...args);
functionName = 'rgb';
}
if (functionName === 'rgb') {
args = args || parseFunctionArgs(node.children, 3, true);
if (!args) {
// something went wrong
return;
}
item.data = {
type: 'Hash',
loc: node.loc,
value: toHex(args[0]) + toHex(args[1]) + toHex(args[2])
};
compressHex(item.data, item);
}
}
function compressIdent(node, item) {
if (this.declaration === null) {
return;
}
let color = node.name.toLowerCase();
if (NAME_TO_HEX.hasOwnProperty(color) &&
cssTree$e.lexer.matchDeclaration(this.declaration).isType(node, 'color')) {
const hex = NAME_TO_HEX[color];
if (hex.length + 1 <= color.length) {
// replace for shorter hex value
item.data = {
type: 'Hash',
loc: node.loc,
value: hex
};
} else {
// special case for consistent colors
if (color === 'grey') {
color = 'gray';
}
// just replace value for lower cased name
node.name = color;
}
}
}
function compressHex(node, item) {
let color = node.value.toLowerCase();
// #112233 -> #123
if (color.length === 6 &&
color[0] === color[1] &&
color[2] === color[3] &&
color[4] === color[5]) {
color = color[0] + color[2] + color[4];
}
if (HEX_TO_NAME[color]) {
item.data = {
type: 'Identifier',
loc: node.loc,
name: HEX_TO_NAME[color]
};
} else {
node.value = color;
}
}
color$1.compressFunction = compressFunction;
color$1.compressHex = compressHex;
color$1.compressIdent = compressIdent;
const cssTree$d = cjs;
const Atrule = Atrule_1;
const AttributeSelector = AttributeSelector_1;
const Value = Value$1;
const Dimension = Dimension$1;
const Percentage = Percentage$1;
const _Number = _Number$4;
const Url = Url_1;
const color = color$1;
const handlers = {
Atrule,
AttributeSelector,
Value,
Dimension,
Percentage,
Number: _Number.Number,
Url,
Hash: color.compressHex,
Identifier: color.compressIdent,
Function: color.compressFunction
};
function replace(ast) {
cssTree$d.walk(ast, {
leave(node, item, list) {
if (handlers.hasOwnProperty(node.type)) {
handlers[node.type].call(this, node, item, list);
}
}
});
}
var replace_1 = replace;
const cssTree$c = cjs;
class Index {
constructor() {
this.map = new Map();
}
resolve(str) {
let index = this.map.get(str);
if (index === undefined) {
index = this.map.size + 1;
this.map.set(str, index);
}
return index;
}
}
function createDeclarationIndexer$1() {
const ids = new Index();
return function markDeclaration(node) {
const id = cssTree$c.generate(node);
node.id = ids.resolve(id);
node.length = id.length;
node.fingerprint = null;
return node;
};
}
var createDeclarationIndexer_1 = createDeclarationIndexer$1;
const cssTree$b = cjs;
function ensureSelectorList(node) {
if (node.type === 'Raw') {
return cssTree$b.parse(node.value, { context: 'selectorList' });
}
return node;
}
function maxSpecificity(a, b) {
for (let i = 0; i < 3; i++) {
if (a[i] !== b[i]) {
return a[i] > b[i] ? a : b;
}
}
return a;
}
function maxSelectorListSpecificity(selectorList) {
return ensureSelectorList(selectorList).children.reduce(
(result, node) => maxSpecificity(specificity$4(node), result),
[0, 0, 0]
);
}
// §16. Calculating a selectors specificity
// https://www.w3.org/TR/selectors-4/#specificity-rules
function specificity$4(simpleSelector) {
let A = 0;
let B = 0;
let C = 0;
// A selectors specificity is calculated for a given element as follows:
simpleSelector.children.forEach((node) => {
switch (node.type) {
// count the number of ID selectors in the selector (= A)
case 'IdSelector':
A++;
break;
// count the number of class selectors, attributes selectors, ...
case 'ClassSelector':
case 'AttributeSelector':
B++;
break;
// ... and pseudo-classes in the selector (= B)
case 'PseudoClassSelector':
switch (node.name.toLowerCase()) {
// The specificity of an :is(), :not(), or :has() pseudo-class is replaced
// by the specificity of the most specific complex selector in its selector list argument.
case 'not':
case 'has':
case 'is':
// :matches() is used before it was renamed to :is()
// https://github.com/w3c/csswg-drafts/issues/3258
case 'matches':
// Older browsers support :is() functionality as prefixed pseudo-class :any()
// https://developer.mozilla.org/en-US/docs/Web/CSS/:is
case '-webkit-any':
case '-moz-any': {
const [a, b, c] = maxSelectorListSpecificity(node.children.first);
A += a;
B += b;
C += c;
break;
}
// Analogously, the specificity of an :nth-child() or :nth-last-child() selector
// is the specificity of the pseudo class itself (counting as one pseudo-class selector)
// plus the specificity of the most specific complex selector in its selector list argument (if any).
case 'nth-child':
case 'nth-last-child': {
const arg = node.children.first;
if (arg.type === 'Nth' && arg.selector) {
const [a, b, c] = maxSelectorListSpecificity(arg.selector);
A += a;
B += b + 1;
C += c;
} else {
B++;
}
break;
}
// The specificity of a :where() pseudo-class is replaced by zero.
case 'where':
break;
// The four Level 2 pseudo-elements (::before, ::after, ::first-line, and ::first-letter) may,
// for legacy reasons, be represented using the <pseudo-class-selector> grammar,
// with only a single ":" character at their start.
// https://www.w3.org/TR/selectors-4/#single-colon-pseudos
case 'before':
case 'after':
case 'first-line':
case 'first-letter':
C++;
break;
default:
B++;
}
break;
// count the number of type selectors ...
case 'TypeSelector':
// ignore the universal selector
if (!node.name.endsWith('*')) {
C++;
}
break;
// ... and pseudo-elements in the selector (= C)
case 'PseudoElementSelector':
C++;
break;
}
});
return [A, B, C];
}
var specificity_1 = specificity$4;
const cssTree$a = cjs;
const specificity$3 = specificity_1;
const nonFreezePseudoElements = new Set([
'first-letter',
'first-line',
'after',
'before'
]);
const nonFreezePseudoClasses = new Set([
'link',
'visited',
'hover',
'active',
'first-letter',
'first-line',
'after',
'before'
]);
function processSelector$2(node, usageData) {
const pseudos = new Set();
node.prelude.children.forEach(function(simpleSelector) {
let tagName = '*';
let scope = 0;
simpleSelector.children.forEach(function(node) {
switch (node.type) {
case 'ClassSelector':
if (usageData && usageData.scopes) {
const classScope = usageData.scopes[node.name] || 0;
if (scope !== 0 && classScope !== scope) {
throw new Error('Selector can\'t has classes from different scopes: ' + cssTree$a.generate(simpleSelector));
}
scope = classScope;
}
break;
case 'PseudoClassSelector': {
const name = node.name.toLowerCase();
if (!nonFreezePseudoClasses.has(name)) {
pseudos.add(`:${name}`);
}
break;
}
case 'PseudoElementSelector': {
const name = node.name.toLowerCase();
if (!nonFreezePseudoElements.has(name)) {
pseudos.add(`::${name}`);
}
break;
}
case 'TypeSelector':
tagName = node.name.toLowerCase();
break;
case 'AttributeSelector':
if (node.flags) {
pseudos.add(`[${node.flags.toLowerCase()}]`);
}
break;
case 'Combinator':
tagName = '*';
break;
}
});
simpleSelector.compareMarker = specificity$3(simpleSelector).toString();
simpleSelector.id = null; // pre-init property to avoid multiple hidden class
simpleSelector.id = cssTree$a.generate(simpleSelector);
if (scope) {
simpleSelector.compareMarker += ':' + scope;
}
if (tagName !== '*') {
simpleSelector.compareMarker += ',' + tagName;
}
});
// add property to all rule nodes to avoid multiple hidden class
node.pseudoSignature = pseudos.size > 0
? [...pseudos].sort().join(',')
: false;
}
var processSelector_1 = processSelector$2;
const cssTree$9 = cjs;
const createDeclarationIndexer = createDeclarationIndexer_1;
const processSelector$1 = processSelector_1;
function prepare(ast, options) {
const markDeclaration = createDeclarationIndexer();
cssTree$9.walk(ast, {
visit: 'Rule',
enter(node) {
node.block.children.forEach(markDeclaration);
processSelector$1(node, options.usage);
}
});
cssTree$9.walk(ast, {
visit: 'Atrule',
enter(node) {
if (node.prelude) {
node.prelude.id = null; // pre-init property to avoid multiple hidden class for generate
node.prelude.id = cssTree$9.generate(node.prelude);
}
// compare keyframe selectors by its values
// NOTE: still no clarification about problems with keyframes selector grouping (issue #197)
if (cssTree$9.keyword(node.name).basename === 'keyframes') {
node.block.avoidRulesMerge = true; /* probably we don't need to prevent those merges for @keyframes
TODO: need to be checked */
node.block.children.forEach(function(rule) {
rule.prelude.children.forEach(function(simpleselector) {
simpleselector.compareMarker = simpleselector.id;
});
});
}
}
});
return {
declaration: markDeclaration
};
}
var prepare_1 = prepare;
const cssTree$8 = cjs;
const { hasOwnProperty: hasOwnProperty$2 } = Object.prototype;
function addRuleToMap(map, item, list, single) {
const node = item.data;
const name = cssTree$8.keyword(node.name).basename;
const id = node.name.toLowerCase() + '/' + (node.prelude ? node.prelude.id : null);
if (!hasOwnProperty$2.call(map, name)) {
map[name] = Object.create(null);
}
if (single) {
delete map[name][id];
}
if (!hasOwnProperty$2.call(map[name], id)) {
map[name][id] = new cssTree$8.List();
}
map[name][id].append(list.remove(item));
}
function relocateAtrules(ast, options) {
const collected = Object.create(null);
let topInjectPoint = null;
ast.children.forEach(function(node, item, list) {
if (node.type === 'Atrule') {
const name = cssTree$8.keyword(node.name).basename;
switch (name) {
case 'keyframes':
addRuleToMap(collected, item, list, true);
return;
case 'media':
if (options.forceMediaMerge) {
addRuleToMap(collected, item, list, false);
return;
}
break;
}
if (topInjectPoint === null &&
name !== 'charset' &&
name !== 'import') {
topInjectPoint = item;
}
} else {
if (topInjectPoint === null) {
topInjectPoint = item;
}
}
});
for (const atrule in collected) {
for (const id in collected[atrule]) {
ast.children.insertList(
collected[atrule][id],
atrule === 'media' ? null : topInjectPoint
);
}
}
}
function isMediaRule(node) {
return node.type === 'Atrule' && node.name === 'media';
}
function processAtrule(node, item, list) {
if (!isMediaRule(node)) {
return;
}
const prev = item.prev && item.prev.data;
if (!prev || !isMediaRule(prev)) {
return;
}
// merge @media with same query
if (node.prelude &&
prev.prelude &&
node.prelude.id === prev.prelude.id) {
prev.block.children.appendList(node.block.children);
list.remove(item);
// TODO: use it when we can refer to several points in source
// prev.loc = {
// primary: prev.loc,
// merged: node.loc
// };
}
}
function rejoinAtrule(ast, options) {
relocateAtrules(ast, options);
cssTree$8.walk(ast, {
visit: 'Atrule',
reverse: true,
enter: processAtrule
});
}
var _1MergeAtrule$1 = rejoinAtrule;
var utils$6 = {};
const { hasOwnProperty: hasOwnProperty$1 } = Object.prototype;
function isEqualSelectors(a, b) {
let cursor1 = a.head;
let cursor2 = b.head;
while (cursor1 !== null && cursor2 !== null && cursor1.data.id === cursor2.data.id) {
cursor1 = cursor1.next;
cursor2 = cursor2.next;
}
return cursor1 === null && cursor2 === null;
}
function isEqualDeclarations(a, b) {
let cursor1 = a.head;
let cursor2 = b.head;
while (cursor1 !== null && cursor2 !== null && cursor1.data.id === cursor2.data.id) {
cursor1 = cursor1.next;
cursor2 = cursor2.next;
}
return cursor1 === null && cursor2 === null;
}
function compareDeclarations(declarations1, declarations2) {
const result = {
eq: [],
ne1: [],
ne2: [],
ne2overrided: []
};
const fingerprints = Object.create(null);
const declarations2hash = Object.create(null);
for (let cursor = declarations2.head; cursor; cursor = cursor.next) {
declarations2hash[cursor.data.id] = true;
}
for (let cursor = declarations1.head; cursor; cursor = cursor.next) {
const data = cursor.data;
if (data.fingerprint) {
fingerprints[data.fingerprint] = data.important;
}
if (declarations2hash[data.id]) {
declarations2hash[data.id] = false;
result.eq.push(data);
} else {
result.ne1.push(data);
}
}
for (let cursor = declarations2.head; cursor; cursor = cursor.next) {
const data = cursor.data;
if (declarations2hash[data.id]) {
// when declarations1 has an overriding declaration, this is not a difference
// unless no !important is used on prev and !important is used on the following
if (!hasOwnProperty$1.call(fingerprints, data.fingerprint) ||
(!fingerprints[data.fingerprint] && data.important)) {
result.ne2.push(data);
}
result.ne2overrided.push(data);
}
}
return result;
}
function addSelectors(dest, source) {
source.forEach((sourceData) => {
const newStr = sourceData.id;
let cursor = dest.head;
while (cursor) {
const nextStr = cursor.data.id;
if (nextStr === newStr) {
return;
}
if (nextStr > newStr) {
break;
}
cursor = cursor.next;
}
dest.insert(dest.createItem(sourceData), cursor);
});
return dest;
}
// check if simpleselectors has no equal specificity and element selector
function hasSimilarSelectors(selectors1, selectors2) {
let cursor1 = selectors1.head;
while (cursor1 !== null) {
let cursor2 = selectors2.head;
while (cursor2 !== null) {
if (cursor1.data.compareMarker === cursor2.data.compareMarker) {
return true;
}
cursor2 = cursor2.next;
}
cursor1 = cursor1.next;
}
return false;
}
// test node can't to be skipped
function unsafeToSkipNode(node) {
switch (node.type) {
case 'Rule':
// unsafe skip ruleset with selector similarities
return hasSimilarSelectors(node.prelude.children, this);
case 'Atrule':
// can skip at-rules with blocks
if (node.block) {
// unsafe skip at-rule if block contains something unsafe to skip
return node.block.children.some(unsafeToSkipNode, this);
}
break;
case 'Declaration':
return false;
}
// unsafe by default
return true;
}
utils$6.addSelectors = addSelectors;
utils$6.compareDeclarations = compareDeclarations;
utils$6.hasSimilarSelectors = hasSimilarSelectors;
utils$6.isEqualDeclarations = isEqualDeclarations;
utils$6.isEqualSelectors = isEqualSelectors;
utils$6.unsafeToSkipNode = unsafeToSkipNode;
const cssTree$7 = cjs;
const utils$5 = utils$6;
function processRule$5(node, item, list) {
const selectors = node.prelude.children;
const declarations = node.block.children;
list.prevUntil(item.prev, function(prev) {
// skip non-ruleset node if safe
if (prev.type !== 'Rule') {
return utils$5.unsafeToSkipNode.call(selectors, prev);
}
const prevSelectors = prev.prelude.children;
const prevDeclarations = prev.block.children;
// try to join rulesets with equal pseudo signature
if (node.pseudoSignature === prev.pseudoSignature) {
// try to join by selectors
if (utils$5.isEqualSelectors(prevSelectors, selectors)) {
prevDeclarations.appendList(declarations);
list.remove(item);
return true;
}
// try to join by declarations
if (utils$5.isEqualDeclarations(declarations, prevDeclarations)) {
utils$5.addSelectors(prevSelectors, selectors);
list.remove(item);
return true;
}
}
// go to prev ruleset if has no selector similarities
return utils$5.hasSimilarSelectors(selectors, prevSelectors);
});
}
// NOTE: direction should be left to right, since rulesets merge to left
// ruleset. When direction right to left unmerged rulesets may prevent lookup
// TODO: remove initial merge
function initialMergeRule(ast) {
cssTree$7.walk(ast, {
visit: 'Rule',
enter: processRule$5
});
}
var _2InitialMergeRuleset$1 = initialMergeRule;
const cssTree$6 = cjs;
function processRule$4(node, item, list) {
const selectors = node.prelude.children;
// generate new rule sets:
// .a, .b { color: red; }
// ->
// .a { color: red; }
// .b { color: red; }
// while there are more than 1 simple selector split for rulesets
while (selectors.head !== selectors.tail) {
const newSelectors = new cssTree$6.List();
newSelectors.insert(selectors.remove(selectors.head));
list.insert(list.createItem({
type: 'Rule',
loc: node.loc,
prelude: {
type: 'SelectorList',
loc: node.prelude.loc,
children: newSelectors
},
block: {
type: 'Block',
loc: node.block.loc,
children: node.block.children.copy()
},
pseudoSignature: node.pseudoSignature
}), item);
}
}
function disjoinRule(ast) {
cssTree$6.walk(ast, {
visit: 'Rule',
reverse: true,
enter: processRule$4
});
}
var _3DisjoinRuleset$1 = disjoinRule;
const cssTree$5 = cjs;
const REPLACE = 1;
const REMOVE = 2;
const TOP = 0;
const RIGHT = 1;
const BOTTOM = 2;
const LEFT = 3;
const SIDES = ['top', 'right', 'bottom', 'left'];
const SIDE = {
'margin-top': 'top',
'margin-right': 'right',
'margin-bottom': 'bottom',
'margin-left': 'left',
'padding-top': 'top',
'padding-right': 'right',
'padding-bottom': 'bottom',
'padding-left': 'left',
'border-top-color': 'top',
'border-right-color': 'right',
'border-bottom-color': 'bottom',
'border-left-color': 'left',
'border-top-width': 'top',
'border-right-width': 'right',
'border-bottom-width': 'bottom',
'border-left-width': 'left',
'border-top-style': 'top',
'border-right-style': 'right',
'border-bottom-style': 'bottom',
'border-left-style': 'left'
};
const MAIN_PROPERTY = {
'margin': 'margin',
'margin-top': 'margin',
'margin-right': 'margin',
'margin-bottom': 'margin',
'margin-left': 'margin',
'padding': 'padding',
'padding-top': 'padding',
'padding-right': 'padding',
'padding-bottom': 'padding',
'padding-left': 'padding',
'border-color': 'border-color',
'border-top-color': 'border-color',
'border-right-color': 'border-color',
'border-bottom-color': 'border-color',
'border-left-color': 'border-color',
'border-width': 'border-width',
'border-top-width': 'border-width',
'border-right-width': 'border-width',
'border-bottom-width': 'border-width',
'border-left-width': 'border-width',
'border-style': 'border-style',
'border-top-style': 'border-style',
'border-right-style': 'border-style',
'border-bottom-style': 'border-style',
'border-left-style': 'border-style'
};
class TRBL {
constructor(name) {
this.name = name;
this.loc = null;
this.iehack = undefined;
this.sides = {
'top': null,
'right': null,
'bottom': null,
'left': null
};
}
getValueSequence(declaration, count) {
const values = [];
let iehack = '';
const hasBadValues = declaration.value.type !== 'Value' || declaration.value.children.some(function(child) {
let special = false;
switch (child.type) {
case 'Identifier':
switch (child.name) {
case '\\0':
case '\\9':
iehack = child.name;
return;
case 'inherit':
case 'initial':
case 'unset':
case 'revert':
special = child.name;
break;
}
break;
case 'Dimension':
switch (child.unit) {
// is not supported until IE11
case 'rem':
// v* units is too buggy across browsers and better
// don't merge values with those units
case 'vw':
case 'vh':
case 'vmin':
case 'vmax':
case 'vm': // IE9 supporting "vm" instead of "vmin".
special = child.unit;
break;
}
break;
case 'Hash': // color
case 'Number':
case 'Percentage':
break;
case 'Function':
if (child.name === 'var') {
return true;
}
special = child.name;
break;
default:
return true; // bad value
}
values.push({
node: child,
special,
important: declaration.important
});
});
if (hasBadValues || values.length > count) {
return false;
}
if (typeof this.iehack === 'string' && this.iehack !== iehack) {
return false;
}
this.iehack = iehack; // move outside
return values;
}
canOverride(side, value) {
const currentValue = this.sides[side];
return !currentValue || (value.important && !currentValue.important);
}
add(name, declaration) {
function attemptToAdd() {
const sides = this.sides;
const side = SIDE[name];
if (side) {
if (side in sides === false) {
return false;
}
const values = this.getValueSequence(declaration, 1);
if (!values || !values.length) {
return false;
}
// can mix only if specials are equal
for (const key in sides) {
if (sides[key] !== null && sides[key].special !== values[0].special) {
return false;
}
}
if (!this.canOverride(side, values[0])) {
return true;
}
sides[side] = values[0];
return true;
} else if (name === this.name) {
const values = this.getValueSequence(declaration, 4);
if (!values || !values.length) {
return false;
}
switch (values.length) {
case 1:
values[RIGHT] = values[TOP];
values[BOTTOM] = values[TOP];
values[LEFT] = values[TOP];
break;
case 2:
values[BOTTOM] = values[TOP];
values[LEFT] = values[RIGHT];
break;
case 3:
values[LEFT] = values[RIGHT];
break;
}
// can mix only if specials are equal
for (let i = 0; i < 4; i++) {
for (const key in sides) {
if (sides[key] !== null && sides[key].special !== values[i].special) {
return false;
}
}
}
for (let i = 0; i < 4; i++) {
if (this.canOverride(SIDES[i], values[i])) {
sides[SIDES[i]] = values[i];
}
}
return true;
}
}
if (!attemptToAdd.call(this)) {
return false;
}
// TODO: use it when we can refer to several points in source
// if (this.loc) {
// this.loc = {
// primary: this.loc,
// merged: declaration.loc
// };
// } else {
// this.loc = declaration.loc;
// }
if (!this.loc) {
this.loc = declaration.loc;
}
return true;
}
isOkToMinimize() {
const top = this.sides.top;
const right = this.sides.right;
const bottom = this.sides.bottom;
const left = this.sides.left;
if (top && right && bottom && left) {
const important =
top.important +
right.important +
bottom.important +
left.important;
return important === 0 || important === 4;
}
return false;
}
getValue() {
const result = new cssTree$5.List();
const sides = this.sides;
const values = [
sides.top,
sides.right,
sides.bottom,
sides.left
];
const stringValues = [
cssTree$5.generate(sides.top.node),
cssTree$5.generate(sides.right.node),
cssTree$5.generate(sides.bottom.node),
cssTree$5.generate(sides.left.node)
];
if (stringValues[LEFT] === stringValues[RIGHT]) {
values.pop();
if (stringValues[BOTTOM] === stringValues[TOP]) {
values.pop();
if (stringValues[RIGHT] === stringValues[TOP]) {
values.pop();
}
}
}
for (let i = 0; i < values.length; i++) {
result.appendData(values[i].node);
}
if (this.iehack) {
result.appendData({
type: 'Identifier',
loc: null,
name: this.iehack
});
}
return {
type: 'Value',
loc: null,
children: result
};
}
getDeclaration() {
return {
type: 'Declaration',
loc: this.loc,
important: this.sides.top.important,
property: this.name,
value: this.getValue()
};
}
}
function processRule$3(rule, shorts, shortDeclarations, lastShortSelector) {
const declarations = rule.block.children;
const selector = rule.prelude.children.first.id;
rule.block.children.forEachRight(function(declaration, item) {
const property = declaration.property;
if (!MAIN_PROPERTY.hasOwnProperty(property)) {
return;
}
const key = MAIN_PROPERTY[property];
let shorthand;
let operation;
if (!lastShortSelector || selector === lastShortSelector) {
if (key in shorts) {
operation = REMOVE;
shorthand = shorts[key];
}
}
if (!shorthand || !shorthand.add(property, declaration)) {
operation = REPLACE;
shorthand = new TRBL(key);
// if can't parse value ignore it and break shorthand children
if (!shorthand.add(property, declaration)) {
lastShortSelector = null;
return;
}
}
shorts[key] = shorthand;
shortDeclarations.push({
operation,
block: declarations,
item,
shorthand
});
lastShortSelector = selector;
});
return lastShortSelector;
}
function processShorthands(shortDeclarations, markDeclaration) {
shortDeclarations.forEach(function(item) {
const shorthand = item.shorthand;
if (!shorthand.isOkToMinimize()) {
return;
}
if (item.operation === REPLACE) {
item.item.data = markDeclaration(shorthand.getDeclaration());
} else {
item.block.remove(item.item);
}
});
}
function restructBlock$1(ast, indexer) {
const stylesheetMap = {};
const shortDeclarations = [];
cssTree$5.walk(ast, {
visit: 'Rule',
reverse: true,
enter(node) {
const stylesheet = this.block || this.stylesheet;
const ruleId = (node.pseudoSignature || '') + '|' + node.prelude.children.first.id;
let ruleMap;
let shorts;
if (!stylesheetMap.hasOwnProperty(stylesheet.id)) {
ruleMap = {
lastShortSelector: null
};
stylesheetMap[stylesheet.id] = ruleMap;
} else {
ruleMap = stylesheetMap[stylesheet.id];
}
if (ruleMap.hasOwnProperty(ruleId)) {
shorts = ruleMap[ruleId];
} else {
shorts = {};
ruleMap[ruleId] = shorts;
}
ruleMap.lastShortSelector = processRule$3.call(this, node, shorts, shortDeclarations, ruleMap.lastShortSelector);
}
});
processShorthands(shortDeclarations, indexer.declaration);
}
var _4RestructShorthand$1 = restructBlock$1;
const cssTree$4 = cjs;
let fingerprintId = 1;
const dontRestructure = new Set([
'src' // https://github.com/afelix/csso/issues/50
]);
const DONT_MIX_VALUE = {
// https://developer.mozilla.org/en-US/docs/Web/CSS/display#Browser_compatibility
'display': /table|ruby|flex|-(flex)?box$|grid|contents|run-in/i,
// https://developer.mozilla.org/en/docs/Web/CSS/text-align
'text-align': /^(start|end|match-parent|justify-all)$/i
};
const SAFE_VALUES = {
cursor: [
'auto', 'crosshair', 'default', 'move', 'text', 'wait', 'help',
'n-resize', 'e-resize', 's-resize', 'w-resize',
'ne-resize', 'nw-resize', 'se-resize', 'sw-resize',
'pointer', 'progress', 'not-allowed', 'no-drop', 'vertical-text', 'all-scroll',
'col-resize', 'row-resize'
],
overflow: [
'hidden', 'visible', 'scroll', 'auto'
],
position: [
'static', 'relative', 'absolute', 'fixed'
]
};
const NEEDLESS_TABLE = {
'border-width': ['border'],
'border-style': ['border'],
'border-color': ['border'],
'border-top': ['border'],
'border-right': ['border'],
'border-bottom': ['border'],
'border-left': ['border'],
'border-top-width': ['border-top', 'border-width', 'border'],
'border-right-width': ['border-right', 'border-width', 'border'],
'border-bottom-width': ['border-bottom', 'border-width', 'border'],
'border-left-width': ['border-left', 'border-width', 'border'],
'border-top-style': ['border-top', 'border-style', 'border'],
'border-right-style': ['border-right', 'border-style', 'border'],
'border-bottom-style': ['border-bottom', 'border-style', 'border'],
'border-left-style': ['border-left', 'border-style', 'border'],
'border-top-color': ['border-top', 'border-color', 'border'],
'border-right-color': ['border-right', 'border-color', 'border'],
'border-bottom-color': ['border-bottom', 'border-color', 'border'],
'border-left-color': ['border-left', 'border-color', 'border'],
'margin-top': ['margin'],
'margin-right': ['margin'],
'margin-bottom': ['margin'],
'margin-left': ['margin'],
'padding-top': ['padding'],
'padding-right': ['padding'],
'padding-bottom': ['padding'],
'padding-left': ['padding'],
'font-style': ['font'],
'font-variant': ['font'],
'font-weight': ['font'],
'font-size': ['font'],
'font-family': ['font'],
'list-style-type': ['list-style'],
'list-style-position': ['list-style'],
'list-style-image': ['list-style']
};
function getPropertyFingerprint(propertyName, declaration, fingerprints) {
const realName = cssTree$4.property(propertyName).basename;
if (realName === 'background') {
return propertyName + ':' + cssTree$4.generate(declaration.value);
}
const declarationId = declaration.id;
let fingerprint = fingerprints[declarationId];
if (!fingerprint) {
switch (declaration.value.type) {
case 'Value':
const special = {};
let vendorId = '';
let iehack = '';
let raw = false;
declaration.value.children.forEach(function walk(node) {
switch (node.type) {
case 'Value':
case 'Brackets':
case 'Parentheses':
node.children.forEach(walk);
break;
case 'Raw':
raw = true;
break;
case 'Identifier': {
const { name } = node;
if (!vendorId) {
vendorId = cssTree$4.keyword(name).vendor;
}
if (/\\[09]/.test(name)) {
iehack = RegExp.lastMatch;
}
if (SAFE_VALUES.hasOwnProperty(realName)) {
if (SAFE_VALUES[realName].indexOf(name) === -1) {
special[name] = true;
}
} else if (DONT_MIX_VALUE.hasOwnProperty(realName)) {
if (DONT_MIX_VALUE[realName].test(name)) {
special[name] = true;
}
}
break;
}
case 'Function': {
let { name } = node;
if (!vendorId) {
vendorId = cssTree$4.keyword(name).vendor;
}
if (name === 'rect') {
// there are 2 forms of rect:
// rect(<top>, <right>, <bottom>, <left>) - standart
// rect(<top> <right> <bottom> <left>) backwards compatible syntax
// only the same form values can be merged
const hasComma = node.children.some((node) =>
node.type === 'Operator' && node.value === ','
);
if (!hasComma) {
name = 'rect-backward';
}
}
special[name + '()'] = true;
// check nested tokens too
node.children.forEach(walk);
break;
}
case 'Dimension': {
const { unit } = node;
if (/\\[09]/.test(unit)) {
iehack = RegExp.lastMatch;
}
switch (unit) {
// is not supported until IE11
case 'rem':
// v* units is too buggy across browsers and better
// don't merge values with those units
case 'vw':
case 'vh':
case 'vmin':
case 'vmax':
case 'vm': // IE9 supporting "vm" instead of "vmin".
special[unit] = true;
break;
}
break;
}
}
});
fingerprint = raw
? '!' + fingerprintId++
: '!' + Object.keys(special).sort() + '|' + iehack + vendorId;
break;
case 'Raw':
fingerprint = '!' + declaration.value.value;
break;
default:
fingerprint = cssTree$4.generate(declaration.value);
}
fingerprints[declarationId] = fingerprint;
}
return propertyName + fingerprint;
}
function needless(props, declaration, fingerprints) {
const property = cssTree$4.property(declaration.property);
if (NEEDLESS_TABLE.hasOwnProperty(property.basename)) {
const table = NEEDLESS_TABLE[property.basename];
for (const entry of table) {
const ppre = getPropertyFingerprint(property.prefix + entry, declaration, fingerprints);
const prev = props.hasOwnProperty(ppre) ? props[ppre] : null;
if (prev && (!declaration.important || prev.item.data.important)) {
return prev;
}
}
}
}
function processRule$2(rule, item, list, props, fingerprints) {
const declarations = rule.block.children;
declarations.forEachRight(function(declaration, declarationItem) {
const { property } = declaration;
const fingerprint = getPropertyFingerprint(property, declaration, fingerprints);
const prev = props[fingerprint];
if (prev && !dontRestructure.has(property)) {
if (declaration.important && !prev.item.data.important) {
props[fingerprint] = {
block: declarations,
item: declarationItem
};
prev.block.remove(prev.item);
// TODO: use it when we can refer to several points in source
// declaration.loc = {
// primary: declaration.loc,
// merged: prev.item.data.loc
// };
} else {
declarations.remove(declarationItem);
// TODO: use it when we can refer to several points in source
// prev.item.data.loc = {
// primary: prev.item.data.loc,
// merged: declaration.loc
// };
}
} else {
const prev = needless(props, declaration, fingerprints);
if (prev) {
declarations.remove(declarationItem);
// TODO: use it when we can refer to several points in source
// prev.item.data.loc = {
// primary: prev.item.data.loc,
// merged: declaration.loc
// };
} else {
declaration.fingerprint = fingerprint;
props[fingerprint] = {
block: declarations,
item: declarationItem
};
}
}
});
if (declarations.isEmpty) {
list.remove(item);
}
}
function restructBlock(ast) {
const stylesheetMap = {};
const fingerprints = Object.create(null);
cssTree$4.walk(ast, {
visit: 'Rule',
reverse: true,
enter(node, item, list) {
const stylesheet = this.block || this.stylesheet;
const ruleId = (node.pseudoSignature || '') + '|' + node.prelude.children.first.id;
let ruleMap;
let props;
if (!stylesheetMap.hasOwnProperty(stylesheet.id)) {
ruleMap = {};
stylesheetMap[stylesheet.id] = ruleMap;
} else {
ruleMap = stylesheetMap[stylesheet.id];
}
if (ruleMap.hasOwnProperty(ruleId)) {
props = ruleMap[ruleId];
} else {
props = {};
ruleMap[ruleId] = props;
}
processRule$2.call(this, node, item, list, props, fingerprints);
}
});
}
var _6RestructBlock$1 = restructBlock;
const cssTree$3 = cjs;
const utils$4 = utils$6;
/*
At this step all rules has single simple selector. We try to join by equal
declaration blocks to first rule, e.g.
.a { color: red }
b { ... }
.b { color: red }
->
.a, .b { color: red }
b { ... }
*/
function processRule$1(node, item, list) {
const selectors = node.prelude.children;
const declarations = node.block.children;
const nodeCompareMarker = selectors.first.compareMarker;
const skippedCompareMarkers = {};
list.nextUntil(item.next, function(next, nextItem) {
// skip non-ruleset node if safe
if (next.type !== 'Rule') {
return utils$4.unsafeToSkipNode.call(selectors, next);
}
if (node.pseudoSignature !== next.pseudoSignature) {
return true;
}
const nextFirstSelector = next.prelude.children.head;
const nextDeclarations = next.block.children;
const nextCompareMarker = nextFirstSelector.data.compareMarker;
// if next ruleset has same marked as one of skipped then stop joining
if (nextCompareMarker in skippedCompareMarkers) {
return true;
}
// try to join by selectors
if (selectors.head === selectors.tail) {
if (selectors.first.id === nextFirstSelector.data.id) {
declarations.appendList(nextDeclarations);
list.remove(nextItem);
return;
}
}
// try to join by properties
if (utils$4.isEqualDeclarations(declarations, nextDeclarations)) {
const nextStr = nextFirstSelector.data.id;
selectors.some((data, item) => {
const curStr = data.id;
if (nextStr < curStr) {
selectors.insert(nextFirstSelector, item);
return true;
}
if (!item.next) {
selectors.insert(nextFirstSelector);
return true;
}
});
list.remove(nextItem);
return;
}
// go to next ruleset if current one can be skipped (has no equal specificity nor element selector)
if (nextCompareMarker === nodeCompareMarker) {
return true;
}
skippedCompareMarkers[nextCompareMarker] = true;
});
}
function mergeRule(ast) {
cssTree$3.walk(ast, {
visit: 'Rule',
enter: processRule$1
});
}
var _7MergeRuleset$1 = mergeRule;
const cssTree$2 = cjs;
const utils$3 = utils$6;
function calcSelectorLength(list) {
return list.reduce((res, data) => res + data.id.length + 1, 0) - 1;
}
function calcDeclarationsLength(tokens) {
let length = 0;
for (const token of tokens) {
length += token.length;
}
return (
length + // declarations
tokens.length - 1 // delimeters
);
}
function processRule(node, item, list) {
const avoidRulesMerge = this.block !== null ? this.block.avoidRulesMerge : false;
const selectors = node.prelude.children;
const block = node.block;
const disallowDownMarkers = Object.create(null);
let allowMergeUp = true;
let allowMergeDown = true;
list.prevUntil(item.prev, function(prev, prevItem) {
const prevBlock = prev.block;
const prevType = prev.type;
if (prevType !== 'Rule') {
const unsafe = utils$3.unsafeToSkipNode.call(selectors, prev);
if (!unsafe && prevType === 'Atrule' && prevBlock) {
cssTree$2.walk(prevBlock, {
visit: 'Rule',
enter(node) {
node.prelude.children.forEach((data) => {
disallowDownMarkers[data.compareMarker] = true;
});
}
});
}
return unsafe;
}
if (node.pseudoSignature !== prev.pseudoSignature) {
return true;
}
const prevSelectors = prev.prelude.children;
allowMergeDown = !prevSelectors.some((selector) =>
selector.compareMarker in disallowDownMarkers
);
// try prev ruleset if simpleselectors has no equal specifity and element selector
if (!allowMergeDown && !allowMergeUp) {
return true;
}
// try to join by selectors
if (allowMergeUp && utils$3.isEqualSelectors(prevSelectors, selectors)) {
prevBlock.children.appendList(block.children);
list.remove(item);
return true;
}
// try to join by properties
const diff = utils$3.compareDeclarations(block.children, prevBlock.children);
// console.log(diff.eq, diff.ne1, diff.ne2);
if (diff.eq.length) {
if (!diff.ne1.length && !diff.ne2.length) {
// equal blocks
if (allowMergeDown) {
utils$3.addSelectors(selectors, prevSelectors);
list.remove(prevItem);
}
return true;
} else if (!avoidRulesMerge) { /* probably we don't need to prevent those merges for @keyframes
TODO: need to be checked */
if (diff.ne1.length && !diff.ne2.length) {
// prevBlock is subset block
const selectorLength = calcSelectorLength(selectors);
const blockLength = calcDeclarationsLength(diff.eq); // declarations length
if (allowMergeUp && selectorLength < blockLength) {
utils$3.addSelectors(prevSelectors, selectors);
block.children.fromArray(diff.ne1);
}
} else if (!diff.ne1.length && diff.ne2.length) {
// node is subset of prevBlock
const selectorLength = calcSelectorLength(prevSelectors);
const blockLength = calcDeclarationsLength(diff.eq); // declarations length
if (allowMergeDown && selectorLength < blockLength) {
utils$3.addSelectors(selectors, prevSelectors);
prevBlock.children.fromArray(diff.ne2);
}
} else {
// diff.ne1.length && diff.ne2.length
// extract equal block
const newSelector = {
type: 'SelectorList',
loc: null,
children: utils$3.addSelectors(prevSelectors.copy(), selectors)
};
const newBlockLength = calcSelectorLength(newSelector.children) + 2; // selectors length + curly braces length
const blockLength = calcDeclarationsLength(diff.eq); // declarations length
// create new ruleset if declarations length greater than
// ruleset description overhead
if (blockLength >= newBlockLength) {
const newItem = list.createItem({
type: 'Rule',
loc: null,
prelude: newSelector,
block: {
type: 'Block',
loc: null,
children: new cssTree$2.List().fromArray(diff.eq)
},
pseudoSignature: node.pseudoSignature
});
block.children.fromArray(diff.ne1);
prevBlock.children.fromArray(diff.ne2overrided);
if (allowMergeUp) {
list.insert(newItem, prevItem);
} else {
list.insert(newItem, item);
}
return true;
}
}
}
}
if (allowMergeUp) {
// TODO: disallow up merge only if any property interception only (i.e. diff.ne2overrided.length > 0);
// await property families to find property interception correctly
allowMergeUp = !prevSelectors.some((prevSelector) =>
selectors.some((selector) =>
selector.compareMarker === prevSelector.compareMarker
)
);
}
prevSelectors.forEach((data) => {
disallowDownMarkers[data.compareMarker] = true;
});
});
}
function restructRule(ast) {
cssTree$2.walk(ast, {
visit: 'Rule',
reverse: true,
enter: processRule
});
}
var _8RestructRuleset$1 = restructRule;
const index$3 = prepare_1;
const _1MergeAtrule = _1MergeAtrule$1;
const _2InitialMergeRuleset = _2InitialMergeRuleset$1;
const _3DisjoinRuleset = _3DisjoinRuleset$1;
const _4RestructShorthand = _4RestructShorthand$1;
const _6RestructBlock = _6RestructBlock$1;
const _7MergeRuleset = _7MergeRuleset$1;
const _8RestructRuleset = _8RestructRuleset$1;
function restructure(ast, options) {
// prepare ast for restructing
const indexer = index$3(ast, options);
options.logger('prepare', ast);
_1MergeAtrule(ast, options);
options.logger('mergeAtrule', ast);
_2InitialMergeRuleset(ast);
options.logger('initialMergeRuleset', ast);
_3DisjoinRuleset(ast);
options.logger('disjoinRuleset', ast);
_4RestructShorthand(ast, indexer);
options.logger('restructShorthand', ast);
_6RestructBlock(ast);
options.logger('restructBlock', ast);
_7MergeRuleset(ast);
options.logger('mergeRuleset', ast);
_8RestructRuleset(ast);
options.logger('restructRuleset', ast);
}
var restructure_1 = restructure;
const cssTree$1 = cjs;
const usage = usage$1;
const index = clean_1;
const index$1 = replace_1;
const index$2 = restructure_1;
function readChunk(input, specialComments) {
const children = new cssTree$1.List();
let nonSpaceTokenInBuffer = false;
let protectedComment;
input.nextUntil(input.head, (node, item, list) => {
if (node.type === 'Comment') {
if (!specialComments || node.value.charAt(0) !== '!') {
list.remove(item);
return;
}
if (nonSpaceTokenInBuffer || protectedComment) {
return true;
}
list.remove(item);
protectedComment = node;
return;
}
if (node.type !== 'WhiteSpace') {
nonSpaceTokenInBuffer = true;
}
children.insert(list.remove(item));
});
return {
comment: protectedComment,
stylesheet: {
type: 'StyleSheet',
loc: null,
children
}
};
}
function compressChunk(ast, firstAtrulesAllowed, num, options) {
options.logger(`Compress block #${num}`, null, true);
let seed = 1;
if (ast.type === 'StyleSheet') {
ast.firstAtrulesAllowed = firstAtrulesAllowed;
ast.id = seed++;
}
cssTree$1.walk(ast, {
visit: 'Atrule',
enter(node) {
if (node.block !== null) {
node.block.id = seed++;
}
}
});
options.logger('init', ast);
// remove redundant
index(ast, options);
options.logger('clean', ast);
// replace nodes for shortened forms
index$1(ast);
options.logger('replace', ast);
// structure optimisations
if (options.restructuring) {
index$2(ast, options);
}
return ast;
}
function getCommentsOption(options) {
let comments = 'comments' in options ? options.comments : 'exclamation';
if (typeof comments === 'boolean') {
comments = comments ? 'exclamation' : false;
} else if (comments !== 'exclamation' && comments !== 'first-exclamation') {
comments = false;
}
return comments;
}
function getRestructureOption(options) {
if ('restructure' in options) {
return options.restructure;
}
return 'restructuring' in options ? options.restructuring : true;
}
function wrapBlock(block) {
return new cssTree$1.List().appendData({
type: 'Rule',
loc: null,
prelude: {
type: 'SelectorList',
loc: null,
children: new cssTree$1.List().appendData({
type: 'Selector',
loc: null,
children: new cssTree$1.List().appendData({
type: 'TypeSelector',
loc: null,
name: 'x'
})
})
},
block
});
}
function compress$2(ast, options) {
ast = ast || { type: 'StyleSheet', loc: null, children: new cssTree$1.List() };
options = options || {};
const compressOptions = {
logger: typeof options.logger === 'function' ? options.logger : function() {},
restructuring: getRestructureOption(options),
forceMediaMerge: Boolean(options.forceMediaMerge),
usage: options.usage ? usage.buildIndex(options.usage) : false
};
const output = new cssTree$1.List();
let specialComments = getCommentsOption(options);
let firstAtrulesAllowed = true;
let input;
let chunk;
let chunkNum = 1;
let chunkChildren;
if (options.clone) {
ast = cssTree$1.clone(ast);
}
if (ast.type === 'StyleSheet') {
input = ast.children;
ast.children = output;
} else {
input = wrapBlock(ast);
}
do {
chunk = readChunk(input, Boolean(specialComments));
compressChunk(chunk.stylesheet, firstAtrulesAllowed, chunkNum++, compressOptions);
chunkChildren = chunk.stylesheet.children;
if (chunk.comment) {
// add \n before comment if there is another content in output
if (!output.isEmpty) {
output.insert(cssTree$1.List.createItem({
type: 'Raw',
value: '\n'
}));
}
output.insert(cssTree$1.List.createItem(chunk.comment));
// add \n after comment if chunk is not empty
if (!chunkChildren.isEmpty) {
output.insert(cssTree$1.List.createItem({
type: 'Raw',
value: '\n'
}));
}
}
if (firstAtrulesAllowed && !chunkChildren.isEmpty) {
const lastRule = chunkChildren.last;
if (lastRule.type !== 'Atrule' ||
(lastRule.name !== 'import' && lastRule.name !== 'charset')) {
firstAtrulesAllowed = false;
}
}
if (specialComments !== 'exclamation') {
specialComments = false;
}
output.appendList(chunkChildren);
} while (!input.isEmpty);
return {
ast
};
}
var compress_1 = compress$2;
const cssTree = cjs;
const compress$1 = compress_1;
const specificity$2 = specificity_1;
function encodeString(value) {
const stringApostrophe = cssTree.string.encode(value, true);
const stringQuote = cssTree.string.encode(value);
return stringApostrophe.length < stringQuote.length
? stringApostrophe
: stringQuote;
}
const {
lexer,
tokenize,
parse: parse$1,
generate: generate$1,
walk,
find,
findLast,
findAll,
fromPlainObject,
toPlainObject
} = cssTree.fork({
node: {
String: {
generate(node) {
this.token(cssTree.tokenTypes.String, encodeString(node.value));
}
},
Url: {
generate(node) {
const encodedUrl = cssTree.url.encode(node.value);
const string = encodeString(node.value);
this.token(cssTree.tokenTypes.Url,
encodedUrl.length <= string.length + 5 /* "url()".length */
? encodedUrl
: 'url(' + string + ')'
);
}
}
}
});
syntax$2.compress = compress$1;
syntax$2.specificity = specificity$2;
syntax$2.find = find;
syntax$2.findAll = findAll;
syntax$2.findLast = findLast;
syntax$2.fromPlainObject = fromPlainObject;
syntax$2.generate = generate$1;
syntax$2.lexer = lexer;
syntax$2.parse = parse$1;
syntax$2.toPlainObject = toPlainObject;
syntax$2.tokenize = tokenize;
syntax$2.walk = walk;
var utils$2 = {};
const processSelector = processSelector_1;
const utils$1 = utils$6;
utils$2.processSelector = processSelector;
utils$2.addSelectors = utils$1.addSelectors;
utils$2.compareDeclarations = utils$1.compareDeclarations;
utils$2.hasSimilarSelectors = utils$1.hasSimilarSelectors;
utils$2.isEqualDeclarations = utils$1.isEqualDeclarations;
utils$2.isEqualSelectors = utils$1.isEqualSelectors;
utils$2.unsafeToSkipNode = utils$1.unsafeToSkipNode;
const version = version$7;
const syntax = syntax$2;
const utils = utils$2;
const { parse, generate, compress } = syntax;
function debugOutput(name, options, startTime, data) {
if (options.debug) {
console.error(`## ${name} done in %d ms\n`, Date.now() - startTime);
}
return data;
}
function createDefaultLogger(level) {
let lastDebug;
return function logger(title, ast) {
let line = title;
if (ast) {
line = `[${((Date.now() - lastDebug) / 1000).toFixed(3)}s] ${line}`;
}
if (level > 1 && ast) {
let css = generate(ast);
// when level 2, limit css to 256 symbols
if (level === 2 && css.length > 256) {
css = css.substr(0, 256) + '...';
}
line += `\n ${css}\n`;
}
console.error(line);
lastDebug = Date.now();
};
}
function buildCompressOptions(options) {
options = { ...options };
if (typeof options.logger !== 'function' && options.debug) {
options.logger = createDefaultLogger(options.debug);
}
return options;
}
function runHandler(ast, options, handlers) {
if (!Array.isArray(handlers)) {
handlers = [handlers];
}
handlers.forEach(fn => fn(ast, options));
}
function minify(context, source, options) {
options = options || {};
const filename = options.filename || '<unknown>';
let result;
// parse
const ast = debugOutput('parsing', options, Date.now(),
parse(source, {
context,
filename,
positions: Boolean(options.sourceMap)
})
);
// before compress handlers
if (options.beforeCompress) {
debugOutput('beforeCompress', options, Date.now(),
runHandler(ast, options, options.beforeCompress)
);
}
// compress
const compressResult = debugOutput('compress', options, Date.now(),
compress(ast, buildCompressOptions(options))
);
// after compress handlers
if (options.afterCompress) {
debugOutput('afterCompress', options, Date.now(),
runHandler(compressResult, options, options.afterCompress)
);
}
// generate
if (options.sourceMap) {
result = debugOutput('generate(sourceMap: true)', options, Date.now(), (() => {
const tmp = generate(compressResult.ast, { sourceMap: true });
tmp.map._file = filename; // since other tools can relay on file in source map transform chain
tmp.map.setSourceContent(filename, source);
return tmp;
})());
} else {
result = debugOutput('generate', options, Date.now(), {
css: generate(compressResult.ast),
map: null
});
}
return result;
}
function minifyStylesheet(source, options) {
return minify('stylesheet', source, options);
}
function minifyBlock(source, options) {
return minify('declarationList', source, options);
}
cjs$1.version = version.version;
cjs$1.syntax = syntax;
cjs$1.utils = utils;
cjs$1.minify = minifyStylesheet;
cjs$1.minifyBlock = minifyBlock;
/**
* @typedef {import('../lib/types').Specificity} Specificity
* @typedef {import('../lib/types').XastElement} XastElement
* @typedef {import('../lib/types').XastParent} XastParent
*/
const csstree$2 = cjs$2;
const {
// @ts-ignore not defined in @types/csso
syntax: { specificity: specificity$1 },
} = cjs$1;
const {
visitSkip: visitSkip$5,
querySelectorAll: querySelectorAll$1,
detachNodeFromParent: detachNodeFromParent$f,
} = xast;
inlineStyles$1.name = 'inlineStyles';
inlineStyles$1.description = 'inline styles (additional options)';
/**
* Compares two selector specificities.
* extracted from https://github.com/keeganstreet/specificity/blob/main/specificity.js#L211
*
* @type {(a: Specificity, b: Specificity) => number}
*/
const compareSpecificity$1 = (a, b) => {
for (var i = 0; i < 4; i += 1) {
if (a[i] < b[i]) {
return -1;
} else if (a[i] > b[i]) {
return 1;
}
}
return 0;
};
/**
* @type {(value: any) => any}
*/
const toAny$1 = (value) => value;
/**
* Moves + merges styles from style elements to element styles
*
* Options
* onlyMatchedOnce (default: true)
* inline only selectors that match once
*
* removeMatchedSelectors (default: true)
* clean up matched selectors,
* leave selectors that hadn't matched
*
* useMqs (default: ['', 'screen'])
* what media queries to be used
* empty string element for styles outside media queries
*
* usePseudos (default: [''])
* what pseudo-classes/-elements to be used
* empty string element for all non-pseudo-classes and/or -elements
*
* @author strarsis <strarsis@gmail.com>
*
* @type {import('./plugins-types').Plugin<'inlineStyles'>}
*/
inlineStyles$1.fn = (root, params) => {
const {
onlyMatchedOnce = true,
removeMatchedSelectors = true,
useMqs = ['', 'screen'],
usePseudos = [''],
} = params;
/**
* @type {Array<{ node: XastElement, parentNode: XastParent, cssAst: csstree.StyleSheet }>}
*/
const styles = [];
/**
* @type {Array<{
* node: csstree.Selector,
* item: csstree.ListItem<csstree.CssNode>,
* rule: csstree.Rule,
* matchedElements?: Array<XastElement>
* }>}
*/
let selectors = [];
return {
element: {
enter: (node, parentNode) => {
// skip <foreignObject /> content
if (node.name === 'foreignObject') {
return visitSkip$5;
}
// collect only non-empty <style /> elements
if (node.name !== 'style' || node.children.length === 0) {
return;
}
// values other than the empty string or text/css are not used
if (
node.attributes.type != null &&
node.attributes.type !== '' &&
node.attributes.type !== 'text/css'
) {
return;
}
// parse css in style element
let cssText = '';
for (const child of node.children) {
if (child.type === 'text' || child.type === 'cdata') {
cssText += child.value;
}
}
/**
* @type {null | csstree.CssNode}
*/
let cssAst = null;
try {
cssAst = csstree$2.parse(cssText, {
parseValue: false,
parseCustomProperty: false,
});
} catch {
return;
}
if (cssAst.type === 'StyleSheet') {
styles.push({ node, parentNode, cssAst });
}
// collect selectors
csstree$2.walk(cssAst, {
visit: 'Selector',
enter(node, item) {
const atrule = this.atrule;
const rule = this.rule;
if (rule == null) {
return;
}
// skip media queries not included into useMqs param
let mq = '';
if (atrule != null) {
mq = atrule.name;
if (atrule.prelude != null) {
mq += ` ${csstree$2.generate(atrule.prelude)}`;
}
}
if (useMqs.includes(mq) === false) {
return;
}
/**
* @type {Array<{
* item: csstree.ListItem<csstree.CssNode>,
* list: csstree.List<csstree.CssNode>
* }>}
*/
const pseudos = [];
if (node.type === 'Selector') {
node.children.forEach((childNode, childItem, childList) => {
if (
childNode.type === 'PseudoClassSelector' ||
childNode.type === 'PseudoElementSelector'
) {
pseudos.push({ item: childItem, list: childList });
}
});
}
// skip pseudo classes and pseudo elements not includes into usePseudos param
const pseudoSelectors = csstree$2.generate({
type: 'Selector',
children: new csstree$2.List().fromArray(
pseudos.map((pseudo) => pseudo.item.data)
),
});
if (usePseudos.includes(pseudoSelectors) === false) {
return;
}
// remove pseudo classes and elements to allow querySelector match elements
// TODO this is not very accurate since some pseudo classes like first-child
// are used for selection
for (const pseudo of pseudos) {
pseudo.list.remove(pseudo.item);
}
selectors.push({ node, item, rule });
},
});
},
},
root: {
exit: () => {
if (styles.length === 0) {
return;
}
// stable sort selectors
const sortedSelectors = [...selectors]
.sort((a, b) => {
const aSpecificity = specificity$1(a.item.data);
const bSpecificity = specificity$1(b.item.data);
return compareSpecificity$1(aSpecificity, bSpecificity);
})
.reverse();
for (const selector of sortedSelectors) {
// match selectors
const selectorText = csstree$2.generate(selector.item.data);
/**
* @type {Array<XastElement>}
*/
const matchedElements = [];
try {
for (const node of querySelectorAll$1(root, selectorText)) {
if (node.type === 'element') {
matchedElements.push(node);
}
}
} catch (selectError) {
continue;
}
// nothing selected
if (matchedElements.length === 0) {
continue;
}
// apply styles to matched elements
// skip selectors that match more than once if option onlyMatchedOnce is enabled
if (onlyMatchedOnce && matchedElements.length > 1) {
continue;
}
// apply <style/> to matched elements
for (const selectedEl of matchedElements) {
const styleDeclarationList = csstree$2.parse(
selectedEl.attributes.style == null
? ''
: selectedEl.attributes.style,
{
context: 'declarationList',
parseValue: false,
}
);
if (styleDeclarationList.type !== 'DeclarationList') {
continue;
}
const styleDeclarationItems = new Map();
csstree$2.walk(styleDeclarationList, {
visit: 'Declaration',
enter(node, item) {
styleDeclarationItems.set(node.property, item);
},
});
// merge declarations
csstree$2.walk(selector.rule, {
visit: 'Declaration',
enter(ruleDeclaration) {
// existing inline styles have higher priority
// no inline styles, external styles, external styles used
// inline styles, external styles same priority as inline styles, inline styles used
// inline styles, external styles higher priority than inline styles, external styles used
const matchedItem = styleDeclarationItems.get(
ruleDeclaration.property
);
const ruleDeclarationItem =
styleDeclarationList.children.createItem(ruleDeclaration);
if (matchedItem == null) {
styleDeclarationList.children.append(ruleDeclarationItem);
} else if (
matchedItem.data.important !== true &&
ruleDeclaration.important === true
) {
styleDeclarationList.children.replace(
matchedItem,
ruleDeclarationItem
);
styleDeclarationItems.set(
ruleDeclaration.property,
ruleDeclarationItem
);
}
},
});
selectedEl.attributes.style =
csstree$2.generate(styleDeclarationList);
}
if (
removeMatchedSelectors &&
matchedElements.length !== 0 &&
selector.rule.prelude.type === 'SelectorList'
) {
// clean up matching simple selectors if option removeMatchedSelectors is enabled
selector.rule.prelude.children.remove(selector.item);
}
selector.matchedElements = matchedElements;
}
// no further processing required
if (removeMatchedSelectors === false) {
return;
}
// clean up matched class + ID attribute values
for (const selector of sortedSelectors) {
if (selector.matchedElements == null) {
continue;
}
if (onlyMatchedOnce && selector.matchedElements.length > 1) {
// skip selectors that match more than once if option onlyMatchedOnce is enabled
continue;
}
for (const selectedEl of selector.matchedElements) {
// class
const classList = new Set(
selectedEl.attributes.class == null
? null
: selectedEl.attributes.class.split(' ')
);
/**
* csstree v2 changed this type
* @type {csstree.CssNode}
*/
const firstSubSelector = toAny$1(selector.node.children.first);
if (
firstSubSelector != null &&
firstSubSelector.type === 'ClassSelector'
) {
classList.delete(firstSubSelector.name);
}
if (classList.size === 0) {
delete selectedEl.attributes.class;
} else {
selectedEl.attributes.class = Array.from(classList).join(' ');
}
// ID
if (
firstSubSelector != null &&
firstSubSelector.type === 'IdSelector'
) {
if (selectedEl.attributes.id === firstSubSelector.name) {
delete selectedEl.attributes.id;
}
}
}
}
for (const style of styles) {
csstree$2.walk(style.cssAst, {
visit: 'Rule',
enter: function (node, item, list) {
// clean up <style/> rulesets without any css selectors left
if (
node.type === 'Rule' &&
node.prelude.type === 'SelectorList' &&
// csstree v2 changed this type
toAny$1(node.prelude.children.isEmpty)
) {
list.remove(item);
}
},
});
// csstree v2 changed this type
if (toAny$1(style.cssAst.children.isEmpty)) {
// remove emtpy style element
detachNodeFromParent$f(style.node, style.parentNode);
} else {
// update style element if any styles left
const firstChild = style.node.children[0];
if (firstChild.type === 'text' || firstChild.type === 'cdata') {
firstChild.value = csstree$2.generate(style.cssAst);
}
}
}
},
},
};
};
var minifyStyles$1 = {};
/**
* @typedef {import('../lib/types').XastElement} XastElement
*/
const csso = cjs$1;
minifyStyles$1.name = 'minifyStyles';
minifyStyles$1.description =
'minifies styles and removes unused styles based on usage data';
/**
* Minifies styles (<style> element + style attribute) using CSSO
*
* @author strarsis <strarsis@gmail.com>
*
* @type {import('./plugins-types').Plugin<'minifyStyles'>}
*/
minifyStyles$1.fn = (_root, { usage, ...params }) => {
let enableTagsUsage = true;
let enableIdsUsage = true;
let enableClassesUsage = true;
// force to use usage data even if it unsafe (document contains <script> or on* attributes)
let forceUsageDeoptimized = false;
if (typeof usage === 'boolean') {
enableTagsUsage = usage;
enableIdsUsage = usage;
enableClassesUsage = usage;
} else if (usage) {
enableTagsUsage = usage.tags == null ? true : usage.tags;
enableIdsUsage = usage.ids == null ? true : usage.ids;
enableClassesUsage = usage.classes == null ? true : usage.classes;
forceUsageDeoptimized = usage.force == null ? false : usage.force;
}
/**
* @type {Array<XastElement>}
*/
const styleElements = [];
/**
* @type {Array<XastElement>}
*/
const elementsWithStyleAttributes = [];
let deoptimized = false;
/**
* @type {Set<string>}
*/
const tagsUsage = new Set();
/**
* @type {Set<string>}
*/
const idsUsage = new Set();
/**
* @type {Set<string>}
*/
const classesUsage = new Set();
return {
element: {
enter: (node) => {
// detect deoptimisations
if (node.name === 'script') {
deoptimized = true;
}
for (const name of Object.keys(node.attributes)) {
if (name.startsWith('on')) {
deoptimized = true;
}
}
// collect tags, ids and classes usage
tagsUsage.add(node.name);
if (node.attributes.id != null) {
idsUsage.add(node.attributes.id);
}
if (node.attributes.class != null) {
for (const className of node.attributes.class.split(/\s+/)) {
classesUsage.add(className);
}
}
// collect style elements or elements with style attribute
if (node.name === 'style' && node.children.length !== 0) {
styleElements.push(node);
} else if (node.attributes.style != null) {
elementsWithStyleAttributes.push(node);
}
},
},
root: {
exit: () => {
/**
* @type {csso.Usage}
*/
const cssoUsage = {};
if (deoptimized === false || forceUsageDeoptimized === true) {
if (enableTagsUsage && tagsUsage.size !== 0) {
cssoUsage.tags = Array.from(tagsUsage);
}
if (enableIdsUsage && idsUsage.size !== 0) {
cssoUsage.ids = Array.from(idsUsage);
}
if (enableClassesUsage && classesUsage.size !== 0) {
cssoUsage.classes = Array.from(classesUsage);
}
}
// minify style elements
for (const node of styleElements) {
if (
node.children[0].type === 'text' ||
node.children[0].type === 'cdata'
) {
const cssText = node.children[0].value;
const minified = csso.minify(cssText, {
...params,
usage: cssoUsage,
}).css;
// preserve cdata if necessary
// TODO split cdata -> text optimisation into separate plugin
if (cssText.indexOf('>') >= 0 || cssText.indexOf('<') >= 0) {
node.children[0].type = 'cdata';
node.children[0].value = minified;
} else {
node.children[0].type = 'text';
node.children[0].value = minified;
}
}
}
// minify style attributes
for (const node of elementsWithStyleAttributes) {
// style attribute
const elemStyle = node.attributes.style;
node.attributes.style = csso.minifyBlock(elemStyle, {
...params,
}).css;
}
},
},
};
};
var cleanupIds$1 = {};
/**
* @typedef {import('../lib/types').XastElement} XastElement
*/
const { visitSkip: visitSkip$4 } = xast;
const { referencesProps: referencesProps$3 } = _collections;
cleanupIds$1.name = 'cleanupIds';
cleanupIds$1.description = 'removes unused IDs and minifies used';
const regReferencesUrl = /\burl\((["'])?#(.+?)\1\)/;
const regReferencesHref = /^#(.+?)$/;
const regReferencesBegin = /(\D+)\./;
const generateIdChars = [
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
];
const maxIdIndex = generateIdChars.length - 1;
/**
* Check if an ID starts with any one of a list of strings.
*
* @type {(string: string, prefixes: Array<string>) => boolean}
*/
const hasStringPrefix = (string, prefixes) => {
for (const prefix of prefixes) {
if (string.startsWith(prefix)) {
return true;
}
}
return false;
};
/**
* Generate unique minimal ID.
*
* @type {(currentId: null | Array<number>) => Array<number>}
*/
const generateId = (currentId) => {
if (currentId == null) {
return [0];
}
currentId[currentId.length - 1] += 1;
for (let i = currentId.length - 1; i > 0; i--) {
if (currentId[i] > maxIdIndex) {
currentId[i] = 0;
if (currentId[i - 1] !== undefined) {
currentId[i - 1]++;
}
}
}
if (currentId[0] > maxIdIndex) {
currentId[0] = 0;
currentId.unshift(0);
}
return currentId;
};
/**
* Get string from generated ID array.
*
* @type {(arr: Array<number>) => string}
*/
const getIdString = (arr) => {
return arr.map((i) => generateIdChars[i]).join('');
};
/**
* Remove unused and minify used IDs
* (only if there are no any <style> or <script>).
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'cleanupIds'>}
*/
cleanupIds$1.fn = (_root, params) => {
const {
remove = true,
minify = true,
preserve = [],
preservePrefixes = [],
force = false,
} = params;
const preserveIds = new Set(
Array.isArray(preserve) ? preserve : preserve ? [preserve] : []
);
const preserveIdPrefixes = Array.isArray(preservePrefixes)
? preservePrefixes
: preservePrefixes
? [preservePrefixes]
: [];
/**
* @type {Map<string, XastElement>}
*/
const nodeById = new Map();
/**
* @type {Map<string, Array<{element: XastElement, name: string, value: string }>>}
*/
const referencesById = new Map();
let deoptimized = false;
return {
element: {
enter: (node) => {
if (force == false) {
// deoptimize if style or script elements are present
if (
(node.name === 'style' || node.name === 'script') &&
node.children.length !== 0
) {
deoptimized = true;
return;
}
// avoid removing IDs if the whole SVG consists only of defs
if (node.name === 'svg') {
let hasDefsOnly = true;
for (const child of node.children) {
if (child.type !== 'element' || child.name !== 'defs') {
hasDefsOnly = false;
break;
}
}
if (hasDefsOnly) {
return visitSkip$4;
}
}
}
for (const [name, value] of Object.entries(node.attributes)) {
if (name === 'id') {
// collect all ids
const id = value;
if (nodeById.has(id)) {
delete node.attributes.id; // remove repeated id
} else {
nodeById.set(id, node);
}
} else {
// collect all references
/**
* @type {null | string}
*/
let id = null;
if (referencesProps$3.includes(name)) {
const match = value.match(regReferencesUrl);
if (match != null) {
id = match[2]; // url() reference
}
}
if (name === 'href' || name.endsWith(':href')) {
const match = value.match(regReferencesHref);
if (match != null) {
id = match[1]; // href reference
}
}
if (name === 'begin') {
const match = value.match(regReferencesBegin);
if (match != null) {
id = match[1]; // href reference
}
}
if (id != null) {
let refs = referencesById.get(id);
if (refs == null) {
refs = [];
referencesById.set(id, refs);
}
refs.push({ element: node, name, value });
}
}
}
},
},
root: {
exit: () => {
if (deoptimized) {
return;
}
/**
* @type {(id: string) => boolean}
**/
const isIdPreserved = (id) =>
preserveIds.has(id) || hasStringPrefix(id, preserveIdPrefixes);
/**
* @type {null | Array<number>}
*/
let currentId = null;
for (const [id, refs] of referencesById) {
const node = nodeById.get(id);
if (node != null) {
// replace referenced IDs with the minified ones
if (minify && isIdPreserved(id) === false) {
/**
* @type {null | string}
*/
let currentIdString = null;
do {
currentId = generateId(currentId);
currentIdString = getIdString(currentId);
} while (isIdPreserved(currentIdString));
node.attributes.id = currentIdString;
for (const { element, name, value } of refs) {
if (value.includes('#')) {
// replace id in href and url()
element.attributes[name] = value.replace(
`#${id}`,
`#${currentIdString}`
);
} else {
// replace id in begin attribute
element.attributes[name] = value.replace(
`${id}.`,
`${currentIdString}.`
);
}
}
}
// keep referenced node
nodeById.delete(id);
}
}
// remove non-referenced IDs attributes from elements
if (remove) {
for (const [id, node] of nodeById) {
if (isIdPreserved(id) === false) {
delete node.attributes.id;
}
}
}
},
},
};
};
var removeUselessDefs$1 = {};
/**
* @typedef {import('../lib/types').XastElement} XastElement
*/
const { detachNodeFromParent: detachNodeFromParent$e } = xast;
const { elemsGroups: elemsGroups$4 } = _collections;
removeUselessDefs$1.name = 'removeUselessDefs';
removeUselessDefs$1.description = 'removes elements in <defs> without id';
/**
* Removes content of defs and properties that aren't rendered directly without ids.
*
* @author Lev Solntsev
*
* @type {import('./plugins-types').Plugin<'removeUselessDefs'>}
*/
removeUselessDefs$1.fn = () => {
return {
element: {
enter: (node, parentNode) => {
if (node.name === 'defs') {
/**
* @type {Array<XastElement>}
*/
const usefulNodes = [];
collectUsefulNodes(node, usefulNodes);
if (usefulNodes.length === 0) {
detachNodeFromParent$e(node, parentNode);
}
// TODO remove legacy parentNode in v4
for (const usefulNode of usefulNodes) {
Object.defineProperty(usefulNode, 'parentNode', {
writable: true,
value: node,
});
}
node.children = usefulNodes;
} else if (
elemsGroups$4.nonRendering.includes(node.name) &&
node.attributes.id == null
) {
detachNodeFromParent$e(node, parentNode);
}
},
},
};
};
/**
* @type {(node: XastElement, usefulNodes: Array<XastElement>) => void}
*/
const collectUsefulNodes = (node, usefulNodes) => {
for (const child of node.children) {
if (child.type === 'element') {
if (child.attributes.id != null || child.name === 'style') {
usefulNodes.push(child);
} else {
collectUsefulNodes(child, usefulNodes);
}
}
}
};
var cleanupNumericValues$1 = {};
var tools = {};
/**
* @typedef {import('../types').PathDataCommand} PathDataCommand
* @typedef {import('../types').DataUri} DataUri
*/
/**
* Encode plain SVG data string into Data URI string.
*
* @type {(str: string, type?: DataUri) => string}
*/
tools.encodeSVGDatauri = (str, type) => {
var prefix = 'data:image/svg+xml';
if (!type || type === 'base64') {
// base64
prefix += ';base64,';
str = prefix + Buffer.from(str).toString('base64');
} else if (type === 'enc') {
// URI encoded
str = prefix + ',' + encodeURIComponent(str);
} else if (type === 'unenc') {
// unencoded
str = prefix + ',' + str;
}
return str;
};
/**
* Decode SVG Data URI string into plain SVG string.
*
* @type {(str: string) => string}
*/
tools.decodeSVGDatauri = (str) => {
var regexp = /data:image\/svg\+xml(;charset=[^;,]*)?(;base64)?,(.*)/;
var match = regexp.exec(str);
// plain string
if (!match) return str;
var data = match[3];
if (match[2]) {
// base64
str = Buffer.from(data, 'base64').toString('utf8');
} else if (data.charAt(0) === '%') {
// URI encoded
str = decodeURIComponent(data);
} else if (data.charAt(0) === '<') {
// unencoded
str = data;
}
return str;
};
/**
* @typedef {{
* noSpaceAfterFlags?: boolean,
* leadingZero?: boolean,
* negativeExtraSpace?: boolean
* }} CleanupOutDataParams
*/
/**
* Convert a row of numbers to an optimized string view.
*
* @example
* [0, -1, .5, .5] → "0-1 .5.5"
*
* @type {(data: Array<number>, params: CleanupOutDataParams, command?: PathDataCommand) => string}
*/
tools.cleanupOutData = (data, params, command) => {
let str = '';
let delimiter;
/**
* @type {number}
*/
let prev;
data.forEach((item, i) => {
// space delimiter by default
delimiter = ' ';
// no extra space in front of first number
if (i == 0) delimiter = '';
// no extra space after 'arcto' command flags(large-arc and sweep flags)
// a20 60 45 0 1 30 20 → a20 60 45 0130 20
if (params.noSpaceAfterFlags && (command == 'A' || command == 'a')) {
var pos = i % 7;
if (pos == 4 || pos == 5) delimiter = '';
}
// remove floating-point numbers leading zeros
// 0.5 → .5
// -0.5 → -.5
const itemStr = params.leadingZero
? removeLeadingZero$3(item)
: item.toString();
// no extra space in front of negative number or
// in front of a floating number if a previous number is floating too
if (
params.negativeExtraSpace &&
delimiter != '' &&
(item < 0 || (itemStr.charAt(0) === '.' && prev % 1 !== 0))
) {
delimiter = '';
}
// save prev item value
prev = item;
str += delimiter + itemStr;
});
return str;
};
/**
* Remove floating-point numbers leading zero.
*
* @example
* 0.5 → .5
*
* @example
* -0.5 → -.5
*
* @type {(num: number) => string}
*/
const removeLeadingZero$3 = (num) => {
var strNum = num.toString();
if (0 < num && num < 1 && strNum.charAt(0) === '0') {
strNum = strNum.slice(1);
} else if (-1 < num && num < 0 && strNum.charAt(1) === '0') {
strNum = strNum.charAt(0) + strNum.slice(2);
}
return strNum;
};
tools.removeLeadingZero = removeLeadingZero$3;
const { removeLeadingZero: removeLeadingZero$2 } = tools;
cleanupNumericValues$1.name = 'cleanupNumericValues';
cleanupNumericValues$1.description =
'rounds numeric values to the fixed precision, removes default px units';
const regNumericValues$3 =
/^([-+]?\d*\.?\d+([eE][-+]?\d+)?)(px|pt|pc|mm|cm|m|in|ft|em|ex|%)?$/;
const absoluteLengths$1 = {
// relative to px
cm: 96 / 2.54,
mm: 96 / 25.4,
in: 96,
pt: 4 / 3,
pc: 16,
px: 1,
};
/**
* Round numeric values to the fixed precision,
* remove default 'px' units.
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'cleanupNumericValues'>}
*/
cleanupNumericValues$1.fn = (_root, params) => {
const {
floatPrecision = 3,
leadingZero = true,
defaultPx = true,
convertToPx = true,
} = params;
return {
element: {
enter: (node) => {
if (node.attributes.viewBox != null) {
const nums = node.attributes.viewBox.split(/\s,?\s*|,\s*/g);
node.attributes.viewBox = nums
.map((value) => {
const num = Number(value);
return Number.isNaN(num)
? value
: Number(num.toFixed(floatPrecision));
})
.join(' ');
}
for (const [name, value] of Object.entries(node.attributes)) {
// The `version` attribute is a text string and cannot be rounded
if (name === 'version') {
continue;
}
const match = value.match(regNumericValues$3);
// if attribute value matches regNumericValues
if (match) {
// round it to the fixed precision
let num = Number(Number(match[1]).toFixed(floatPrecision));
/**
* @type {any}
*/
let matchedUnit = match[3] || '';
/**
* @type{'' | keyof typeof absoluteLengths}
*/
let units = matchedUnit;
// convert absolute values to pixels
if (convertToPx && units !== '' && units in absoluteLengths$1) {
const pxNum = Number(
(absoluteLengths$1[units] * Number(match[1])).toFixed(
floatPrecision
)
);
if (pxNum.toString().length < match[0].length) {
num = pxNum;
units = 'px';
}
}
// and remove leading zero
let str;
if (leadingZero) {
str = removeLeadingZero$2(num);
} else {
str = num.toString();
}
// remove default 'px' units
if (defaultPx && units === 'px') {
units = '';
}
node.attributes[name] = str + units;
}
}
},
},
};
};
var convertColors$1 = {};
const collections = _collections;
convertColors$1.name = 'convertColors';
convertColors$1.description = 'converts colors: rgb() to #rrggbb and #rrggbb to #rgb';
const rNumber = '([+-]?(?:\\d*\\.\\d+|\\d+\\.?)%?)';
const rComma = '\\s*,\\s*';
const regRGB = new RegExp(
'^rgb\\(\\s*' + rNumber + rComma + rNumber + rComma + rNumber + '\\s*\\)$'
);
const regHEX = /^#(([a-fA-F0-9])\2){3}$/;
/**
* Convert [r, g, b] to #rrggbb.
*
* @see https://gist.github.com/983535
*
* @example
* rgb2hex([255, 255, 255]) // '#ffffff'
*
* @author Jed Schmidt
*
* @type {(rgb: Array<number>) => string}
*/
const convertRgbToHex = ([r, g, b]) => {
// combine the octets into a 32-bit integer as: [1][r][g][b]
const hexNumber =
// operator precedence is (+) > (<<) > (|)
((((256 + // [1][0]
r) << // [1][r]
8) | // [1][r][0]
g) << // [1][r][g]
8) | // [1][r][g][0]
b;
// serialize [1][r][g][b] to a hex string, and
// remove the 1 to get the number with 0s intact
return '#' + hexNumber.toString(16).slice(1).toUpperCase();
};
/**
* Convert different colors formats in element attributes to hex.
*
* @see https://www.w3.org/TR/SVG11/types.html#DataTypeColor
* @see https://www.w3.org/TR/SVG11/single-page.html#types-ColorKeywords
*
* @example
* Convert color name keyword to long hex:
* fuchsia ➡ #ff00ff
*
* Convert rgb() to long hex:
* rgb(255, 0, 255) ➡ #ff00ff
* rgb(50%, 100, 100%) ➡ #7f64ff
*
* Convert long hex to short hex:
* #aabbcc ➡ #abc
*
* Convert hex to short name
* #000080 ➡ navy
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'convertColors'>}
*/
convertColors$1.fn = (_root, params) => {
const {
currentColor = false,
names2hex = true,
rgb2hex = true,
shorthex = true,
shortname = true,
} = params;
return {
element: {
enter: (node) => {
for (const [name, value] of Object.entries(node.attributes)) {
if (collections.colorsProps.includes(name)) {
let val = value;
// convert colors to currentColor
if (currentColor) {
let matched;
if (typeof currentColor === 'string') {
matched = val === currentColor;
} else if (currentColor instanceof RegExp) {
matched = currentColor.exec(val) != null;
} else {
matched = val !== 'none';
}
if (matched) {
val = 'currentColor';
}
}
// convert color name keyword to long hex
if (names2hex) {
const colorName = val.toLowerCase();
if (collections.colorsNames[colorName] != null) {
val = collections.colorsNames[colorName];
}
}
// convert rgb() to long hex
if (rgb2hex) {
let match = val.match(regRGB);
if (match != null) {
let nums = match.slice(1, 4).map((m) => {
let n;
if (m.indexOf('%') > -1) {
n = Math.round(parseFloat(m) * 2.55);
} else {
n = Number(m);
}
return Math.max(0, Math.min(n, 255));
});
val = convertRgbToHex(nums);
}
}
// convert long hex to short hex
if (shorthex) {
let match = val.match(regHEX);
if (match != null) {
val = '#' + match[0][1] + match[0][3] + match[0][5];
}
}
// convert hex to short name
if (shortname) {
const colorName = val.toLowerCase();
if (collections.colorsShortNames[colorName] != null) {
val = collections.colorsShortNames[colorName];
}
}
node.attributes[name] = val;
}
}
},
},
};
};
var removeUnknownsAndDefaults$1 = {};
var style = {};
/**
* @typedef {import('css-tree').Rule} CsstreeRule
* @typedef {import('./types').Specificity} Specificity
* @typedef {import('./types').Stylesheet} Stylesheet
* @typedef {import('./types').StylesheetRule} StylesheetRule
* @typedef {import('./types').StylesheetDeclaration} StylesheetDeclaration
* @typedef {import('./types').ComputedStyles} ComputedStyles
* @typedef {import('./types').XastRoot} XastRoot
* @typedef {import('./types').XastElement} XastElement
* @typedef {import('./types').XastParent} XastParent
* @typedef {import('./types').XastChild} XastChild
*/
const csstree$1 = cjs$2;
const {
// @ts-ignore not defined in @types/csso
syntax: { specificity },
} = cjs$1;
const { visit: visit$5, matches } = xast;
const {
attrsGroups: attrsGroups$4,
inheritableAttrs: inheritableAttrs$3,
presentationNonInheritableGroupAttrs: presentationNonInheritableGroupAttrs$2,
} = _collections;
// @ts-ignore not defined in @types/csstree
const csstreeWalkSkip = csstree$1.walk.skip;
/**
* @type {(ruleNode: CsstreeRule, dynamic: boolean) => StylesheetRule[]}
*/
const parseRule = (ruleNode, dynamic) => {
/**
* @type {Array<StylesheetDeclaration>}
*/
const declarations = [];
// collect declarations
ruleNode.block.children.forEach((cssNode) => {
if (cssNode.type === 'Declaration') {
declarations.push({
name: cssNode.property,
value: csstree$1.generate(cssNode.value),
important: cssNode.important === true,
});
}
});
/**
* @type {StylesheetRule[]}
*/
const rules = [];
csstree$1.walk(ruleNode.prelude, (node) => {
if (node.type === 'Selector') {
const newNode = csstree$1.clone(node);
let hasPseudoClasses = false;
csstree$1.walk(newNode, (pseudoClassNode, item, list) => {
if (pseudoClassNode.type === 'PseudoClassSelector') {
hasPseudoClasses = true;
list.remove(item);
}
});
rules.push({
specificity: specificity(node),
dynamic: hasPseudoClasses || dynamic,
// compute specificity from original node to consider pseudo classes
selector: csstree$1.generate(newNode),
declarations,
});
}
});
return rules;
};
/**
* @type {(css: string, dynamic: boolean) => Array<StylesheetRule>}
*/
const parseStylesheet = (css, dynamic) => {
/**
* @type {Array<StylesheetRule>}
*/
const rules = [];
const ast = csstree$1.parse(css, {
parseValue: false,
parseAtrulePrelude: false,
});
csstree$1.walk(ast, (cssNode) => {
if (cssNode.type === 'Rule') {
rules.push(...parseRule(cssNode, dynamic || false));
return csstreeWalkSkip;
}
if (cssNode.type === 'Atrule') {
if (cssNode.name === 'keyframes') {
return csstreeWalkSkip;
}
csstree$1.walk(cssNode, (ruleNode) => {
if (ruleNode.type === 'Rule') {
rules.push(...parseRule(ruleNode, dynamic || true));
return csstreeWalkSkip;
}
});
return csstreeWalkSkip;
}
});
return rules;
};
/**
* @type {(css: string) => Array<StylesheetDeclaration>}
*/
const parseStyleDeclarations = (css) => {
/**
* @type {Array<StylesheetDeclaration>}
*/
const declarations = [];
const ast = csstree$1.parse(css, {
context: 'declarationList',
parseValue: false,
});
csstree$1.walk(ast, (cssNode) => {
if (cssNode.type === 'Declaration') {
declarations.push({
name: cssNode.property,
value: csstree$1.generate(cssNode.value),
important: cssNode.important === true,
});
}
});
return declarations;
};
/**
* @type {(stylesheet: Stylesheet, node: XastElement) => ComputedStyles}
*/
const computeOwnStyle = (stylesheet, node) => {
/**
* @type {ComputedStyles}
*/
const computedStyle = {};
const importantStyles = new Map();
// collect attributes
for (const [name, value] of Object.entries(node.attributes)) {
if (attrsGroups$4.presentation.includes(name)) {
computedStyle[name] = { type: 'static', inherited: false, value };
importantStyles.set(name, false);
}
}
// collect matching rules
for (const { selector, declarations, dynamic } of stylesheet.rules) {
if (matches(node, selector)) {
for (const { name, value, important } of declarations) {
const computed = computedStyle[name];
if (computed && computed.type === 'dynamic') {
continue;
}
if (dynamic) {
computedStyle[name] = { type: 'dynamic', inherited: false };
continue;
}
if (
computed == null ||
important === true ||
importantStyles.get(name) === false
) {
computedStyle[name] = { type: 'static', inherited: false, value };
importantStyles.set(name, important);
}
}
}
}
// collect inline styles
const styleDeclarations =
node.attributes.style == null
? []
: parseStyleDeclarations(node.attributes.style);
for (const { name, value, important } of styleDeclarations) {
const computed = computedStyle[name];
if (computed && computed.type === 'dynamic') {
continue;
}
if (
computed == null ||
important === true ||
importantStyles.get(name) === false
) {
computedStyle[name] = { type: 'static', inherited: false, value };
importantStyles.set(name, important);
}
}
return computedStyle;
};
/**
* Compares two selector specificities.
* extracted from https://github.com/keeganstreet/specificity/blob/main/specificity.js#L211
*
* @type {(a: Specificity, b: Specificity) => number}
*/
const compareSpecificity = (a, b) => {
for (let i = 0; i < 4; i += 1) {
if (a[i] < b[i]) {
return -1;
} else if (a[i] > b[i]) {
return 1;
}
}
return 0;
};
/**
* @type {(root: XastRoot) => Stylesheet}
*/
const collectStylesheet$6 = (root) => {
/**
* @type {Array<StylesheetRule>}
*/
const rules = [];
/**
* @type {Map<XastElement, XastParent>}
*/
const parents = new Map();
visit$5(root, {
element: {
enter: (node, parentNode) => {
// store parents
parents.set(node, parentNode);
// find and parse all styles
if (node.name === 'style') {
const dynamic =
node.attributes.media != null && node.attributes.media !== 'all';
if (
node.attributes.type == null ||
node.attributes.type === '' ||
node.attributes.type === 'text/css'
) {
const children = node.children;
for (const child of children) {
if (child.type === 'text' || child.type === 'cdata') {
rules.push(...parseStylesheet(child.value, dynamic));
}
}
}
}
},
},
});
// sort by selectors specificity
rules.sort((a, b) => compareSpecificity(a.specificity, b.specificity));
return { rules, parents };
};
style.collectStylesheet = collectStylesheet$6;
/**
* @type {(stylesheet: Stylesheet, node: XastElement) => ComputedStyles}
*/
const computeStyle$6 = (stylesheet, node) => {
const { parents } = stylesheet;
// collect inherited styles
const computedStyles = computeOwnStyle(stylesheet, node);
let parent = parents.get(node);
while (parent != null && parent.type !== 'root') {
const inheritedStyles = computeOwnStyle(stylesheet, parent);
for (const [name, computed] of Object.entries(inheritedStyles)) {
if (
computedStyles[name] == null &&
// ignore not inheritable styles
inheritableAttrs$3.includes(name) === true &&
presentationNonInheritableGroupAttrs$2.includes(name) === false
) {
computedStyles[name] = { ...computed, inherited: true };
}
}
parent = parents.get(parent);
}
return computedStyles;
};
style.computeStyle = computeStyle$6;
const { visitSkip: visitSkip$3, detachNodeFromParent: detachNodeFromParent$d } = xast;
const { collectStylesheet: collectStylesheet$5, computeStyle: computeStyle$5 } = style;
const {
elems,
attrsGroups: attrsGroups$3,
elemsGroups: elemsGroups$3,
attrsGroupsDefaults: attrsGroupsDefaults$1,
presentationNonInheritableGroupAttrs: presentationNonInheritableGroupAttrs$1,
} = _collections;
removeUnknownsAndDefaults$1.name = 'removeUnknownsAndDefaults';
removeUnknownsAndDefaults$1.description =
'removes unknown elements content and attributes, removes attrs with default values';
// resolve all groups references
/**
* @type {Map<string, Set<string>>}
*/
const allowedChildrenPerElement = new Map();
/**
* @type {Map<string, Set<string>>}
*/
const allowedAttributesPerElement = new Map();
/**
* @type {Map<string, Map<string, string>>}
*/
const attributesDefaultsPerElement = new Map();
for (const [name, config] of Object.entries(elems)) {
/**
* @type {Set<string>}
*/
const allowedChildren = new Set();
if (config.content) {
for (const elementName of config.content) {
allowedChildren.add(elementName);
}
}
if (config.contentGroups) {
for (const contentGroupName of config.contentGroups) {
const elemsGroup = elemsGroups$3[contentGroupName];
if (elemsGroup) {
for (const elementName of elemsGroup) {
allowedChildren.add(elementName);
}
}
}
}
/**
* @type {Set<string>}
*/
const allowedAttributes = new Set();
if (config.attrs) {
for (const attrName of config.attrs) {
allowedAttributes.add(attrName);
}
}
/**
* @type {Map<string, string>}
*/
const attributesDefaults = new Map();
if (config.defaults) {
for (const [attrName, defaultValue] of Object.entries(config.defaults)) {
attributesDefaults.set(attrName, defaultValue);
}
}
for (const attrsGroupName of config.attrsGroups) {
const attrsGroup = attrsGroups$3[attrsGroupName];
if (attrsGroup) {
for (const attrName of attrsGroup) {
allowedAttributes.add(attrName);
}
}
const groupDefaults = attrsGroupsDefaults$1[attrsGroupName];
if (groupDefaults) {
for (const [attrName, defaultValue] of Object.entries(groupDefaults)) {
attributesDefaults.set(attrName, defaultValue);
}
}
}
allowedChildrenPerElement.set(name, allowedChildren);
allowedAttributesPerElement.set(name, allowedAttributes);
attributesDefaultsPerElement.set(name, attributesDefaults);
}
/**
* Remove unknown elements content and attributes,
* remove attributes with default values.
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'removeUnknownsAndDefaults'>}
*/
removeUnknownsAndDefaults$1.fn = (root, params) => {
const {
unknownContent = true,
unknownAttrs = true,
defaultAttrs = true,
uselessOverrides = true,
keepDataAttrs = true,
keepAriaAttrs = true,
keepRoleAttr = false,
} = params;
const stylesheet = collectStylesheet$5(root);
return {
element: {
enter: (node, parentNode) => {
// skip namespaced elements
if (node.name.includes(':')) {
return;
}
// skip visiting foreignObject subtree
if (node.name === 'foreignObject') {
return visitSkip$3;
}
// remove unknown element's content
if (unknownContent && parentNode.type === 'element') {
const allowedChildren = allowedChildrenPerElement.get(
parentNode.name
);
if (allowedChildren == null || allowedChildren.size === 0) {
// remove unknown elements
if (allowedChildrenPerElement.get(node.name) == null) {
detachNodeFromParent$d(node, parentNode);
return;
}
} else {
// remove not allowed children
if (allowedChildren.has(node.name) === false) {
detachNodeFromParent$d(node, parentNode);
return;
}
}
}
const allowedAttributes = allowedAttributesPerElement.get(node.name);
const attributesDefaults = attributesDefaultsPerElement.get(node.name);
const computedParentStyle =
parentNode.type === 'element'
? computeStyle$5(stylesheet, parentNode)
: null;
// remove element's unknown attrs and attrs with default values
for (const [name, value] of Object.entries(node.attributes)) {
if (keepDataAttrs && name.startsWith('data-')) {
continue;
}
if (keepAriaAttrs && name.startsWith('aria-')) {
continue;
}
if (keepRoleAttr && name === 'role') {
continue;
}
// skip xmlns attribute
if (name === 'xmlns') {
continue;
}
// skip namespaced attributes except xml:* and xlink:*
if (name.includes(':')) {
const [prefix] = name.split(':');
if (prefix !== 'xml' && prefix !== 'xlink') {
continue;
}
}
if (
unknownAttrs &&
allowedAttributes &&
allowedAttributes.has(name) === false
) {
delete node.attributes[name];
}
if (
defaultAttrs &&
node.attributes.id == null &&
attributesDefaults &&
attributesDefaults.get(name) === value
) {
// keep defaults if parent has own or inherited style
if (
computedParentStyle == null ||
computedParentStyle[name] == null
) {
delete node.attributes[name];
}
}
if (uselessOverrides && node.attributes.id == null) {
const style =
computedParentStyle == null ? null : computedParentStyle[name];
if (
presentationNonInheritableGroupAttrs$1.includes(name) === false &&
style != null &&
style.type === 'static' &&
style.value === value
) {
delete node.attributes[name];
}
}
}
},
},
};
};
var removeNonInheritableGroupAttrs$1 = {};
const {
inheritableAttrs: inheritableAttrs$2,
attrsGroups: attrsGroups$2,
presentationNonInheritableGroupAttrs,
} = _collections;
removeNonInheritableGroupAttrs$1.name = 'removeNonInheritableGroupAttrs';
removeNonInheritableGroupAttrs$1.description =
'removes non-inheritable groups presentational attributes';
/**
* Remove non-inheritable group's "presentation" attributes.
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'removeNonInheritableGroupAttrs'>}
*/
removeNonInheritableGroupAttrs$1.fn = () => {
return {
element: {
enter: (node) => {
if (node.name === 'g') {
for (const name of Object.keys(node.attributes)) {
if (
attrsGroups$2.presentation.includes(name) === true &&
inheritableAttrs$2.includes(name) === false &&
presentationNonInheritableGroupAttrs.includes(name) === false
) {
delete node.attributes[name];
}
}
}
},
},
};
};
var removeUselessStrokeAndFill$1 = {};
const { visit: visit$4, visitSkip: visitSkip$2, detachNodeFromParent: detachNodeFromParent$c } = xast;
const { collectStylesheet: collectStylesheet$4, computeStyle: computeStyle$4 } = style;
const { elemsGroups: elemsGroups$2 } = _collections;
removeUselessStrokeAndFill$1.name = 'removeUselessStrokeAndFill';
removeUselessStrokeAndFill$1.description = 'removes useless stroke and fill attributes';
/**
* Remove useless stroke and fill attrs.
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'removeUselessStrokeAndFill'>}
*/
removeUselessStrokeAndFill$1.fn = (root, params) => {
const {
stroke: removeStroke = true,
fill: removeFill = true,
removeNone = false,
} = params;
// style and script elements deoptimise this plugin
let hasStyleOrScript = false;
visit$4(root, {
element: {
enter: (node) => {
if (node.name === 'style' || node.name === 'script') {
hasStyleOrScript = true;
}
},
},
});
if (hasStyleOrScript) {
return null;
}
const stylesheet = collectStylesheet$4(root);
return {
element: {
enter: (node, parentNode) => {
// id attribute deoptimise the whole subtree
if (node.attributes.id != null) {
return visitSkip$2;
}
if (elemsGroups$2.shape.includes(node.name) == false) {
return;
}
const computedStyle = computeStyle$4(stylesheet, node);
const stroke = computedStyle.stroke;
const strokeOpacity = computedStyle['stroke-opacity'];
const strokeWidth = computedStyle['stroke-width'];
const markerEnd = computedStyle['marker-end'];
const fill = computedStyle.fill;
const fillOpacity = computedStyle['fill-opacity'];
const computedParentStyle =
parentNode.type === 'element'
? computeStyle$4(stylesheet, parentNode)
: null;
const parentStroke =
computedParentStyle == null ? null : computedParentStyle.stroke;
// remove stroke*
if (removeStroke) {
if (
stroke == null ||
(stroke.type === 'static' && stroke.value == 'none') ||
(strokeOpacity != null &&
strokeOpacity.type === 'static' &&
strokeOpacity.value === '0') ||
(strokeWidth != null &&
strokeWidth.type === 'static' &&
strokeWidth.value === '0')
) {
// stroke-width may affect the size of marker-end
// marker is not visible when stroke-width is 0
if (
(strokeWidth != null &&
strokeWidth.type === 'static' &&
strokeWidth.value === '0') ||
markerEnd == null
) {
for (const name of Object.keys(node.attributes)) {
if (name.startsWith('stroke')) {
delete node.attributes[name];
}
}
// set explicit none to not inherit from parent
if (
parentStroke != null &&
parentStroke.type === 'static' &&
parentStroke.value !== 'none'
) {
node.attributes.stroke = 'none';
}
}
}
}
// remove fill*
if (removeFill) {
if (
(fill != null && fill.type === 'static' && fill.value === 'none') ||
(fillOpacity != null &&
fillOpacity.type === 'static' &&
fillOpacity.value === '0')
) {
for (const name of Object.keys(node.attributes)) {
if (name.startsWith('fill-')) {
delete node.attributes[name];
}
}
if (
fill == null ||
(fill.type === 'static' && fill.value !== 'none')
) {
node.attributes.fill = 'none';
}
}
}
if (removeNone) {
if (
(stroke == null || node.attributes.stroke === 'none') &&
((fill != null &&
fill.type === 'static' &&
fill.value === 'none') ||
node.attributes.fill === 'none')
) {
detachNodeFromParent$c(node, parentNode);
}
}
},
},
};
};
var removeViewBox$1 = {};
removeViewBox$1.name = 'removeViewBox';
removeViewBox$1.description = 'removes viewBox attribute when possible';
const viewBoxElems = ['svg', 'pattern', 'symbol'];
/**
* Remove viewBox attr which coincides with a width/height box.
*
* @see https://www.w3.org/TR/SVG11/coords.html#ViewBoxAttribute
*
* @example
* <svg width="100" height="50" viewBox="0 0 100 50">
* ⬇
* <svg width="100" height="50">
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'removeViewBox'>}
*/
removeViewBox$1.fn = () => {
return {
element: {
enter: (node, parentNode) => {
if (
viewBoxElems.includes(node.name) &&
node.attributes.viewBox != null &&
node.attributes.width != null &&
node.attributes.height != null
) {
// TODO remove width/height for such case instead
if (node.name === 'svg' && parentNode.type !== 'root') {
return;
}
const nums = node.attributes.viewBox.split(/[ ,]+/g);
if (
nums[0] === '0' &&
nums[1] === '0' &&
node.attributes.width.replace(/px$/, '') === nums[2] && // could use parseFloat too
node.attributes.height.replace(/px$/, '') === nums[3]
) {
delete node.attributes.viewBox;
}
}
},
},
};
};
var cleanupEnableBackground$1 = {};
const { visit: visit$3 } = xast;
cleanupEnableBackground$1.name = 'cleanupEnableBackground';
cleanupEnableBackground$1.description =
'remove or cleanup enable-background attribute when possible';
/**
* Remove or cleanup enable-background attr which coincides with a width/height box.
*
* @see https://www.w3.org/TR/SVG11/filters.html#EnableBackgroundProperty
*
* @example
* <svg width="100" height="50" enable-background="new 0 0 100 50">
* ⬇
* <svg width="100" height="50">
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'cleanupEnableBackground'>}
*/
cleanupEnableBackground$1.fn = (root) => {
const regEnableBackground =
/^new\s0\s0\s([-+]?\d*\.?\d+([eE][-+]?\d+)?)\s([-+]?\d*\.?\d+([eE][-+]?\d+)?)$/;
let hasFilter = false;
visit$3(root, {
element: {
enter: (node) => {
if (node.name === 'filter') {
hasFilter = true;
}
},
},
});
return {
element: {
enter: (node) => {
if (node.attributes['enable-background'] == null) {
return;
}
if (hasFilter) {
if (
(node.name === 'svg' ||
node.name === 'mask' ||
node.name === 'pattern') &&
node.attributes.width != null &&
node.attributes.height != null
) {
const match =
node.attributes['enable-background'].match(regEnableBackground);
if (
match != null &&
node.attributes.width === match[1] &&
node.attributes.height === match[3]
) {
if (node.name === 'svg') {
delete node.attributes['enable-background'];
} else {
node.attributes['enable-background'] = 'new';
}
}
}
} else {
//we don't need 'enable-background' if we have no filters
delete node.attributes['enable-background'];
}
},
},
};
};
var removeHiddenElems$1 = {};
var path = {};
/**
* @typedef {import('./types').PathDataItem} PathDataItem
* @typedef {import('./types').PathDataCommand} PathDataCommand
*/
// Based on https://www.w3.org/TR/SVG11/paths.html#PathDataBNF
const argsCountPerCommand = {
M: 2,
m: 2,
Z: 0,
z: 0,
L: 2,
l: 2,
H: 1,
h: 1,
V: 1,
v: 1,
C: 6,
c: 6,
S: 4,
s: 4,
Q: 4,
q: 4,
T: 2,
t: 2,
A: 7,
a: 7,
};
/**
* @type {(c: string) => c is PathDataCommand}
*/
const isCommand = (c) => {
return c in argsCountPerCommand;
};
/**
* @type {(c: string) => boolean}
*/
const isWsp = (c) => {
const codePoint = c.codePointAt(0);
return (
codePoint === 0x20 ||
codePoint === 0x9 ||
codePoint === 0xd ||
codePoint === 0xa
);
};
/**
* @type {(c: string) => boolean}
*/
const isDigit = (c) => {
const codePoint = c.codePointAt(0);
if (codePoint == null) {
return false;
}
return 48 <= codePoint && codePoint <= 57;
};
/**
* @typedef {'none' | 'sign' | 'whole' | 'decimal_point' | 'decimal' | 'e' | 'exponent_sign' | 'exponent'} ReadNumberState
*/
/**
* @type {(string: string, cursor: number) => [number, number | null]}
*/
const readNumber = (string, cursor) => {
let i = cursor;
let value = '';
let state = /** @type {ReadNumberState} */ ('none');
for (; i < string.length; i += 1) {
const c = string[i];
if (c === '+' || c === '-') {
if (state === 'none') {
state = 'sign';
value += c;
continue;
}
if (state === 'e') {
state = 'exponent_sign';
value += c;
continue;
}
}
if (isDigit(c)) {
if (state === 'none' || state === 'sign' || state === 'whole') {
state = 'whole';
value += c;
continue;
}
if (state === 'decimal_point' || state === 'decimal') {
state = 'decimal';
value += c;
continue;
}
if (state === 'e' || state === 'exponent_sign' || state === 'exponent') {
state = 'exponent';
value += c;
continue;
}
}
if (c === '.') {
if (state === 'none' || state === 'sign' || state === 'whole') {
state = 'decimal_point';
value += c;
continue;
}
}
if (c === 'E' || c == 'e') {
if (
state === 'whole' ||
state === 'decimal_point' ||
state === 'decimal'
) {
state = 'e';
value += c;
continue;
}
}
break;
}
const number = Number.parseFloat(value);
if (Number.isNaN(number)) {
return [cursor, null];
} else {
// step back to delegate iteration to parent loop
return [i - 1, number];
}
};
/**
* @type {(string: string) => Array<PathDataItem>}
*/
const parsePathData$3 = (string) => {
/**
* @type {Array<PathDataItem>}
*/
const pathData = [];
/**
* @type {null | PathDataCommand}
*/
let command = null;
let args = /** @type {number[]} */ ([]);
let argsCount = 0;
let canHaveComma = false;
let hadComma = false;
for (let i = 0; i < string.length; i += 1) {
const c = string.charAt(i);
if (isWsp(c)) {
continue;
}
// allow comma only between arguments
if (canHaveComma && c === ',') {
if (hadComma) {
break;
}
hadComma = true;
continue;
}
if (isCommand(c)) {
if (hadComma) {
return pathData;
}
if (command == null) {
// moveto should be leading command
if (c !== 'M' && c !== 'm') {
return pathData;
}
} else {
// stop if previous command arguments are not flushed
if (args.length !== 0) {
return pathData;
}
}
command = c;
args = [];
argsCount = argsCountPerCommand[command];
canHaveComma = false;
// flush command without arguments
if (argsCount === 0) {
pathData.push({ command, args });
}
continue;
}
// avoid parsing arguments if no command detected
if (command == null) {
return pathData;
}
// read next argument
let newCursor = i;
let number = null;
if (command === 'A' || command === 'a') {
const position = args.length;
if (position === 0 || position === 1) {
// allow only positive number without sign as first two arguments
if (c !== '+' && c !== '-') {
[newCursor, number] = readNumber(string, i);
}
}
if (position === 2 || position === 5 || position === 6) {
[newCursor, number] = readNumber(string, i);
}
if (position === 3 || position === 4) {
// read flags
if (c === '0') {
number = 0;
}
if (c === '1') {
number = 1;
}
}
} else {
[newCursor, number] = readNumber(string, i);
}
if (number == null) {
return pathData;
}
args.push(number);
canHaveComma = true;
hadComma = false;
i = newCursor;
// flush arguments when necessary count is reached
if (args.length === argsCount) {
pathData.push({ command, args });
// subsequent moveto coordinates are threated as implicit lineto commands
if (command === 'M') {
command = 'L';
}
if (command === 'm') {
command = 'l';
}
args = [];
}
}
return pathData;
};
path.parsePathData = parsePathData$3;
/**
* @type {(number: number, precision?: number) => string}
*/
const stringifyNumber = (number, precision) => {
if (precision != null) {
const ratio = 10 ** precision;
number = Math.round(number * ratio) / ratio;
}
// remove zero whole from decimal number
return number.toString().replace(/^0\./, '.').replace(/^-0\./, '-.');
};
/**
* Elliptical arc large-arc and sweep flags are rendered with spaces
* because many non-browser environments are not able to parse such paths
*
* @type {(
* command: string,
* args: number[],
* precision?: number,
* disableSpaceAfterFlags?: boolean
* ) => string}
*/
const stringifyArgs = (command, args, precision, disableSpaceAfterFlags) => {
let result = '';
let prev = '';
for (let i = 0; i < args.length; i += 1) {
const number = args[i];
const numberString = stringifyNumber(number, precision);
if (
disableSpaceAfterFlags &&
(command === 'A' || command === 'a') &&
// consider combined arcs
(i % 7 === 4 || i % 7 === 5)
) {
result += numberString;
} else if (i === 0 || numberString.startsWith('-')) {
// avoid space before first and negative numbers
result += numberString;
} else if (prev.includes('.') && numberString.startsWith('.')) {
// remove space before decimal with zero whole
// only when previous number is also decimal
result += numberString;
} else {
result += ` ${numberString}`;
}
prev = numberString;
}
return result;
};
/**
* @typedef {{
* pathData: Array<PathDataItem>;
* precision?: number;
* disableSpaceAfterFlags?: boolean;
* }} StringifyPathDataOptions
*/
/**
* @type {(options: StringifyPathDataOptions) => string}
*/
const stringifyPathData$2 = ({ pathData, precision, disableSpaceAfterFlags }) => {
// combine sequence of the same commands
let combined = [];
for (let i = 0; i < pathData.length; i += 1) {
const { command, args } = pathData[i];
if (i === 0) {
combined.push({ command, args });
} else {
/**
* @type {PathDataItem}
*/
const last = combined[combined.length - 1];
// match leading moveto with following lineto
if (i === 1) {
if (command === 'L') {
last.command = 'M';
}
if (command === 'l') {
last.command = 'm';
}
}
if (
(last.command === command &&
last.command !== 'M' &&
last.command !== 'm') ||
// combine matching moveto and lineto sequences
(last.command === 'M' && command === 'L') ||
(last.command === 'm' && command === 'l')
) {
last.args = [...last.args, ...args];
} else {
combined.push({ command, args });
}
}
}
let result = '';
for (const { command, args } of combined) {
result +=
command + stringifyArgs(command, args, precision, disableSpaceAfterFlags);
}
return result;
};
path.stringifyPathData = stringifyPathData$2;
const {
visit: visit$2,
visitSkip: visitSkip$1,
querySelector,
detachNodeFromParent: detachNodeFromParent$b,
} = xast;
const { collectStylesheet: collectStylesheet$3, computeStyle: computeStyle$3 } = style;
const { parsePathData: parsePathData$2 } = path;
removeHiddenElems$1.name = 'removeHiddenElems';
removeHiddenElems$1.description =
'removes hidden elements (zero sized, with absent attributes)';
/**
* Remove hidden elements with disabled rendering:
* - display="none"
* - opacity="0"
* - circle with zero radius
* - ellipse with zero x-axis or y-axis radius
* - rectangle with zero width or height
* - pattern with zero width or height
* - image with zero width or height
* - path with empty data
* - polyline with empty points
* - polygon with empty points
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'removeHiddenElems'>}
*/
removeHiddenElems$1.fn = (root, params) => {
const {
isHidden = true,
displayNone = true,
opacity0 = true,
circleR0 = true,
ellipseRX0 = true,
ellipseRY0 = true,
rectWidth0 = true,
rectHeight0 = true,
patternWidth0 = true,
patternHeight0 = true,
imageWidth0 = true,
imageHeight0 = true,
pathEmptyD = true,
polylineEmptyPoints = true,
polygonEmptyPoints = true,
} = params;
const stylesheet = collectStylesheet$3(root);
visit$2(root, {
element: {
enter: (node, parentNode) => {
// transparent element inside clipPath still affect clipped elements
if (node.name === 'clipPath') {
return visitSkip$1;
}
const computedStyle = computeStyle$3(stylesheet, node);
// opacity="0"
//
// https://www.w3.org/TR/SVG11/masking.html#ObjectAndGroupOpacityProperties
if (
opacity0 &&
computedStyle.opacity &&
computedStyle.opacity.type === 'static' &&
computedStyle.opacity.value === '0'
) {
detachNodeFromParent$b(node, parentNode);
return;
}
},
},
});
return {
element: {
enter: (node, parentNode) => {
// Removes hidden elements
// https://www.w3schools.com/cssref/pr_class_visibility.asp
const computedStyle = computeStyle$3(stylesheet, node);
if (
isHidden &&
computedStyle.visibility &&
computedStyle.visibility.type === 'static' &&
computedStyle.visibility.value === 'hidden' &&
// keep if any descendant enables visibility
querySelector(node, '[visibility=visible]') == null
) {
detachNodeFromParent$b(node, parentNode);
return;
}
// display="none"
//
// https://www.w3.org/TR/SVG11/painting.html#DisplayProperty
// "A value of display: none indicates that the given element
// and its children shall not be rendered directly"
if (
displayNone &&
computedStyle.display &&
computedStyle.display.type === 'static' &&
computedStyle.display.value === 'none' &&
// markers with display: none still rendered
node.name !== 'marker'
) {
detachNodeFromParent$b(node, parentNode);
return;
}
// Circles with zero radius
//
// https://www.w3.org/TR/SVG11/shapes.html#CircleElementRAttribute
// "A value of zero disables rendering of the element"
//
// <circle r="0">
if (
circleR0 &&
node.name === 'circle' &&
node.children.length === 0 &&
node.attributes.r === '0'
) {
detachNodeFromParent$b(node, parentNode);
return;
}
// Ellipse with zero x-axis radius
//
// https://www.w3.org/TR/SVG11/shapes.html#EllipseElementRXAttribute
// "A value of zero disables rendering of the element"
//
// <ellipse rx="0">
if (
ellipseRX0 &&
node.name === 'ellipse' &&
node.children.length === 0 &&
node.attributes.rx === '0'
) {
detachNodeFromParent$b(node, parentNode);
return;
}
// Ellipse with zero y-axis radius
//
// https://www.w3.org/TR/SVG11/shapes.html#EllipseElementRYAttribute
// "A value of zero disables rendering of the element"
//
// <ellipse ry="0">
if (
ellipseRY0 &&
node.name === 'ellipse' &&
node.children.length === 0 &&
node.attributes.ry === '0'
) {
detachNodeFromParent$b(node, parentNode);
return;
}
// Rectangle with zero width
//
// https://www.w3.org/TR/SVG11/shapes.html#RectElementWidthAttribute
// "A value of zero disables rendering of the element"
//
// <rect width="0">
if (
rectWidth0 &&
node.name === 'rect' &&
node.children.length === 0 &&
node.attributes.width === '0'
) {
detachNodeFromParent$b(node, parentNode);
return;
}
// Rectangle with zero height
//
// https://www.w3.org/TR/SVG11/shapes.html#RectElementHeightAttribute
// "A value of zero disables rendering of the element"
//
// <rect height="0">
if (
rectHeight0 &&
rectWidth0 &&
node.name === 'rect' &&
node.children.length === 0 &&
node.attributes.height === '0'
) {
detachNodeFromParent$b(node, parentNode);
return;
}
// Pattern with zero width
//
// https://www.w3.org/TR/SVG11/pservers.html#PatternElementWidthAttribute
// "A value of zero disables rendering of the element (i.e., no paint is applied)"
//
// <pattern width="0">
if (
patternWidth0 &&
node.name === 'pattern' &&
node.attributes.width === '0'
) {
detachNodeFromParent$b(node, parentNode);
return;
}
// Pattern with zero height
//
// https://www.w3.org/TR/SVG11/pservers.html#PatternElementHeightAttribute
// "A value of zero disables rendering of the element (i.e., no paint is applied)"
//
// <pattern height="0">
if (
patternHeight0 &&
node.name === 'pattern' &&
node.attributes.height === '0'
) {
detachNodeFromParent$b(node, parentNode);
return;
}
// Image with zero width
//
// https://www.w3.org/TR/SVG11/struct.html#ImageElementWidthAttribute
// "A value of zero disables rendering of the element"
//
// <image width="0">
if (
imageWidth0 &&
node.name === 'image' &&
node.attributes.width === '0'
) {
detachNodeFromParent$b(node, parentNode);
return;
}
// Image with zero height
//
// https://www.w3.org/TR/SVG11/struct.html#ImageElementHeightAttribute
// "A value of zero disables rendering of the element"
//
// <image height="0">
if (
imageHeight0 &&
node.name === 'image' &&
node.attributes.height === '0'
) {
detachNodeFromParent$b(node, parentNode);
return;
}
// Path with empty data
//
// https://www.w3.org/TR/SVG11/paths.html#DAttribute
//
// <path d=""/>
if (pathEmptyD && node.name === 'path') {
if (node.attributes.d == null) {
detachNodeFromParent$b(node, parentNode);
return;
}
const pathData = parsePathData$2(node.attributes.d);
if (pathData.length === 0) {
detachNodeFromParent$b(node, parentNode);
return;
}
// keep single point paths for markers
if (
pathData.length === 1 &&
computedStyle['marker-start'] == null &&
computedStyle['marker-end'] == null
) {
detachNodeFromParent$b(node, parentNode);
return;
}
return;
}
// Polyline with empty points
//
// https://www.w3.org/TR/SVG11/shapes.html#PolylineElementPointsAttribute
//
// <polyline points="">
if (
polylineEmptyPoints &&
node.name === 'polyline' &&
node.attributes.points == null
) {
detachNodeFromParent$b(node, parentNode);
return;
}
// Polygon with empty points
//
// https://www.w3.org/TR/SVG11/shapes.html#PolygonElementPointsAttribute
//
// <polygon points="">
if (
polygonEmptyPoints &&
node.name === 'polygon' &&
node.attributes.points == null
) {
detachNodeFromParent$b(node, parentNode);
return;
}
},
},
};
};
var removeEmptyText$1 = {};
const { detachNodeFromParent: detachNodeFromParent$a } = xast;
removeEmptyText$1.name = 'removeEmptyText';
removeEmptyText$1.description = 'removes empty <text> elements';
/**
* Remove empty Text elements.
*
* @see https://www.w3.org/TR/SVG11/text.html
*
* @example
* Remove empty text element:
* <text/>
*
* Remove empty tspan element:
* <tspan/>
*
* Remove tref with empty xlink:href attribute:
* <tref xlink:href=""/>
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'removeEmptyText'>}
*/
removeEmptyText$1.fn = (root, params) => {
const { text = true, tspan = true, tref = true } = params;
return {
element: {
enter: (node, parentNode) => {
// Remove empty text element
if (text && node.name === 'text' && node.children.length === 0) {
detachNodeFromParent$a(node, parentNode);
}
// Remove empty tspan element
if (tspan && node.name === 'tspan' && node.children.length === 0) {
detachNodeFromParent$a(node, parentNode);
}
// Remove tref with empty xlink:href attribute
if (
tref &&
node.name === 'tref' &&
node.attributes['xlink:href'] == null
) {
detachNodeFromParent$a(node, parentNode);
}
},
},
};
};
var convertShapeToPath$1 = {};
/**
* @typedef {import('../lib/types').PathDataItem} PathDataItem
*/
const { stringifyPathData: stringifyPathData$1 } = path;
const { detachNodeFromParent: detachNodeFromParent$9 } = xast;
convertShapeToPath$1.name = 'convertShapeToPath';
convertShapeToPath$1.description = 'converts basic shapes to more compact path form';
const regNumber = /[-+]?(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?/g;
/**
* Converts basic shape to more compact path.
* It also allows further optimizations like
* combining paths with similar attributes.
*
* @see https://www.w3.org/TR/SVG11/shapes.html
*
* @author Lev Solntsev
*
* @type {import('./plugins-types').Plugin<'convertShapeToPath'>}
*/
convertShapeToPath$1.fn = (root, params) => {
const { convertArcs = false, floatPrecision: precision } = params;
return {
element: {
enter: (node, parentNode) => {
// convert rect to path
if (
node.name === 'rect' &&
node.attributes.width != null &&
node.attributes.height != null &&
node.attributes.rx == null &&
node.attributes.ry == null
) {
const x = Number(node.attributes.x || '0');
const y = Number(node.attributes.y || '0');
const width = Number(node.attributes.width);
const height = Number(node.attributes.height);
// Values like '100%' compute to NaN, thus running after
// cleanupNumericValues when 'px' units has already been removed.
// TODO: Calculate sizes from % and non-px units if possible.
if (Number.isNaN(x - y + width - height)) return;
/**
* @type {Array<PathDataItem>}
*/
const pathData = [
{ command: 'M', args: [x, y] },
{ command: 'H', args: [x + width] },
{ command: 'V', args: [y + height] },
{ command: 'H', args: [x] },
{ command: 'z', args: [] },
];
node.name = 'path';
node.attributes.d = stringifyPathData$1({ pathData, precision });
delete node.attributes.x;
delete node.attributes.y;
delete node.attributes.width;
delete node.attributes.height;
}
// convert line to path
if (node.name === 'line') {
const x1 = Number(node.attributes.x1 || '0');
const y1 = Number(node.attributes.y1 || '0');
const x2 = Number(node.attributes.x2 || '0');
const y2 = Number(node.attributes.y2 || '0');
if (Number.isNaN(x1 - y1 + x2 - y2)) return;
/**
* @type {Array<PathDataItem>}
*/
const pathData = [
{ command: 'M', args: [x1, y1] },
{ command: 'L', args: [x2, y2] },
];
node.name = 'path';
node.attributes.d = stringifyPathData$1({ pathData, precision });
delete node.attributes.x1;
delete node.attributes.y1;
delete node.attributes.x2;
delete node.attributes.y2;
}
// convert polyline and polygon to path
if (
(node.name === 'polyline' || node.name === 'polygon') &&
node.attributes.points != null
) {
const coords = (node.attributes.points.match(regNumber) || []).map(
Number
);
if (coords.length < 4) {
detachNodeFromParent$9(node, parentNode);
return;
}
/**
* @type {Array<PathDataItem>}
*/
const pathData = [];
for (let i = 0; i < coords.length; i += 2) {
pathData.push({
command: i === 0 ? 'M' : 'L',
args: coords.slice(i, i + 2),
});
}
if (node.name === 'polygon') {
pathData.push({ command: 'z', args: [] });
}
node.name = 'path';
node.attributes.d = stringifyPathData$1({ pathData, precision });
delete node.attributes.points;
}
// optionally convert circle
if (node.name === 'circle' && convertArcs) {
const cx = Number(node.attributes.cx || '0');
const cy = Number(node.attributes.cy || '0');
const r = Number(node.attributes.r || '0');
if (Number.isNaN(cx - cy + r)) {
return;
}
/**
* @type {Array<PathDataItem>}
*/
const pathData = [
{ command: 'M', args: [cx, cy - r] },
{ command: 'A', args: [r, r, 0, 1, 0, cx, cy + r] },
{ command: 'A', args: [r, r, 0, 1, 0, cx, cy - r] },
{ command: 'z', args: [] },
];
node.name = 'path';
node.attributes.d = stringifyPathData$1({ pathData, precision });
delete node.attributes.cx;
delete node.attributes.cy;
delete node.attributes.r;
}
// optionally covert ellipse
if (node.name === 'ellipse' && convertArcs) {
const ecx = Number(node.attributes.cx || '0');
const ecy = Number(node.attributes.cy || '0');
const rx = Number(node.attributes.rx || '0');
const ry = Number(node.attributes.ry || '0');
if (Number.isNaN(ecx - ecy + rx - ry)) {
return;
}
/**
* @type {Array<PathDataItem>}
*/
const pathData = [
{ command: 'M', args: [ecx, ecy - ry] },
{ command: 'A', args: [rx, ry, 0, 1, 0, ecx, ecy + ry] },
{ command: 'A', args: [rx, ry, 0, 1, 0, ecx, ecy - ry] },
{ command: 'z', args: [] },
];
node.name = 'path';
node.attributes.d = stringifyPathData$1({ pathData, precision });
delete node.attributes.cx;
delete node.attributes.cy;
delete node.attributes.rx;
delete node.attributes.ry;
}
},
},
};
};
var convertEllipseToCircle$1 = {};
convertEllipseToCircle$1.name = 'convertEllipseToCircle';
convertEllipseToCircle$1.description = 'converts non-eccentric <ellipse>s to <circle>s';
/**
* Converts non-eccentric <ellipse>s to <circle>s.
*
* @see https://www.w3.org/TR/SVG11/shapes.html
*
* @author Taylor Hunt
*
* @type {import('./plugins-types').Plugin<'convertEllipseToCircle'>}
*/
convertEllipseToCircle$1.fn = () => {
return {
element: {
enter: (node) => {
if (node.name === 'ellipse') {
const rx = node.attributes.rx || '0';
const ry = node.attributes.ry || '0';
if (
rx === ry ||
rx === 'auto' ||
ry === 'auto' // SVG2
) {
node.name = 'circle';
const radius = rx === 'auto' ? ry : rx;
delete node.attributes.rx;
delete node.attributes.ry;
node.attributes.r = radius;
}
}
},
},
};
};
var moveElemsAttrsToGroup$1 = {};
const { visit: visit$1 } = xast;
const { inheritableAttrs: inheritableAttrs$1, pathElems: pathElems$2 } = _collections;
moveElemsAttrsToGroup$1.name = 'moveElemsAttrsToGroup';
moveElemsAttrsToGroup$1.description = 'Move common attributes of group children to the group';
/**
* Move common attributes of group children to the group
*
* @example
* <g attr1="val1">
* <g attr2="val2">
* text
* </g>
* <circle attr2="val2" attr3="val3"/>
* </g>
* ⬇
* <g attr1="val1" attr2="val2">
* <g>
* text
* </g>
* <circle attr3="val3"/>
* </g>
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'moveElemsAttrsToGroup'>}
*/
moveElemsAttrsToGroup$1.fn = (root) => {
// find if any style element is present
let deoptimizedWithStyles = false;
visit$1(root, {
element: {
enter: (node) => {
if (node.name === 'style') {
deoptimizedWithStyles = true;
}
},
},
});
return {
element: {
exit: (node) => {
// process only groups with more than 1 children
if (node.name !== 'g' || node.children.length <= 1) {
return;
}
// deoptimize the plugin when style elements are present
// selectors may rely on id, classes or tag names
if (deoptimizedWithStyles) {
return;
}
/**
* find common attributes in group children
* @type {Map<string, string>}
*/
const commonAttributes = new Map();
let initial = true;
let everyChildIsPath = true;
for (const child of node.children) {
if (child.type === 'element') {
if (pathElems$2.includes(child.name) === false) {
everyChildIsPath = false;
}
if (initial) {
initial = false;
// collect all inheritable attributes from first child element
for (const [name, value] of Object.entries(child.attributes)) {
// consider only inheritable attributes
if (inheritableAttrs$1.includes(name)) {
commonAttributes.set(name, value);
}
}
} else {
// exclude uncommon attributes from initial list
for (const [name, value] of commonAttributes) {
if (child.attributes[name] !== value) {
commonAttributes.delete(name);
}
}
}
}
}
// preserve transform on children when group has clip-path or mask
if (
node.attributes['clip-path'] != null ||
node.attributes.mask != null
) {
commonAttributes.delete('transform');
}
// preserve transform when all children are paths
// so the transform could be applied to path data by other plugins
if (everyChildIsPath) {
commonAttributes.delete('transform');
}
// add common children attributes to group
for (const [name, value] of commonAttributes) {
if (name === 'transform') {
if (node.attributes.transform != null) {
node.attributes.transform = `${node.attributes.transform} ${value}`;
} else {
node.attributes.transform = value;
}
} else {
node.attributes[name] = value;
}
}
// delete common attributes from children
for (const child of node.children) {
if (child.type === 'element') {
for (const [name] of commonAttributes) {
delete child.attributes[name];
}
}
}
},
},
};
};
var moveGroupAttrsToElems$1 = {};
const { pathElems: pathElems$1, referencesProps: referencesProps$2 } = _collections;
moveGroupAttrsToElems$1.name = 'moveGroupAttrsToElems';
moveGroupAttrsToElems$1.description = 'moves some group attributes to the content elements';
const pathElemsWithGroupsAndText = [...pathElems$1, 'g', 'text'];
/**
* Move group attrs to the content elements.
*
* @example
* <g transform="scale(2)">
* <path transform="rotate(45)" d="M0,0 L10,20"/>
* <path transform="translate(10, 20)" d="M0,10 L20,30"/>
* </g>
* ⬇
* <g>
* <path transform="scale(2) rotate(45)" d="M0,0 L10,20"/>
* <path transform="scale(2) translate(10, 20)" d="M0,10 L20,30"/>
* </g>
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'moveGroupAttrsToElems'>}
*/
moveGroupAttrsToElems$1.fn = () => {
return {
element: {
enter: (node) => {
// move group transform attr to content's pathElems
if (
node.name === 'g' &&
node.children.length !== 0 &&
node.attributes.transform != null &&
Object.entries(node.attributes).some(
([name, value]) =>
referencesProps$2.includes(name) && value.includes('url(')
) === false &&
node.children.every(
(child) =>
child.type === 'element' &&
pathElemsWithGroupsAndText.includes(child.name) &&
child.attributes.id == null
)
) {
for (const child of node.children) {
const value = node.attributes.transform;
if (child.type === 'element') {
if (child.attributes.transform != null) {
child.attributes.transform = `${value} ${child.attributes.transform}`;
} else {
child.attributes.transform = value;
}
}
}
delete node.attributes.transform;
}
},
},
};
};
var collapseGroups$1 = {};
/**
* @typedef {import('../lib/types').XastNode} XastNode
*/
const { inheritableAttrs, elemsGroups: elemsGroups$1 } = _collections;
collapseGroups$1.name = 'collapseGroups';
collapseGroups$1.description = 'collapses useless groups';
/**
* @type {(node: XastNode, name: string) => boolean}
*/
const hasAnimatedAttr = (node, name) => {
if (node.type === 'element') {
if (
elemsGroups$1.animation.includes(node.name) &&
node.attributes.attributeName === name
) {
return true;
}
for (const child of node.children) {
if (hasAnimatedAttr(child, name)) {
return true;
}
}
}
return false;
};
/**
* Collapse useless groups.
*
* @example
* <g>
* <g attr1="val1">
* <path d="..."/>
* </g>
* </g>
* ⬇
* <g>
* <g>
* <path attr1="val1" d="..."/>
* </g>
* </g>
* ⬇
* <path attr1="val1" d="..."/>
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'collapseGroups'>}
*/
collapseGroups$1.fn = () => {
return {
element: {
exit: (node, parentNode) => {
if (parentNode.type === 'root' || parentNode.name === 'switch') {
return;
}
// non-empty groups
if (node.name !== 'g' || node.children.length === 0) {
return;
}
// move group attibutes to the single child element
if (
Object.keys(node.attributes).length !== 0 &&
node.children.length === 1
) {
const firstChild = node.children[0];
// TODO untangle this mess
if (
firstChild.type === 'element' &&
firstChild.attributes.id == null &&
node.attributes.filter == null &&
(node.attributes.class == null ||
firstChild.attributes.class == null) &&
((node.attributes['clip-path'] == null &&
node.attributes.mask == null) ||
(firstChild.name === 'g' &&
node.attributes.transform == null &&
firstChild.attributes.transform == null))
) {
for (const [name, value] of Object.entries(node.attributes)) {
// avoid copying to not conflict with animated attribute
if (hasAnimatedAttr(firstChild, name)) {
return;
}
if (firstChild.attributes[name] == null) {
firstChild.attributes[name] = value;
} else if (name === 'transform') {
firstChild.attributes[name] =
value + ' ' + firstChild.attributes[name];
} else if (firstChild.attributes[name] === 'inherit') {
firstChild.attributes[name] = value;
} else if (
inheritableAttrs.includes(name) === false &&
firstChild.attributes[name] !== value
) {
return;
}
delete node.attributes[name];
}
}
}
// collapse groups without attributes
if (Object.keys(node.attributes).length === 0) {
// animation elements "add" attributes to group
// group should be preserved
for (const child of node.children) {
if (
child.type === 'element' &&
elemsGroups$1.animation.includes(child.name)
) {
return;
}
}
// replace current node with all its children
const index = parentNode.children.indexOf(node);
parentNode.children.splice(index, 1, ...node.children);
// TODO remove legacy parentNode in v4
for (const child of node.children) {
Object.defineProperty(child, 'parentNode', {
writable: true,
value: parentNode,
});
}
}
},
},
};
};
var convertPathData$1 = {};
var _path = {};
/**
* @typedef {import('../lib/types').XastElement} XastElement
* @typedef {import('../lib/types').PathDataItem} PathDataItem
*/
const { parsePathData: parsePathData$1, stringifyPathData } = path;
/**
* @type {[number, number]}
*/
var prevCtrlPoint;
/**
* Convert path string to JS representation.
*
* @type {(path: XastElement) => Array<PathDataItem>}
*/
const path2js$3 = (path) => {
// @ts-ignore legacy
if (path.pathJS) return path.pathJS;
/**
* @type {Array<PathDataItem>}
*/
const pathData = []; // JS representation of the path data
const newPathData = parsePathData$1(path.attributes.d);
for (const { command, args } of newPathData) {
pathData.push({ command, args });
}
// First moveto is actually absolute. Subsequent coordinates were separated above.
if (pathData.length && pathData[0].command == 'm') {
pathData[0].command = 'M';
}
// @ts-ignore legacy
path.pathJS = pathData;
return pathData;
};
_path.path2js = path2js$3;
/**
* Convert relative Path data to absolute.
*
* @type {(data: Array<PathDataItem>) => Array<PathDataItem>}
*
*/
const convertRelativeToAbsolute = (data) => {
/**
* @type {Array<PathDataItem>}
*/
const newData = [];
let start = [0, 0];
let cursor = [0, 0];
for (let { command, args } of data) {
args = args.slice();
// moveto (x y)
if (command === 'm') {
args[0] += cursor[0];
args[1] += cursor[1];
command = 'M';
}
if (command === 'M') {
cursor[0] = args[0];
cursor[1] = args[1];
start[0] = cursor[0];
start[1] = cursor[1];
}
// horizontal lineto (x)
if (command === 'h') {
args[0] += cursor[0];
command = 'H';
}
if (command === 'H') {
cursor[0] = args[0];
}
// vertical lineto (y)
if (command === 'v') {
args[0] += cursor[1];
command = 'V';
}
if (command === 'V') {
cursor[1] = args[0];
}
// lineto (x y)
if (command === 'l') {
args[0] += cursor[0];
args[1] += cursor[1];
command = 'L';
}
if (command === 'L') {
cursor[0] = args[0];
cursor[1] = args[1];
}
// curveto (x1 y1 x2 y2 x y)
if (command === 'c') {
args[0] += cursor[0];
args[1] += cursor[1];
args[2] += cursor[0];
args[3] += cursor[1];
args[4] += cursor[0];
args[5] += cursor[1];
command = 'C';
}
if (command === 'C') {
cursor[0] = args[4];
cursor[1] = args[5];
}
// smooth curveto (x2 y2 x y)
if (command === 's') {
args[0] += cursor[0];
args[1] += cursor[1];
args[2] += cursor[0];
args[3] += cursor[1];
command = 'S';
}
if (command === 'S') {
cursor[0] = args[2];
cursor[1] = args[3];
}
// quadratic Bézier curveto (x1 y1 x y)
if (command === 'q') {
args[0] += cursor[0];
args[1] += cursor[1];
args[2] += cursor[0];
args[3] += cursor[1];
command = 'Q';
}
if (command === 'Q') {
cursor[0] = args[2];
cursor[1] = args[3];
}
// smooth quadratic Bézier curveto (x y)
if (command === 't') {
args[0] += cursor[0];
args[1] += cursor[1];
command = 'T';
}
if (command === 'T') {
cursor[0] = args[0];
cursor[1] = args[1];
}
// elliptical arc (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
if (command === 'a') {
args[5] += cursor[0];
args[6] += cursor[1];
command = 'A';
}
if (command === 'A') {
cursor[0] = args[5];
cursor[1] = args[6];
}
// closepath
if (command === 'z' || command === 'Z') {
cursor[0] = start[0];
cursor[1] = start[1];
command = 'z';
}
newData.push({ command, args });
}
return newData;
};
/**
* @typedef {{ floatPrecision?: number, noSpaceAfterFlags?: boolean }} Js2PathParams
*/
/**
* Convert path array to string.
*
* @type {(path: XastElement, data: Array<PathDataItem>, params: Js2PathParams) => void}
*/
_path.js2path = function (path, data, params) {
// @ts-ignore legacy
path.pathJS = data;
const pathData = [];
for (const item of data) {
// remove moveto commands which are followed by moveto commands
if (
pathData.length !== 0 &&
(item.command === 'M' || item.command === 'm')
) {
const last = pathData[pathData.length - 1];
if (last.command === 'M' || last.command === 'm') {
pathData.pop();
}
}
pathData.push({
command: item.command,
args: item.args,
});
}
path.attributes.d = stringifyPathData({
pathData,
precision: params.floatPrecision,
disableSpaceAfterFlags: params.noSpaceAfterFlags,
});
};
/**
* @type {(dest: Array<number>, source: Array<number>) => Array<number>}
*/
function set(dest, source) {
dest[0] = source[source.length - 2];
dest[1] = source[source.length - 1];
return dest;
}
/**
* Checks if two paths have an intersection by checking convex hulls
* collision using Gilbert-Johnson-Keerthi distance algorithm
* https://web.archive.org/web/20180822200027/http://entropyinteractive.com/2011/04/gjk-algorithm/
*
* @type {(path1: Array<PathDataItem>, path2: Array<PathDataItem>) => boolean}
*/
_path.intersects = function (path1, path2) {
// Collect points of every subpath.
const points1 = gatherPoints(convertRelativeToAbsolute(path1));
const points2 = gatherPoints(convertRelativeToAbsolute(path2));
// Axis-aligned bounding box check.
if (
points1.maxX <= points2.minX ||
points2.maxX <= points1.minX ||
points1.maxY <= points2.minY ||
points2.maxY <= points1.minY ||
points1.list.every((set1) => {
return points2.list.every((set2) => {
return (
set1.list[set1.maxX][0] <= set2.list[set2.minX][0] ||
set2.list[set2.maxX][0] <= set1.list[set1.minX][0] ||
set1.list[set1.maxY][1] <= set2.list[set2.minY][1] ||
set2.list[set2.maxY][1] <= set1.list[set1.minY][1]
);
});
})
)
return false;
// Get a convex hull from points of each subpath. Has the most complexity O(n·log n).
const hullNest1 = points1.list.map(convexHull);
const hullNest2 = points2.list.map(convexHull);
// Check intersection of every subpath of the first path with every subpath of the second.
return hullNest1.some(function (hull1) {
if (hull1.list.length < 3) return false;
return hullNest2.some(function (hull2) {
if (hull2.list.length < 3) return false;
var simplex = [getSupport(hull1, hull2, [1, 0])], // create the initial simplex
direction = minus(simplex[0]); // set the direction to point towards the origin
var iterations = 1e4; // infinite loop protection, 10 000 iterations is more than enough
// eslint-disable-next-line no-constant-condition
while (true) {
// eslint-disable-next-line no-constant-condition
if (iterations-- == 0) {
console.error(
'Error: infinite loop while processing mergePaths plugin.'
);
return true; // true is the safe value that means “do nothing with paths”
}
// add a new point
simplex.push(getSupport(hull1, hull2, direction));
// see if the new point was on the correct side of the origin
if (dot(direction, simplex[simplex.length - 1]) <= 0) return false;
// process the simplex
if (processSimplex(simplex, direction)) return true;
}
});
});
/**
* @type {(a: Point, b: Point, direction: Array<number>) => Array<number>}
*/
function getSupport(a, b, direction) {
return sub(supportPoint(a, direction), supportPoint(b, minus(direction)));
}
// Computes farthest polygon point in particular direction.
// Thanks to knowledge of min/max x and y coordinates we can choose a quadrant to search in.
// Since we're working on convex hull, the dot product is increasing until we find the farthest point.
/**
* @type {(polygon: Point, direction: Array<number>) => Array<number>}
*/
function supportPoint(polygon, direction) {
var index =
direction[1] >= 0
? direction[0] < 0
? polygon.maxY
: polygon.maxX
: direction[0] < 0
? polygon.minX
: polygon.minY,
max = -Infinity,
value;
while ((value = dot(polygon.list[index], direction)) > max) {
max = value;
index = ++index % polygon.list.length;
}
return polygon.list[(index || polygon.list.length) - 1];
}
};
/**
* @type {(simplex: Array<Array<number>>, direction: Array<number>) => boolean}
*/
function processSimplex(simplex, direction) {
// we only need to handle to 1-simplex and 2-simplex
if (simplex.length == 2) {
// 1-simplex
let a = simplex[1],
b = simplex[0],
AO = minus(simplex[1]),
AB = sub(b, a);
// AO is in the same direction as AB
if (dot(AO, AB) > 0) {
// get the vector perpendicular to AB facing O
set(direction, orth(AB, a));
} else {
set(direction, AO);
// only A remains in the simplex
simplex.shift();
}
} else {
// 2-simplex
let a = simplex[2], // [a, b, c] = simplex
b = simplex[1],
c = simplex[0],
AB = sub(b, a),
AC = sub(c, a),
AO = minus(a),
ACB = orth(AB, AC), // the vector perpendicular to AB facing away from C
ABC = orth(AC, AB); // the vector perpendicular to AC facing away from B
if (dot(ACB, AO) > 0) {
if (dot(AB, AO) > 0) {
// region 4
set(direction, ACB);
simplex.shift(); // simplex = [b, a]
} else {
// region 5
set(direction, AO);
simplex.splice(0, 2); // simplex = [a]
}
} else if (dot(ABC, AO) > 0) {
if (dot(AC, AO) > 0) {
// region 6
set(direction, ABC);
simplex.splice(1, 1); // simplex = [c, a]
} else {
// region 5 (again)
set(direction, AO);
simplex.splice(0, 2); // simplex = [a]
}
} // region 7
else return true;
}
return false;
}
/**
* @type {(v: Array<number>) => Array<number>}
*/
function minus(v) {
return [-v[0], -v[1]];
}
/**
* @type {(v1: Array<number>, v2: Array<number>) => Array<number>}
*/
function sub(v1, v2) {
return [v1[0] - v2[0], v1[1] - v2[1]];
}
/**
* @type {(v1: Array<number>, v2: Array<number>) => number}
*/
function dot(v1, v2) {
return v1[0] * v2[0] + v1[1] * v2[1];
}
/**
* @type {(v1: Array<number>, v2: Array<number>) => Array<number>}
*/
function orth(v, from) {
var o = [-v[1], v[0]];
return dot(o, minus(from)) < 0 ? minus(o) : o;
}
/**
* @typedef {{
* list: Array<Array<number>>,
* minX: number,
* minY: number,
* maxX: number,
* maxY: number
* }} Point
*/
/**
* @typedef {{
* list: Array<Point>,
* minX: number,
* minY: number,
* maxX: number,
* maxY: number
* }} Points
*/
/**
* @type {(pathData: Array<PathDataItem>) => Points}
*/
function gatherPoints(pathData) {
/**
* @type {Points}
*/
const points = { list: [], minX: 0, minY: 0, maxX: 0, maxY: 0 };
// Writes data about the extreme points on each axle
/**
* @type {(path: Point, point: Array<number>) => void}
*/
const addPoint = (path, point) => {
if (!path.list.length || point[1] > path.list[path.maxY][1]) {
path.maxY = path.list.length;
points.maxY = points.list.length
? Math.max(point[1], points.maxY)
: point[1];
}
if (!path.list.length || point[0] > path.list[path.maxX][0]) {
path.maxX = path.list.length;
points.maxX = points.list.length
? Math.max(point[0], points.maxX)
: point[0];
}
if (!path.list.length || point[1] < path.list[path.minY][1]) {
path.minY = path.list.length;
points.minY = points.list.length
? Math.min(point[1], points.minY)
: point[1];
}
if (!path.list.length || point[0] < path.list[path.minX][0]) {
path.minX = path.list.length;
points.minX = points.list.length
? Math.min(point[0], points.minX)
: point[0];
}
path.list.push(point);
};
for (let i = 0; i < pathData.length; i += 1) {
const pathDataItem = pathData[i];
let subPath =
points.list.length === 0
? { list: [], minX: 0, minY: 0, maxX: 0, maxY: 0 }
: points.list[points.list.length - 1];
let prev = i === 0 ? null : pathData[i - 1];
let basePoint =
subPath.list.length === 0 ? null : subPath.list[subPath.list.length - 1];
let data = pathDataItem.args;
let ctrlPoint = basePoint;
/**
* @type {(n: number, i: number) => number}
* TODO fix null hack
*/
const toAbsolute = (n, i) => n + (basePoint == null ? 0 : basePoint[i % 2]);
switch (pathDataItem.command) {
case 'M':
subPath = { list: [], minX: 0, minY: 0, maxX: 0, maxY: 0 };
points.list.push(subPath);
break;
case 'H':
if (basePoint != null) {
addPoint(subPath, [data[0], basePoint[1]]);
}
break;
case 'V':
if (basePoint != null) {
addPoint(subPath, [basePoint[0], data[0]]);
}
break;
case 'Q':
addPoint(subPath, data.slice(0, 2));
prevCtrlPoint = [data[2] - data[0], data[3] - data[1]]; // Save control point for shorthand
break;
case 'T':
if (
basePoint != null &&
prev != null &&
(prev.command == 'Q' || prev.command == 'T')
) {
ctrlPoint = [
basePoint[0] + prevCtrlPoint[0],
basePoint[1] + prevCtrlPoint[1],
];
addPoint(subPath, ctrlPoint);
prevCtrlPoint = [data[0] - ctrlPoint[0], data[1] - ctrlPoint[1]];
}
break;
case 'C':
if (basePoint != null) {
// Approximate quibic Bezier curve with middle points between control points
addPoint(subPath, [
0.5 * (basePoint[0] + data[0]),
0.5 * (basePoint[1] + data[1]),
]);
}
addPoint(subPath, [
0.5 * (data[0] + data[2]),
0.5 * (data[1] + data[3]),
]);
addPoint(subPath, [
0.5 * (data[2] + data[4]),
0.5 * (data[3] + data[5]),
]);
prevCtrlPoint = [data[4] - data[2], data[5] - data[3]]; // Save control point for shorthand
break;
case 'S':
if (
basePoint != null &&
prev != null &&
(prev.command == 'C' || prev.command == 'S')
) {
addPoint(subPath, [
basePoint[0] + 0.5 * prevCtrlPoint[0],
basePoint[1] + 0.5 * prevCtrlPoint[1],
]);
ctrlPoint = [
basePoint[0] + prevCtrlPoint[0],
basePoint[1] + prevCtrlPoint[1],
];
}
if (ctrlPoint != null) {
addPoint(subPath, [
0.5 * (ctrlPoint[0] + data[0]),
0.5 * (ctrlPoint[1] + data[1]),
]);
}
addPoint(subPath, [
0.5 * (data[0] + data[2]),
0.5 * (data[1] + data[3]),
]);
prevCtrlPoint = [data[2] - data[0], data[3] - data[1]];
break;
case 'A':
if (basePoint != null) {
// Convert the arc to bezier curves and use the same approximation
// @ts-ignore no idea what's going on here
var curves = a2c.apply(0, basePoint.concat(data));
for (
var cData;
(cData = curves.splice(0, 6).map(toAbsolute)).length;
) {
if (basePoint != null) {
addPoint(subPath, [
0.5 * (basePoint[0] + cData[0]),
0.5 * (basePoint[1] + cData[1]),
]);
}
addPoint(subPath, [
0.5 * (cData[0] + cData[2]),
0.5 * (cData[1] + cData[3]),
]);
addPoint(subPath, [
0.5 * (cData[2] + cData[4]),
0.5 * (cData[3] + cData[5]),
]);
if (curves.length) addPoint(subPath, (basePoint = cData.slice(-2)));
}
}
break;
}
// Save final command coordinates
if (data.length >= 2) addPoint(subPath, data.slice(-2));
}
return points;
}
/**
* Forms a convex hull from set of points of every subpath using monotone chain convex hull algorithm.
* https://en.wikibooks.org/wiki/Algorithm_Implementation/Geometry/Convex_hull/Monotone_chain
*
* @type {(points: Point) => Point}
*/
function convexHull(points) {
points.list.sort(function (a, b) {
return a[0] == b[0] ? a[1] - b[1] : a[0] - b[0];
});
var lower = [],
minY = 0,
bottom = 0;
for (let i = 0; i < points.list.length; i++) {
while (
lower.length >= 2 &&
cross(lower[lower.length - 2], lower[lower.length - 1], points.list[i]) <=
0
) {
lower.pop();
}
if (points.list[i][1] < points.list[minY][1]) {
minY = i;
bottom = lower.length;
}
lower.push(points.list[i]);
}
var upper = [],
maxY = points.list.length - 1,
top = 0;
for (let i = points.list.length; i--; ) {
while (
upper.length >= 2 &&
cross(upper[upper.length - 2], upper[upper.length - 1], points.list[i]) <=
0
) {
upper.pop();
}
if (points.list[i][1] > points.list[maxY][1]) {
maxY = i;
top = upper.length;
}
upper.push(points.list[i]);
}
// last points are equal to starting points of the other part
upper.pop();
lower.pop();
const hullList = lower.concat(upper);
/**
* @type {Point}
*/
const hull = {
list: hullList,
minX: 0, // by sorting
maxX: lower.length,
minY: bottom,
maxY: (lower.length + top) % hullList.length,
};
return hull;
}
/**
* @type {(o: Array<number>, a: Array<number>, b: Array<number>) => number}
*/
function cross(o, a, b) {
return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);
}
/**
* Based on code from Snap.svg (Apache 2 license). http://snapsvg.io/
* Thanks to Dmitry Baranovskiy for his great work!
*
* @type {(
* x1: number,
* y1: number,
* rx: number,
* ry: number,
* angle: number,
* large_arc_flag: number,
* sweep_flag: number,
* x2: number,
* y2: number,
* recursive: Array<number>
* ) => Array<number>}
*/
const a2c = (
x1,
y1,
rx,
ry,
angle,
large_arc_flag,
sweep_flag,
x2,
y2,
recursive
) => {
// for more information of where this Math came from visit:
// https://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
const _120 = (Math.PI * 120) / 180;
const rad = (Math.PI / 180) * (+angle || 0);
/**
* @type {Array<number>}
*/
let res = [];
/**
* @type {(x: number, y: number, rad: number) => number}
*/
const rotateX = (x, y, rad) => {
return x * Math.cos(rad) - y * Math.sin(rad);
};
/**
* @type {(x: number, y: number, rad: number) => number}
*/
const rotateY = (x, y, rad) => {
return x * Math.sin(rad) + y * Math.cos(rad);
};
if (!recursive) {
x1 = rotateX(x1, y1, -rad);
y1 = rotateY(x1, y1, -rad);
x2 = rotateX(x2, y2, -rad);
y2 = rotateY(x2, y2, -rad);
var x = (x1 - x2) / 2,
y = (y1 - y2) / 2;
var h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
if (h > 1) {
h = Math.sqrt(h);
rx = h * rx;
ry = h * ry;
}
var rx2 = rx * rx;
var ry2 = ry * ry;
var k =
(large_arc_flag == sweep_flag ? -1 : 1) *
Math.sqrt(
Math.abs(
(rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x)
)
);
var cx = (k * rx * y) / ry + (x1 + x2) / 2;
var cy = (k * -ry * x) / rx + (y1 + y2) / 2;
var f1 = Math.asin(Number(((y1 - cy) / ry).toFixed(9)));
var f2 = Math.asin(Number(((y2 - cy) / ry).toFixed(9)));
f1 = x1 < cx ? Math.PI - f1 : f1;
f2 = x2 < cx ? Math.PI - f2 : f2;
f1 < 0 && (f1 = Math.PI * 2 + f1);
f2 < 0 && (f2 = Math.PI * 2 + f2);
if (sweep_flag && f1 > f2) {
f1 = f1 - Math.PI * 2;
}
if (!sweep_flag && f2 > f1) {
f2 = f2 - Math.PI * 2;
}
} else {
f1 = recursive[0];
f2 = recursive[1];
cx = recursive[2];
cy = recursive[3];
}
var df = f2 - f1;
if (Math.abs(df) > _120) {
var f2old = f2,
x2old = x2,
y2old = y2;
f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
x2 = cx + rx * Math.cos(f2);
y2 = cy + ry * Math.sin(f2);
res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [
f2,
f2old,
cx,
cy,
]);
}
df = f2 - f1;
var c1 = Math.cos(f1),
s1 = Math.sin(f1),
c2 = Math.cos(f2),
s2 = Math.sin(f2),
t = Math.tan(df / 4),
hx = (4 / 3) * rx * t,
hy = (4 / 3) * ry * t,
m = [
-hx * s1,
hy * c1,
x2 + hx * s2 - x1,
y2 - hy * c2 - y1,
x2 - x1,
y2 - y1,
];
if (recursive) {
return m.concat(res);
} else {
res = m.concat(res);
var newres = [];
for (var i = 0, n = res.length; i < n; i++) {
newres[i] =
i % 2
? rotateY(res[i - 1], res[i], rad)
: rotateX(res[i], res[i + 1], rad);
}
return newres;
}
};
var applyTransforms$2 = {};
var _transforms = {};
const regTransformTypes = /matrix|translate|scale|rotate|skewX|skewY/;
const regTransformSplit =
/\s*(matrix|translate|scale|rotate|skewX|skewY)\s*\(\s*(.+?)\s*\)[\s,]*/;
const regNumericValues$2 = /[-+]?(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?/g;
/**
* @typedef {{ name: string, data: Array<number> }} TransformItem
*/
/**
* Convert transform string to JS representation.
*
* @type {(transformString: string) => Array<TransformItem>}
*/
_transforms.transform2js = (transformString) => {
// JS representation of the transform data
/**
* @type {Array<TransformItem>}
*/
const transforms = [];
// current transform context
/**
* @type {null | TransformItem}
*/
let current = null;
// split value into ['', 'translate', '10 50', '', 'scale', '2', '', 'rotate', '-45', '']
for (const item of transformString.split(regTransformSplit)) {
var num;
if (item) {
// if item is a translate function
if (regTransformTypes.test(item)) {
// then collect it and change current context
current = { name: item, data: [] };
transforms.push(current);
// else if item is data
} else {
// then split it into [10, 50] and collect as context.data
// eslint-disable-next-line no-cond-assign
while ((num = regNumericValues$2.exec(item))) {
num = Number(num);
if (current != null) {
current.data.push(num);
}
}
}
}
}
// return empty array if broken transform (no data)
return current == null || current.data.length == 0 ? [] : transforms;
};
/**
* Multiply transforms into one.
*
* @type {(transforms: Array<TransformItem>) => TransformItem}
*/
_transforms.transformsMultiply = (transforms) => {
// convert transforms objects to the matrices
const matrixData = transforms.map((transform) => {
if (transform.name === 'matrix') {
return transform.data;
}
return transformToMatrix(transform);
});
// multiply all matrices into one
const matrixTransform = {
name: 'matrix',
data:
matrixData.length > 0 ? matrixData.reduce(multiplyTransformMatrices) : [],
};
return matrixTransform;
};
/**
* math utilities in radians.
*/
const mth = {
/**
* @type {(deg: number) => number}
*/
rad: (deg) => {
return (deg * Math.PI) / 180;
},
/**
* @type {(rad: number) => number}
*/
deg: (rad) => {
return (rad * 180) / Math.PI;
},
/**
* @type {(deg: number) => number}
*/
cos: (deg) => {
return Math.cos(mth.rad(deg));
},
/**
* @type {(val: number, floatPrecision: number) => number}
*/
acos: (val, floatPrecision) => {
return Number(mth.deg(Math.acos(val)).toFixed(floatPrecision));
},
/**
* @type {(deg: number) => number}
*/
sin: (deg) => {
return Math.sin(mth.rad(deg));
},
/**
* @type {(val: number, floatPrecision: number) => number}
*/
asin: (val, floatPrecision) => {
return Number(mth.deg(Math.asin(val)).toFixed(floatPrecision));
},
/**
* @type {(deg: number) => number}
*/
tan: (deg) => {
return Math.tan(mth.rad(deg));
},
/**
* @type {(val: number, floatPrecision: number) => number}
*/
atan: (val, floatPrecision) => {
return Number(mth.deg(Math.atan(val)).toFixed(floatPrecision));
},
};
/**
* @typedef {{
* convertToShorts: boolean,
* floatPrecision: number,
* transformPrecision: number,
* matrixToTransform: boolean,
* shortTranslate: boolean,
* shortScale: boolean,
* shortRotate: boolean,
* removeUseless: boolean,
* collapseIntoOne: boolean,
* leadingZero: boolean,
* negativeExtraSpace: boolean,
* }} TransformParams
*/
/**
* Decompose matrix into simple transforms. See
* https://frederic-wang.fr/decomposition-of-2d-transform-matrices.html
*
* @type {(transform: TransformItem, params: TransformParams) => Array<TransformItem>}
*/
_transforms.matrixToTransform = (transform, params) => {
let floatPrecision = params.floatPrecision;
let data = transform.data;
let transforms = [];
let sx = Number(
Math.hypot(data[0], data[1]).toFixed(params.transformPrecision)
);
let sy = Number(
((data[0] * data[3] - data[1] * data[2]) / sx).toFixed(
params.transformPrecision
)
);
let colsSum = data[0] * data[2] + data[1] * data[3];
let rowsSum = data[0] * data[1] + data[2] * data[3];
let scaleBefore = rowsSum != 0 || sx == sy;
// [..., ..., ..., ..., tx, ty] → translate(tx, ty)
if (data[4] || data[5]) {
transforms.push({
name: 'translate',
data: data.slice(4, data[5] ? 6 : 5),
});
}
// [sx, 0, tan(a)·sy, sy, 0, 0] → skewX(a)·scale(sx, sy)
if (!data[1] && data[2]) {
transforms.push({
name: 'skewX',
data: [mth.atan(data[2] / sy, floatPrecision)],
});
// [sx, sx·tan(a), 0, sy, 0, 0] → skewY(a)·scale(sx, sy)
} else if (data[1] && !data[2]) {
transforms.push({
name: 'skewY',
data: [mth.atan(data[1] / data[0], floatPrecision)],
});
sx = data[0];
sy = data[3];
// [sx·cos(a), sx·sin(a), sy·-sin(a), sy·cos(a), x, y] → rotate(a[, cx, cy])·(scale or skewX) or
// [sx·cos(a), sy·sin(a), sx·-sin(a), sy·cos(a), x, y] → scale(sx, sy)·rotate(a[, cx, cy]) (if !scaleBefore)
} else if (!colsSum || (sx == 1 && sy == 1) || !scaleBefore) {
if (!scaleBefore) {
sx = (data[0] < 0 ? -1 : 1) * Math.hypot(data[0], data[2]);
sy = (data[3] < 0 ? -1 : 1) * Math.hypot(data[1], data[3]);
transforms.push({ name: 'scale', data: [sx, sy] });
}
var angle = Math.min(Math.max(-1, data[0] / sx), 1),
rotate = [
mth.acos(angle, floatPrecision) *
((scaleBefore ? 1 : sy) * data[1] < 0 ? -1 : 1),
];
if (rotate[0]) transforms.push({ name: 'rotate', data: rotate });
if (rowsSum && colsSum)
transforms.push({
name: 'skewX',
data: [mth.atan(colsSum / (sx * sx), floatPrecision)],
});
// rotate(a, cx, cy) can consume translate() within optional arguments cx, cy (rotation point)
if (rotate[0] && (data[4] || data[5])) {
transforms.shift();
var cos = data[0] / sx,
sin = data[1] / (scaleBefore ? sx : sy),
x = data[4] * (scaleBefore ? 1 : sy),
y = data[5] * (scaleBefore ? 1 : sx),
denom =
(Math.pow(1 - cos, 2) + Math.pow(sin, 2)) *
(scaleBefore ? 1 : sx * sy);
rotate.push(((1 - cos) * x - sin * y) / denom);
rotate.push(((1 - cos) * y + sin * x) / denom);
}
// Too many transformations, return original matrix if it isn't just a scale/translate
} else if (data[1] || data[2]) {
return [transform];
}
if ((scaleBefore && (sx != 1 || sy != 1)) || !transforms.length)
transforms.push({
name: 'scale',
data: sx == sy ? [sx] : [sx, sy],
});
return transforms;
};
/**
* Convert transform to the matrix data.
*
* @type {(transform: TransformItem) => Array<number> }
*/
const transformToMatrix = (transform) => {
if (transform.name === 'matrix') {
return transform.data;
}
switch (transform.name) {
case 'translate':
// [1, 0, 0, 1, tx, ty]
return [1, 0, 0, 1, transform.data[0], transform.data[1] || 0];
case 'scale':
// [sx, 0, 0, sy, 0, 0]
return [
transform.data[0],
0,
0,
transform.data[1] || transform.data[0],
0,
0,
];
case 'rotate':
// [cos(a), sin(a), -sin(a), cos(a), x, y]
var cos = mth.cos(transform.data[0]),
sin = mth.sin(transform.data[0]),
cx = transform.data[1] || 0,
cy = transform.data[2] || 0;
return [
cos,
sin,
-sin,
cos,
(1 - cos) * cx + sin * cy,
(1 - cos) * cy - sin * cx,
];
case 'skewX':
// [1, 0, tan(a), 1, 0, 0]
return [1, 0, mth.tan(transform.data[0]), 1, 0, 0];
case 'skewY':
// [1, tan(a), 0, 1, 0, 0]
return [1, mth.tan(transform.data[0]), 0, 1, 0, 0];
default:
throw Error(`Unknown transform ${transform.name}`);
}
};
/**
* Applies transformation to an arc. To do so, we represent ellipse as a matrix, multiply it
* by the transformation matrix and use a singular value decomposition to represent in a form
* rotate(θ)·scale(a b)·rotate(φ). This gives us new ellipse params a, b and θ.
* SVD is being done with the formulae provided by Wolffram|Alpha (svd {{m0, m2}, {m1, m3}})
*
* @type {(
* cursor: [x: number, y: number],
* arc: Array<number>,
* transform: Array<number>
* ) => Array<number>}
*/
_transforms.transformArc = (cursor, arc, transform) => {
const x = arc[5] - cursor[0];
const y = arc[6] - cursor[1];
let a = arc[0];
let b = arc[1];
const rot = (arc[2] * Math.PI) / 180;
const cos = Math.cos(rot);
const sin = Math.sin(rot);
// skip if radius is 0
if (a > 0 && b > 0) {
let h =
Math.pow(x * cos + y * sin, 2) / (4 * a * a) +
Math.pow(y * cos - x * sin, 2) / (4 * b * b);
if (h > 1) {
h = Math.sqrt(h);
a *= h;
b *= h;
}
}
const ellipse = [a * cos, a * sin, -b * sin, b * cos, 0, 0];
const m = multiplyTransformMatrices(transform, ellipse);
// Decompose the new ellipse matrix
const lastCol = m[2] * m[2] + m[3] * m[3];
const squareSum = m[0] * m[0] + m[1] * m[1] + lastCol;
const root =
Math.hypot(m[0] - m[3], m[1] + m[2]) * Math.hypot(m[0] + m[3], m[1] - m[2]);
if (!root) {
// circle
arc[0] = arc[1] = Math.sqrt(squareSum / 2);
arc[2] = 0;
} else {
const majorAxisSqr = (squareSum + root) / 2;
const minorAxisSqr = (squareSum - root) / 2;
const major = Math.abs(majorAxisSqr - lastCol) > 1e-6;
const sub = (major ? majorAxisSqr : minorAxisSqr) - lastCol;
const rowsSum = m[0] * m[2] + m[1] * m[3];
const term1 = m[0] * sub + m[2] * rowsSum;
const term2 = m[1] * sub + m[3] * rowsSum;
arc[0] = Math.sqrt(majorAxisSqr);
arc[1] = Math.sqrt(minorAxisSqr);
arc[2] =
(((major ? term2 < 0 : term1 > 0) ? -1 : 1) *
Math.acos((major ? term1 : term2) / Math.hypot(term1, term2)) *
180) /
Math.PI;
}
if (transform[0] < 0 !== transform[3] < 0) {
// Flip the sweep flag if coordinates are being flipped horizontally XOR vertically
arc[4] = 1 - arc[4];
}
return arc;
};
/**
* Multiply transformation matrices.
*
* @type {(a: Array<number>, b: Array<number>) => Array<number>}
*/
const multiplyTransformMatrices = (a, b) => {
return [
a[0] * b[0] + a[2] * b[1],
a[1] * b[0] + a[3] * b[1],
a[0] * b[2] + a[2] * b[3],
a[1] * b[2] + a[3] * b[3],
a[0] * b[4] + a[2] * b[5] + a[4],
a[1] * b[4] + a[3] * b[5] + a[5],
];
};
/**
* @typedef {import('../lib/types').PathDataItem} PathDataItem
* @typedef {import('../lib/types').XastElement} XastElement
*/
const { collectStylesheet: collectStylesheet$2, computeStyle: computeStyle$2 } = style;
const {
transformsMultiply: transformsMultiply$1,
transform2js: transform2js$1,
transformArc,
} = _transforms;
const { path2js: path2js$2 } = _path;
const { removeLeadingZero: removeLeadingZero$1 } = tools;
const { referencesProps: referencesProps$1, attrsGroupsDefaults } = _collections;
/**
* @typedef {Array<PathDataItem>} PathData
* @typedef {Array<number>} Matrix
*/
const regNumericValues$1 = /[-+]?(\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?/g;
/**
* Apply transformation(s) to the Path data.
*
* @type {import('../lib/types').Plugin<{
* transformPrecision: number,
* applyTransformsStroked: boolean,
* }>}
*/
const applyTransforms$1 = (root, params) => {
const stylesheet = collectStylesheet$2(root);
return {
element: {
enter: (node) => {
const computedStyle = computeStyle$2(stylesheet, node);
// used only for paths for now
if (node.attributes.d == null) {
return;
}
// stroke and stroke-width can be redefined with <use>
if (node.attributes.id != null) {
return;
}
// if there are no 'stroke' attr and references to other objects such as
// gradiends or clip-path which are also subjects to transform.
if (
node.attributes.transform == null ||
node.attributes.transform === '' ||
// styles are not considered when applying transform
// can be fixed properly with new style engine
node.attributes.style != null ||
Object.entries(node.attributes).some(
([name, value]) =>
referencesProps$1.includes(name) && value.includes('url(')
)
) {
return;
}
const matrix = transformsMultiply$1(
transform2js$1(node.attributes.transform)
);
const stroke =
computedStyle.stroke != null && computedStyle.stroke.type === 'static'
? computedStyle.stroke.value
: null;
const strokeWidth =
computedStyle['stroke-width'] != null &&
computedStyle['stroke-width'].type === 'static'
? computedStyle['stroke-width'].value
: null;
const transformPrecision = params.transformPrecision;
if (
(computedStyle.stroke != null &&
computedStyle.stroke.type === 'dynamic') ||
(computedStyle.strokeWidth != null &&
computedStyle['stroke-width'].type === 'dynamic')
) {
return;
}
const scale = Number(
Math.sqrt(
matrix.data[0] * matrix.data[0] + matrix.data[1] * matrix.data[1]
).toFixed(transformPrecision)
);
if (stroke && stroke != 'none') {
if (params.applyTransformsStroked === false) {
return;
}
// stroke cannot be transformed with different vertical and horizontal scale or skew
if (
(matrix.data[0] !== matrix.data[3] ||
matrix.data[1] !== -matrix.data[2]) &&
(matrix.data[0] !== -matrix.data[3] ||
matrix.data[1] !== matrix.data[2])
) {
return;
}
// apply transform to stroke-width, stroke-dashoffset and stroke-dasharray
if (scale !== 1) {
if (node.attributes['vector-effect'] !== 'non-scaling-stroke') {
node.attributes['stroke-width'] = (
strokeWidth || attrsGroupsDefaults.presentation['stroke-width']
)
.trim()
.replace(regNumericValues$1, (num) =>
removeLeadingZero$1(Number(num) * scale)
);
if (node.attributes['stroke-dashoffset'] != null) {
node.attributes['stroke-dashoffset'] = node.attributes[
'stroke-dashoffset'
]
.trim()
.replace(regNumericValues$1, (num) =>
removeLeadingZero$1(Number(num) * scale)
);
}
if (node.attributes['stroke-dasharray'] != null) {
node.attributes['stroke-dasharray'] = node.attributes[
'stroke-dasharray'
]
.trim()
.replace(regNumericValues$1, (num) =>
removeLeadingZero$1(Number(num) * scale)
);
}
}
}
}
const pathData = path2js$2(node);
applyMatrixToPathData(pathData, matrix.data);
// remove transform attr
delete node.attributes.transform;
},
},
};
};
applyTransforms$2.applyTransforms = applyTransforms$1;
/**
* @type {(matrix: Matrix, x: number, y: number) => [number, number]}
*/
const transformAbsolutePoint = (matrix, x, y) => {
const newX = matrix[0] * x + matrix[2] * y + matrix[4];
const newY = matrix[1] * x + matrix[3] * y + matrix[5];
return [newX, newY];
};
/**
* @type {(matrix: Matrix, x: number, y: number) => [number, number]}
*/
const transformRelativePoint = (matrix, x, y) => {
const newX = matrix[0] * x + matrix[2] * y;
const newY = matrix[1] * x + matrix[3] * y;
return [newX, newY];
};
/**
* @type {(pathData: PathData, matrix: Matrix) => void}
*/
const applyMatrixToPathData = (pathData, matrix) => {
/**
* @type {[number, number]}
*/
const start = [0, 0];
/**
* @type {[number, number]}
*/
const cursor = [0, 0];
for (const pathItem of pathData) {
let { command, args } = pathItem;
// moveto (x y)
if (command === 'M') {
cursor[0] = args[0];
cursor[1] = args[1];
start[0] = cursor[0];
start[1] = cursor[1];
const [x, y] = transformAbsolutePoint(matrix, args[0], args[1]);
args[0] = x;
args[1] = y;
}
if (command === 'm') {
cursor[0] += args[0];
cursor[1] += args[1];
start[0] = cursor[0];
start[1] = cursor[1];
const [x, y] = transformRelativePoint(matrix, args[0], args[1]);
args[0] = x;
args[1] = y;
}
// horizontal lineto (x)
// convert to lineto to handle two-dimentional transforms
if (command === 'H') {
command = 'L';
args = [args[0], cursor[1]];
}
if (command === 'h') {
command = 'l';
args = [args[0], 0];
}
// vertical lineto (y)
// convert to lineto to handle two-dimentional transforms
if (command === 'V') {
command = 'L';
args = [cursor[0], args[0]];
}
if (command === 'v') {
command = 'l';
args = [0, args[0]];
}
// lineto (x y)
if (command === 'L') {
cursor[0] = args[0];
cursor[1] = args[1];
const [x, y] = transformAbsolutePoint(matrix, args[0], args[1]);
args[0] = x;
args[1] = y;
}
if (command === 'l') {
cursor[0] += args[0];
cursor[1] += args[1];
const [x, y] = transformRelativePoint(matrix, args[0], args[1]);
args[0] = x;
args[1] = y;
}
// curveto (x1 y1 x2 y2 x y)
if (command === 'C') {
cursor[0] = args[4];
cursor[1] = args[5];
const [x1, y1] = transformAbsolutePoint(matrix, args[0], args[1]);
const [x2, y2] = transformAbsolutePoint(matrix, args[2], args[3]);
const [x, y] = transformAbsolutePoint(matrix, args[4], args[5]);
args[0] = x1;
args[1] = y1;
args[2] = x2;
args[3] = y2;
args[4] = x;
args[5] = y;
}
if (command === 'c') {
cursor[0] += args[4];
cursor[1] += args[5];
const [x1, y1] = transformRelativePoint(matrix, args[0], args[1]);
const [x2, y2] = transformRelativePoint(matrix, args[2], args[3]);
const [x, y] = transformRelativePoint(matrix, args[4], args[5]);
args[0] = x1;
args[1] = y1;
args[2] = x2;
args[3] = y2;
args[4] = x;
args[5] = y;
}
// smooth curveto (x2 y2 x y)
if (command === 'S') {
cursor[0] = args[2];
cursor[1] = args[3];
const [x2, y2] = transformAbsolutePoint(matrix, args[0], args[1]);
const [x, y] = transformAbsolutePoint(matrix, args[2], args[3]);
args[0] = x2;
args[1] = y2;
args[2] = x;
args[3] = y;
}
if (command === 's') {
cursor[0] += args[2];
cursor[1] += args[3];
const [x2, y2] = transformRelativePoint(matrix, args[0], args[1]);
const [x, y] = transformRelativePoint(matrix, args[2], args[3]);
args[0] = x2;
args[1] = y2;
args[2] = x;
args[3] = y;
}
// quadratic Bézier curveto (x1 y1 x y)
if (command === 'Q') {
cursor[0] = args[2];
cursor[1] = args[3];
const [x1, y1] = transformAbsolutePoint(matrix, args[0], args[1]);
const [x, y] = transformAbsolutePoint(matrix, args[2], args[3]);
args[0] = x1;
args[1] = y1;
args[2] = x;
args[3] = y;
}
if (command === 'q') {
cursor[0] += args[2];
cursor[1] += args[3];
const [x1, y1] = transformRelativePoint(matrix, args[0], args[1]);
const [x, y] = transformRelativePoint(matrix, args[2], args[3]);
args[0] = x1;
args[1] = y1;
args[2] = x;
args[3] = y;
}
// smooth quadratic Bézier curveto (x y)
if (command === 'T') {
cursor[0] = args[0];
cursor[1] = args[1];
const [x, y] = transformAbsolutePoint(matrix, args[0], args[1]);
args[0] = x;
args[1] = y;
}
if (command === 't') {
cursor[0] += args[0];
cursor[1] += args[1];
const [x, y] = transformRelativePoint(matrix, args[0], args[1]);
args[0] = x;
args[1] = y;
}
// elliptical arc (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
if (command === 'A') {
transformArc(cursor, args, matrix);
cursor[0] = args[5];
cursor[1] = args[6];
// reduce number of digits in rotation angle
if (Math.abs(args[2]) > 80) {
const a = args[0];
const rotation = args[2];
args[0] = args[1];
args[1] = a;
args[2] = rotation + (rotation > 0 ? -90 : 90);
}
const [x, y] = transformAbsolutePoint(matrix, args[5], args[6]);
args[5] = x;
args[6] = y;
}
if (command === 'a') {
transformArc([0, 0], args, matrix);
cursor[0] += args[5];
cursor[1] += args[6];
// reduce number of digits in rotation angle
if (Math.abs(args[2]) > 80) {
const a = args[0];
const rotation = args[2];
args[0] = args[1];
args[1] = a;
args[2] = rotation + (rotation > 0 ? -90 : 90);
}
const [x, y] = transformRelativePoint(matrix, args[5], args[6]);
args[5] = x;
args[6] = y;
}
// closepath
if (command === 'z' || command === 'Z') {
cursor[0] = start[0];
cursor[1] = start[1];
}
pathItem.command = command;
pathItem.args = args;
}
};
/**
* @typedef {import('../lib//types').PathDataItem} PathDataItem
*/
const { collectStylesheet: collectStylesheet$1, computeStyle: computeStyle$1 } = style;
const { visit } = xast;
const { pathElems } = _collections;
const { path2js: path2js$1, js2path: js2path$1 } = _path;
const { applyTransforms } = applyTransforms$2;
const { cleanupOutData: cleanupOutData$1 } = tools;
convertPathData$1.name = 'convertPathData';
convertPathData$1.description =
'optimizes path data: writes in shorter form, applies transformations';
/**
* @type {(data: number[]) => number[]}
*/
let roundData;
/**
* @type {number | false}
*/
let precision;
/**
* @type {number}
*/
let error;
/**
* @type {number}
*/
let arcThreshold;
/**
* @type {number}
*/
let arcTolerance;
/**
* @typedef {{
* applyTransforms: boolean,
* applyTransformsStroked: boolean,
* makeArcs: {
* threshold: number,
* tolerance: number,
* },
* straightCurves: boolean,
* lineShorthands: boolean,
* curveSmoothShorthands: boolean,
* floatPrecision: number | false,
* transformPrecision: number,
* removeUseless: boolean,
* collapseRepeated: boolean,
* utilizeAbsolute: boolean,
* leadingZero: boolean,
* negativeExtraSpace: boolean,
* noSpaceAfterFlags: boolean,
* forceAbsolutePath: boolean,
* }} InternalParams
*/
/**
* @typedef {[number, number]} Point
*/
/**
* @typedef {{
* center: Point,
* radius: number
* }} Circle
*/
/**
* Convert absolute Path to relative,
* collapse repeated instructions,
* detect and convert Lineto shorthands,
* remove useless instructions like "l0,0",
* trim useless delimiters and leading zeros,
* decrease accuracy of floating-point numbers.
*
* @see https://www.w3.org/TR/SVG11/paths.html#PathData
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'convertPathData'>}
*/
convertPathData$1.fn = (root, params) => {
const {
// TODO convert to separate plugin in v3
applyTransforms: _applyTransforms = true,
applyTransformsStroked = true,
makeArcs = {
threshold: 2.5, // coefficient of rounding error
tolerance: 0.5, // percentage of radius
},
straightCurves = true,
lineShorthands = true,
curveSmoothShorthands = true,
floatPrecision = 3,
transformPrecision = 5,
removeUseless = true,
collapseRepeated = true,
utilizeAbsolute = true,
leadingZero = true,
negativeExtraSpace = true,
noSpaceAfterFlags = false, // a20 60 45 0 1 30 20 → a20 60 45 0130 20
forceAbsolutePath = false,
} = params;
/**
* @type {InternalParams}
*/
const newParams = {
applyTransforms: _applyTransforms,
applyTransformsStroked,
makeArcs,
straightCurves,
lineShorthands,
curveSmoothShorthands,
floatPrecision,
transformPrecision,
removeUseless,
collapseRepeated,
utilizeAbsolute,
leadingZero,
negativeExtraSpace,
noSpaceAfterFlags,
forceAbsolutePath,
};
// invoke applyTransforms plugin
if (_applyTransforms) {
visit(
root,
// @ts-ignore
applyTransforms(root, {
transformPrecision,
applyTransformsStroked,
})
);
}
const stylesheet = collectStylesheet$1(root);
return {
element: {
enter: (node) => {
if (pathElems.includes(node.name) && node.attributes.d != null) {
const computedStyle = computeStyle$1(stylesheet, node);
precision = floatPrecision;
error =
precision !== false
? +Math.pow(0.1, precision).toFixed(precision)
: 1e-2;
roundData = precision > 0 && precision < 20 ? strongRound : round$1;
if (makeArcs) {
arcThreshold = makeArcs.threshold;
arcTolerance = makeArcs.tolerance;
}
const hasMarkerMid = computedStyle['marker-mid'] != null;
const maybeHasStroke =
computedStyle.stroke &&
(computedStyle.stroke.type === 'dynamic' ||
computedStyle.stroke.value !== 'none');
const maybeHasLinecap =
computedStyle['stroke-linecap'] &&
(computedStyle['stroke-linecap'].type === 'dynamic' ||
computedStyle['stroke-linecap'].value !== 'butt');
const maybeHasStrokeAndLinecap = maybeHasStroke && maybeHasLinecap;
var data = path2js$1(node);
// TODO: get rid of functions returns
if (data.length) {
convertToRelative(data);
data = filters(data, newParams, {
maybeHasStrokeAndLinecap,
hasMarkerMid,
});
if (utilizeAbsolute) {
data = convertToMixed(data, newParams);
}
// @ts-ignore
js2path$1(node, data, newParams);
}
}
},
},
};
};
/**
* Convert absolute path data coordinates to relative.
*
* @type {(pathData: PathDataItem[]) => PathDataItem[]}
*/
const convertToRelative = (pathData) => {
let start = [0, 0];
let cursor = [0, 0];
let prevCoords = [0, 0];
for (let i = 0; i < pathData.length; i += 1) {
const pathItem = pathData[i];
let { command, args } = pathItem;
// moveto (x y)
if (command === 'm') {
// update start and cursor
cursor[0] += args[0];
cursor[1] += args[1];
start[0] = cursor[0];
start[1] = cursor[1];
}
if (command === 'M') {
// M → m
// skip first moveto
if (i !== 0) {
command = 'm';
}
args[0] -= cursor[0];
args[1] -= cursor[1];
// update start and cursor
cursor[0] += args[0];
cursor[1] += args[1];
start[0] = cursor[0];
start[1] = cursor[1];
}
// lineto (x y)
if (command === 'l') {
cursor[0] += args[0];
cursor[1] += args[1];
}
if (command === 'L') {
// L → l
command = 'l';
args[0] -= cursor[0];
args[1] -= cursor[1];
cursor[0] += args[0];
cursor[1] += args[1];
}
// horizontal lineto (x)
if (command === 'h') {
cursor[0] += args[0];
}
if (command === 'H') {
// H → h
command = 'h';
args[0] -= cursor[0];
cursor[0] += args[0];
}
// vertical lineto (y)
if (command === 'v') {
cursor[1] += args[0];
}
if (command === 'V') {
// V → v
command = 'v';
args[0] -= cursor[1];
cursor[1] += args[0];
}
// curveto (x1 y1 x2 y2 x y)
if (command === 'c') {
cursor[0] += args[4];
cursor[1] += args[5];
}
if (command === 'C') {
// C → c
command = 'c';
args[0] -= cursor[0];
args[1] -= cursor[1];
args[2] -= cursor[0];
args[3] -= cursor[1];
args[4] -= cursor[0];
args[5] -= cursor[1];
cursor[0] += args[4];
cursor[1] += args[5];
}
// smooth curveto (x2 y2 x y)
if (command === 's') {
cursor[0] += args[2];
cursor[1] += args[3];
}
if (command === 'S') {
// S → s
command = 's';
args[0] -= cursor[0];
args[1] -= cursor[1];
args[2] -= cursor[0];
args[3] -= cursor[1];
cursor[0] += args[2];
cursor[1] += args[3];
}
// quadratic Bézier curveto (x1 y1 x y)
if (command === 'q') {
cursor[0] += args[2];
cursor[1] += args[3];
}
if (command === 'Q') {
// Q → q
command = 'q';
args[0] -= cursor[0];
args[1] -= cursor[1];
args[2] -= cursor[0];
args[3] -= cursor[1];
cursor[0] += args[2];
cursor[1] += args[3];
}
// smooth quadratic Bézier curveto (x y)
if (command === 't') {
cursor[0] += args[0];
cursor[1] += args[1];
}
if (command === 'T') {
// T → t
command = 't';
args[0] -= cursor[0];
args[1] -= cursor[1];
cursor[0] += args[0];
cursor[1] += args[1];
}
// elliptical arc (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
if (command === 'a') {
cursor[0] += args[5];
cursor[1] += args[6];
}
if (command === 'A') {
// A → a
command = 'a';
args[5] -= cursor[0];
args[6] -= cursor[1];
cursor[0] += args[5];
cursor[1] += args[6];
}
// closepath
if (command === 'Z' || command === 'z') {
// reset cursor
cursor[0] = start[0];
cursor[1] = start[1];
}
pathItem.command = command;
pathItem.args = args;
// store absolute coordinates for later use
// base should preserve reference from other element
// @ts-ignore
pathItem.base = prevCoords;
// @ts-ignore
pathItem.coords = [cursor[0], cursor[1]];
// @ts-ignore
prevCoords = pathItem.coords;
}
return pathData;
};
/**
* Main filters loop.
*
* @type {(
* path: PathDataItem[],
* params: InternalParams,
* aux: { maybeHasStrokeAndLinecap: boolean, hasMarkerMid: boolean }
* ) => PathDataItem[]}
*/
function filters(path, params, { maybeHasStrokeAndLinecap, hasMarkerMid }) {
var stringify = data2Path.bind(null, params),
relSubpoint = [0, 0],
pathBase = [0, 0],
prev = {};
path = path.filter(function (item, index, path) {
let command = item.command;
let data = item.args;
let next = path[index + 1];
if (command !== 'Z' && command !== 'z') {
var sdata = data,
circle;
if (command === 's') {
sdata = [0, 0].concat(data);
// @ts-ignore
var pdata = prev.args,
n = pdata.length;
// (-x, -y) of the prev tangent point relative to the current point
sdata[0] = pdata[n - 2] - pdata[n - 4];
sdata[1] = pdata[n - 1] - pdata[n - 3];
}
// convert curves to arcs if possible
if (
params.makeArcs &&
(command == 'c' || command == 's') &&
isConvex(sdata) &&
(circle = findCircle(sdata))
) {
var r = roundData([circle.radius])[0],
angle = findArcAngle(sdata, circle),
sweep = sdata[5] * sdata[0] - sdata[4] * sdata[1] > 0 ? 1 : 0,
/**
* @type {PathDataItem}
*/
arc = {
command: 'a',
args: [r, r, 0, 0, sweep, sdata[4], sdata[5]],
// @ts-ignore
coords: item.coords.slice(),
// @ts-ignore
base: item.base,
},
/**
* @type {PathDataItem[]}
*/
output = [arc],
// relative coordinates to adjust the found circle
/**
* @type {Point}
*/
relCenter = [
circle.center[0] - sdata[4],
circle.center[1] - sdata[5],
],
relCircle = { center: relCenter, radius: circle.radius },
arcCurves = [item],
hasPrev = 0,
suffix = '',
nextLonghand;
if (
// @ts-ignore
(prev.command == 'c' &&
// @ts-ignore
isConvex(prev.args) &&
// @ts-ignore
isArcPrev(prev.args, circle)) ||
// @ts-ignore
(prev.command == 'a' && prev.sdata && isArcPrev(prev.sdata, circle))
) {
// @ts-ignore
arcCurves.unshift(prev);
// @ts-ignore
arc.base = prev.base;
// @ts-ignore
arc.args[5] = arc.coords[0] - arc.base[0];
// @ts-ignore
arc.args[6] = arc.coords[1] - arc.base[1];
// @ts-ignore
var prevData = prev.command == 'a' ? prev.sdata : prev.args;
var prevAngle = findArcAngle(prevData, {
center: [
prevData[4] + circle.center[0],
prevData[5] + circle.center[1],
],
radius: circle.radius,
});
angle += prevAngle;
if (angle > Math.PI) arc.args[3] = 1;
hasPrev = 1;
}
// check if next curves are fitting the arc
for (
var j = index;
(next = path[++j]) && ~'cs'.indexOf(next.command);
) {
var nextData = next.args;
if (next.command == 's') {
nextLonghand = makeLonghand(
{ command: 's', args: next.args.slice() },
path[j - 1].args
);
nextData = nextLonghand.args;
nextLonghand.args = nextData.slice(0, 2);
suffix = stringify([nextLonghand]);
}
if (isConvex(nextData) && isArc(nextData, relCircle)) {
angle += findArcAngle(nextData, relCircle);
if (angle - 2 * Math.PI > 1e-3) break; // more than 360°
if (angle > Math.PI) arc.args[3] = 1;
arcCurves.push(next);
if (2 * Math.PI - angle > 1e-3) {
// less than 360°
// @ts-ignore
arc.coords = next.coords;
// @ts-ignore
arc.args[5] = arc.coords[0] - arc.base[0];
// @ts-ignore
arc.args[6] = arc.coords[1] - arc.base[1];
} else {
// full circle, make a half-circle arc and add a second one
arc.args[5] = 2 * (relCircle.center[0] - nextData[4]);
arc.args[6] = 2 * (relCircle.center[1] - nextData[5]);
// @ts-ignore
arc.coords = [
// @ts-ignore
arc.base[0] + arc.args[5],
// @ts-ignore
arc.base[1] + arc.args[6],
];
arc = {
command: 'a',
args: [
r,
r,
0,
0,
sweep,
// @ts-ignore
next.coords[0] - arc.coords[0],
// @ts-ignore
next.coords[1] - arc.coords[1],
],
// @ts-ignore
coords: next.coords,
// @ts-ignore
base: arc.coords,
};
output.push(arc);
j++;
break;
}
relCenter[0] -= nextData[4];
relCenter[1] -= nextData[5];
} else break;
}
if ((stringify(output) + suffix).length < stringify(arcCurves).length) {
if (path[j] && path[j].command == 's') {
makeLonghand(path[j], path[j - 1].args);
}
if (hasPrev) {
var prevArc = output.shift();
// @ts-ignore
roundData(prevArc.args);
// @ts-ignore
relSubpoint[0] += prevArc.args[5] - prev.args[prev.args.length - 2];
// @ts-ignore
relSubpoint[1] += prevArc.args[6] - prev.args[prev.args.length - 1];
// @ts-ignore
prev.command = 'a';
// @ts-ignore
prev.args = prevArc.args;
// @ts-ignore
item.base = prev.coords = prevArc.coords;
}
// @ts-ignore
arc = output.shift();
if (arcCurves.length == 1) {
// @ts-ignore
item.sdata = sdata.slice(); // preserve curve data for future checks
} else if (arcCurves.length - 1 - hasPrev > 0) {
// filter out consumed next items
path.splice.apply(
path,
// @ts-ignore
[index + 1, arcCurves.length - 1 - hasPrev].concat(output)
);
}
if (!arc) return false;
command = 'a';
data = arc.args;
// @ts-ignore
item.coords = arc.coords;
}
}
// Rounding relative coordinates, taking in account accummulating error
// to get closer to absolute coordinates. Sum of rounded value remains same:
// l .25 3 .25 2 .25 3 .25 2 -> l .3 3 .2 2 .3 3 .2 2
if (precision !== false) {
if (
command === 'm' ||
command === 'l' ||
command === 't' ||
command === 'q' ||
command === 's' ||
command === 'c'
) {
for (var i = data.length; i--; ) {
// @ts-ignore
data[i] += item.base[i % 2] - relSubpoint[i % 2];
}
} else if (command == 'h') {
// @ts-ignore
data[0] += item.base[0] - relSubpoint[0];
} else if (command == 'v') {
// @ts-ignore
data[0] += item.base[1] - relSubpoint[1];
} else if (command == 'a') {
// @ts-ignore
data[5] += item.base[0] - relSubpoint[0];
// @ts-ignore
data[6] += item.base[1] - relSubpoint[1];
}
roundData(data);
if (command == 'h') relSubpoint[0] += data[0];
else if (command == 'v') relSubpoint[1] += data[0];
else {
relSubpoint[0] += data[data.length - 2];
relSubpoint[1] += data[data.length - 1];
}
roundData(relSubpoint);
if (command === 'M' || command === 'm') {
pathBase[0] = relSubpoint[0];
pathBase[1] = relSubpoint[1];
}
}
// convert straight curves into lines segments
if (params.straightCurves) {
if (
(command === 'c' && isCurveStraightLine(data)) ||
(command === 's' && isCurveStraightLine(sdata))
) {
if (next && next.command == 's') makeLonghand(next, data); // fix up next curve
command = 'l';
data = data.slice(-2);
} else if (command === 'q' && isCurveStraightLine(data)) {
if (next && next.command == 't') makeLonghand(next, data); // fix up next curve
command = 'l';
data = data.slice(-2);
} else if (
command === 't' &&
// @ts-ignore
prev.command !== 'q' &&
// @ts-ignore
prev.command !== 't'
) {
command = 'l';
data = data.slice(-2);
} else if (command === 'a' && (data[0] === 0 || data[1] === 0)) {
command = 'l';
data = data.slice(-2);
}
}
// horizontal and vertical line shorthands
// l 50 0 → h 50
// l 0 50 → v 50
if (params.lineShorthands && command === 'l') {
if (data[1] === 0) {
command = 'h';
data.pop();
} else if (data[0] === 0) {
command = 'v';
data.shift();
}
}
// collapse repeated commands
// h 20 h 30 -> h 50
if (
params.collapseRepeated &&
hasMarkerMid === false &&
(command === 'm' || command === 'h' || command === 'v') &&
// @ts-ignore
prev.command &&
// @ts-ignore
command == prev.command.toLowerCase() &&
((command != 'h' && command != 'v') ||
// @ts-ignore
prev.args[0] >= 0 == data[0] >= 0)
) {
// @ts-ignore
prev.args[0] += data[0];
if (command != 'h' && command != 'v') {
// @ts-ignore
prev.args[1] += data[1];
}
// @ts-ignore
prev.coords = item.coords;
// @ts-ignore
path[index] = prev;
return false;
}
// convert curves into smooth shorthands
// @ts-ignore
if (params.curveSmoothShorthands && prev.command) {
// curveto
if (command === 'c') {
// c + c → c + s
if (
// @ts-ignore
prev.command === 'c' &&
// @ts-ignore
data[0] === -(prev.args[2] - prev.args[4]) &&
// @ts-ignore
data[1] === -(prev.args[3] - prev.args[5])
) {
command = 's';
data = data.slice(2);
}
// s + c → s + s
else if (
// @ts-ignore
prev.command === 's' &&
// @ts-ignore
data[0] === -(prev.args[0] - prev.args[2]) &&
// @ts-ignore
data[1] === -(prev.args[1] - prev.args[3])
) {
command = 's';
data = data.slice(2);
}
// [^cs] + c → [^cs] + s
else if (
// @ts-ignore
prev.command !== 'c' &&
// @ts-ignore
prev.command !== 's' &&
data[0] === 0 &&
data[1] === 0
) {
command = 's';
data = data.slice(2);
}
}
// quadratic Bézier curveto
else if (command === 'q') {
// q + q → q + t
if (
// @ts-ignore
prev.command === 'q' &&
// @ts-ignore
data[0] === prev.args[2] - prev.args[0] &&
// @ts-ignore
data[1] === prev.args[3] - prev.args[1]
) {
command = 't';
data = data.slice(2);
}
// t + q → t + t
else if (
// @ts-ignore
prev.command === 't' &&
// @ts-ignore
data[2] === prev.args[0] &&
// @ts-ignore
data[3] === prev.args[1]
) {
command = 't';
data = data.slice(2);
}
}
}
// remove useless non-first path segments
if (params.removeUseless && !maybeHasStrokeAndLinecap) {
// l 0,0 / h 0 / v 0 / q 0,0 0,0 / t 0,0 / c 0,0 0,0 0,0 / s 0,0 0,0
if (
(command === 'l' ||
command === 'h' ||
command === 'v' ||
command === 'q' ||
command === 't' ||
command === 'c' ||
command === 's') &&
data.every(function (i) {
return i === 0;
})
) {
// @ts-ignore
path[index] = prev;
return false;
}
// a 25,25 -30 0,1 0,0
if (command === 'a' && data[5] === 0 && data[6] === 0) {
// @ts-ignore
path[index] = prev;
return false;
}
}
item.command = command;
item.args = data;
prev = item;
} else {
// z resets coordinates
relSubpoint[0] = pathBase[0];
relSubpoint[1] = pathBase[1];
// @ts-ignore
if (prev.command === 'Z' || prev.command === 'z') return false;
prev = item;
}
return true;
});
return path;
}
/**
* Writes data in shortest form using absolute or relative coordinates.
*
* @type {(path: PathDataItem[], params: InternalParams) => PathDataItem[]}
*/
function convertToMixed(path, params) {
var prev = path[0];
path = path.filter(function (item, index) {
if (index == 0) return true;
if (item.command === 'Z' || item.command === 'z') {
prev = item;
return true;
}
var command = item.command,
data = item.args,
adata = data.slice();
if (
command === 'm' ||
command === 'l' ||
command === 't' ||
command === 'q' ||
command === 's' ||
command === 'c'
) {
for (var i = adata.length; i--; ) {
// @ts-ignore
adata[i] += item.base[i % 2];
}
} else if (command == 'h') {
// @ts-ignore
adata[0] += item.base[0];
} else if (command == 'v') {
// @ts-ignore
adata[0] += item.base[1];
} else if (command == 'a') {
// @ts-ignore
adata[5] += item.base[0];
// @ts-ignore
adata[6] += item.base[1];
}
roundData(adata);
var absoluteDataStr = cleanupOutData$1(adata, params),
relativeDataStr = cleanupOutData$1(data, params);
// Convert to absolute coordinates if it's shorter or forceAbsolutePath is true.
// v-20 -> V0
// Don't convert if it fits following previous command.
// l20 30-10-50 instead of l20 30L20 30
if (
params.forceAbsolutePath ||
(absoluteDataStr.length < relativeDataStr.length &&
!(
params.negativeExtraSpace &&
command == prev.command &&
prev.command.charCodeAt(0) > 96 &&
absoluteDataStr.length == relativeDataStr.length - 1 &&
(data[0] < 0 ||
// @ts-ignore
(/^0\./.test(data[0]) && prev.args[prev.args.length - 1] % 1))
))
) {
// @ts-ignore
item.command = command.toUpperCase();
item.args = adata;
}
prev = item;
return true;
});
return path;
}
/**
* Checks if curve is convex. Control points of such a curve must form
* a convex quadrilateral with diagonals crosspoint inside of it.
*
* @type {(data: number[]) => boolean}
*/
function isConvex(data) {
var center = getIntersection([
0,
0,
data[2],
data[3],
data[0],
data[1],
data[4],
data[5],
]);
return (
center != null &&
data[2] < center[0] == center[0] < 0 &&
data[3] < center[1] == center[1] < 0 &&
data[4] < center[0] == center[0] < data[0] &&
data[5] < center[1] == center[1] < data[1]
);
}
/**
* Computes lines equations by two points and returns their intersection point.
*
* @type {(coords: number[]) => undefined | Point}
*/
function getIntersection(coords) {
// Prev line equation parameters.
var a1 = coords[1] - coords[3], // y1 - y2
b1 = coords[2] - coords[0], // x2 - x1
c1 = coords[0] * coords[3] - coords[2] * coords[1], // x1 * y2 - x2 * y1
// Next line equation parameters
a2 = coords[5] - coords[7], // y1 - y2
b2 = coords[6] - coords[4], // x2 - x1
c2 = coords[4] * coords[7] - coords[5] * coords[6], // x1 * y2 - x2 * y1
denom = a1 * b2 - a2 * b1;
if (!denom) return; // parallel lines havn't an intersection
/**
* @type {Point}
*/
var cross = [(b1 * c2 - b2 * c1) / denom, (a1 * c2 - a2 * c1) / -denom];
if (
!isNaN(cross[0]) &&
!isNaN(cross[1]) &&
isFinite(cross[0]) &&
isFinite(cross[1])
) {
return cross;
}
}
/**
* Decrease accuracy of floating-point numbers
* in path data keeping a specified number of decimals.
* Smart rounds values like 2.3491 to 2.35 instead of 2.349.
* Doesn't apply "smartness" if the number precision fits already.
*
* @type {(data: number[]) => number[]}
*/
function strongRound(data) {
for (var i = data.length; i-- > 0; ) {
// @ts-ignore
if (data[i].toFixed(precision) != data[i]) {
// @ts-ignore
var rounded = +data[i].toFixed(precision - 1);
data[i] =
// @ts-ignore
+Math.abs(rounded - data[i]).toFixed(precision + 1) >= error
? // @ts-ignore
+data[i].toFixed(precision)
: rounded;
}
}
return data;
}
/**
* Simple rounding function if precision is 0.
*
* @type {(data: number[]) => number[]}
*/
function round$1(data) {
for (var i = data.length; i-- > 0; ) {
data[i] = Math.round(data[i]);
}
return data;
}
/**
* Checks if a curve is a straight line by measuring distance
* from middle points to the line formed by end points.
*
* @type {(data: number[]) => boolean}
*/
function isCurveStraightLine(data) {
// Get line equation a·x + b·y + c = 0 coefficients a, b (c = 0) by start and end points.
var i = data.length - 2,
a = -data[i + 1], // y1 y2 (y1 = 0)
b = data[i], // x2 x1 (x1 = 0)
d = 1 / (a * a + b * b); // same part for all points
if (i <= 1 || !isFinite(d)) return false; // curve that ends at start point isn't the case
// Distance from point (x0, y0) to the line is sqrt((c a·x0 b·y0)² / (a² + b²))
while ((i -= 2) >= 0) {
if (Math.sqrt(Math.pow(a * data[i] + b * data[i + 1], 2) * d) > error)
return false;
}
return true;
}
/**
* Converts next curve from shorthand to full form using the current curve data.
*
* @type {(item: PathDataItem, data: number[]) => PathDataItem}
*/
function makeLonghand(item, data) {
switch (item.command) {
case 's':
item.command = 'c';
break;
case 't':
item.command = 'q';
break;
}
item.args.unshift(
data[data.length - 2] - data[data.length - 4],
data[data.length - 1] - data[data.length - 3]
);
return item;
}
/**
* Returns distance between two points
*
* @type {(point1: Point, point2: Point) => number}
*/
function getDistance(point1, point2) {
return Math.hypot(point1[0] - point2[0], point1[1] - point2[1]);
}
/**
* Returns coordinates of the curve point corresponding to the certain t
* a·(1 - t)³·p1 + b·(1 - t)²·t·p2 + c·(1 - t)·t²·p3 + d·t³·p4,
* where pN are control points and p1 is zero due to relative coordinates.
*
* @type {(curve: number[], t: number) => Point}
*/
function getCubicBezierPoint(curve, t) {
var sqrT = t * t,
cubT = sqrT * t,
mt = 1 - t,
sqrMt = mt * mt;
return [
3 * sqrMt * t * curve[0] + 3 * mt * sqrT * curve[2] + cubT * curve[4],
3 * sqrMt * t * curve[1] + 3 * mt * sqrT * curve[3] + cubT * curve[5],
];
}
/**
* Finds circle by 3 points of the curve and checks if the curve fits the found circle.
*
* @type {(curve: number[]) => undefined | Circle}
*/
function findCircle(curve) {
var midPoint = getCubicBezierPoint(curve, 1 / 2),
m1 = [midPoint[0] / 2, midPoint[1] / 2],
m2 = [(midPoint[0] + curve[4]) / 2, (midPoint[1] + curve[5]) / 2],
center = getIntersection([
m1[0],
m1[1],
m1[0] + m1[1],
m1[1] - m1[0],
m2[0],
m2[1],
m2[0] + (m2[1] - midPoint[1]),
m2[1] - (m2[0] - midPoint[0]),
]),
radius = center && getDistance([0, 0], center),
// @ts-ignore
tolerance = Math.min(arcThreshold * error, (arcTolerance * radius) / 100);
if (
center &&
// @ts-ignore
radius < 1e15 &&
[1 / 4, 3 / 4].every(function (point) {
return (
Math.abs(
// @ts-ignore
getDistance(getCubicBezierPoint(curve, point), center) - radius
) <= tolerance
);
})
)
// @ts-ignore
return { center: center, radius: radius };
}
/**
* Checks if a curve fits the given circle.
*
* @type {(curve: number[], circle: Circle) => boolean}
*/
function isArc(curve, circle) {
var tolerance = Math.min(
arcThreshold * error,
(arcTolerance * circle.radius) / 100
);
return [0, 1 / 4, 1 / 2, 3 / 4, 1].every(function (point) {
return (
Math.abs(
getDistance(getCubicBezierPoint(curve, point), circle.center) -
circle.radius
) <= tolerance
);
});
}
/**
* Checks if a previous curve fits the given circle.
*
* @type {(curve: number[], circle: Circle) => boolean}
*/
function isArcPrev(curve, circle) {
return isArc(curve, {
center: [circle.center[0] + curve[4], circle.center[1] + curve[5]],
radius: circle.radius,
});
}
/**
* Finds angle of a curve fitting the given arc.
* @type {(curve: number[], relCircle: Circle) => number}
*/
function findArcAngle(curve, relCircle) {
var x1 = -relCircle.center[0],
y1 = -relCircle.center[1],
x2 = curve[4] - relCircle.center[0],
y2 = curve[5] - relCircle.center[1];
return Math.acos(
(x1 * x2 + y1 * y2) / Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2))
);
}
/**
* Converts given path data to string.
*
* @type {(params: InternalParams, pathData: PathDataItem[]) => string}
*/
function data2Path(params, pathData) {
return pathData.reduce(function (pathString, item) {
var strData = '';
if (item.args) {
strData = cleanupOutData$1(roundData(item.args.slice()), params);
}
return pathString + item.command + strData;
}, '');
}
var convertTransform$2 = {};
/**
* @typedef {import('../lib/types').XastElement} XastElement
*/
const { cleanupOutData } = tools;
const {
transform2js,
transformsMultiply,
matrixToTransform,
} = _transforms;
convertTransform$2.name = 'convertTransform';
convertTransform$2.description = 'collapses multiple transformations and optimizes it';
/**
* Convert matrices to the short aliases,
* convert long translate, scale or rotate transform notations to the shorts ones,
* convert transforms to the matrices and multiply them all into one,
* remove useless transforms.
*
* @see https://www.w3.org/TR/SVG11/coords.html#TransformMatrixDefined
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'convertTransform'>}
*/
convertTransform$2.fn = (_root, params) => {
const {
convertToShorts = true,
// degPrecision = 3, // transformPrecision (or matrix precision) - 2 by default
degPrecision,
floatPrecision = 3,
transformPrecision = 5,
matrixToTransform = true,
shortTranslate = true,
shortScale = true,
shortRotate = true,
removeUseless = true,
collapseIntoOne = true,
leadingZero = true,
negativeExtraSpace = false,
} = params;
const newParams = {
convertToShorts,
degPrecision,
floatPrecision,
transformPrecision,
matrixToTransform,
shortTranslate,
shortScale,
shortRotate,
removeUseless,
collapseIntoOne,
leadingZero,
negativeExtraSpace,
};
return {
element: {
enter: (node) => {
// transform
if (node.attributes.transform != null) {
convertTransform$1(node, 'transform', newParams);
}
// gradientTransform
if (node.attributes.gradientTransform != null) {
convertTransform$1(node, 'gradientTransform', newParams);
}
// patternTransform
if (node.attributes.patternTransform != null) {
convertTransform$1(node, 'patternTransform', newParams);
}
},
},
};
};
/**
* @typedef {{
* convertToShorts: boolean,
* degPrecision?: number,
* floatPrecision: number,
* transformPrecision: number,
* matrixToTransform: boolean,
* shortTranslate: boolean,
* shortScale: boolean,
* shortRotate: boolean,
* removeUseless: boolean,
* collapseIntoOne: boolean,
* leadingZero: boolean,
* negativeExtraSpace: boolean,
* }} TransformParams
*/
/**
* @typedef {{ name: string, data: Array<number> }} TransformItem
*/
/**
* Main function.
*
* @type {(item: XastElement, attrName: string, params: TransformParams) => void}
*/
const convertTransform$1 = (item, attrName, params) => {
let data = transform2js(item.attributes[attrName]);
params = definePrecision(data, params);
if (params.collapseIntoOne && data.length > 1) {
data = [transformsMultiply(data)];
}
if (params.convertToShorts) {
data = convertToShorts(data, params);
} else {
data.forEach((item) => roundTransform(item, params));
}
if (params.removeUseless) {
data = removeUseless(data);
}
if (data.length) {
item.attributes[attrName] = js2transform(data, params);
} else {
delete item.attributes[attrName];
}
};
/**
* Defines precision to work with certain parts.
* transformPrecision - for scale and four first matrix parameters (needs a better precision due to multiplying),
* floatPrecision - for translate including two last matrix and rotate parameters,
* degPrecision - for rotate and skew. By default it's equal to (rougly)
* transformPrecision - 2 or floatPrecision whichever is lower. Can be set in params.
*
* @type {(data: Array<TransformItem>, params: TransformParams) => TransformParams}
*
* clone params so it don't affect other elements transformations.
*/
const definePrecision = (data, { ...newParams }) => {
const matrixData = [];
for (const item of data) {
if (item.name == 'matrix') {
matrixData.push(...item.data.slice(0, 4));
}
}
let significantDigits = newParams.transformPrecision;
// Limit transform precision with matrix one. Calculating with larger precision doesn't add any value.
if (matrixData.length) {
newParams.transformPrecision = Math.min(
newParams.transformPrecision,
Math.max.apply(Math, matrixData.map(floatDigits)) ||
newParams.transformPrecision
);
significantDigits = Math.max.apply(
Math,
matrixData.map(
(n) => n.toString().replace(/\D+/g, '').length // Number of digits in a number. 123.45 → 5
)
);
}
// No sense in angle precision more then number of significant digits in matrix.
if (newParams.degPrecision == null) {
newParams.degPrecision = Math.max(
0,
Math.min(newParams.floatPrecision, significantDigits - 2)
);
}
return newParams;
};
/**
* @type {(data: Array<number>, params: TransformParams) => Array<number>}
*/
const degRound = (data, params) => {
if (
params.degPrecision != null &&
params.degPrecision >= 1 &&
params.floatPrecision < 20
) {
return smartRound(params.degPrecision, data);
} else {
return round(data);
}
};
/**
* @type {(data: Array<number>, params: TransformParams) => Array<number>}
*/
const floatRound = (data, params) => {
if (params.floatPrecision >= 1 && params.floatPrecision < 20) {
return smartRound(params.floatPrecision, data);
} else {
return round(data);
}
};
/**
* @type {(data: Array<number>, params: TransformParams) => Array<number>}
*/
const transformRound = (data, params) => {
if (params.transformPrecision >= 1 && params.floatPrecision < 20) {
return smartRound(params.transformPrecision, data);
} else {
return round(data);
}
};
/**
* Returns number of digits after the point. 0.125 → 3
*
* @type {(n: number) => number}
*/
const floatDigits = (n) => {
const str = n.toString();
return str.slice(str.indexOf('.')).length - 1;
};
/**
* Convert transforms to the shorthand alternatives.
*
* @type {(transforms: Array<TransformItem>, params: TransformParams) => Array<TransformItem>}
*/
const convertToShorts = (transforms, params) => {
for (var i = 0; i < transforms.length; i++) {
var transform = transforms[i];
// convert matrix to the short aliases
if (params.matrixToTransform && transform.name === 'matrix') {
var decomposed = matrixToTransform(transform, params);
if (
js2transform(decomposed, params).length <=
js2transform([transform], params).length
) {
transforms.splice(i, 1, ...decomposed);
}
transform = transforms[i];
}
// fixed-point numbers
// 12.754997 → 12.755
roundTransform(transform, params);
// convert long translate transform notation to the shorts one
// translate(10 0) → translate(10)
if (
params.shortTranslate &&
transform.name === 'translate' &&
transform.data.length === 2 &&
!transform.data[1]
) {
transform.data.pop();
}
// convert long scale transform notation to the shorts one
// scale(2 2) → scale(2)
if (
params.shortScale &&
transform.name === 'scale' &&
transform.data.length === 2 &&
transform.data[0] === transform.data[1]
) {
transform.data.pop();
}
// convert long rotate transform notation to the short one
// translate(cx cy) rotate(a) translate(-cx -cy) → rotate(a cx cy)
if (
params.shortRotate &&
transforms[i - 2] &&
transforms[i - 2].name === 'translate' &&
transforms[i - 1].name === 'rotate' &&
transforms[i].name === 'translate' &&
transforms[i - 2].data[0] === -transforms[i].data[0] &&
transforms[i - 2].data[1] === -transforms[i].data[1]
) {
transforms.splice(i - 2, 3, {
name: 'rotate',
data: [
transforms[i - 1].data[0],
transforms[i - 2].data[0],
transforms[i - 2].data[1],
],
});
// splice compensation
i -= 2;
}
}
return transforms;
};
/**
* Remove useless transforms.
*
* @type {(trasforms: Array<TransformItem>) => Array<TransformItem>}
*/
const removeUseless = (transforms) => {
return transforms.filter((transform) => {
// translate(0), rotate(0[, cx, cy]), skewX(0), skewY(0)
if (
(['translate', 'rotate', 'skewX', 'skewY'].indexOf(transform.name) > -1 &&
(transform.data.length == 1 || transform.name == 'rotate') &&
!transform.data[0]) ||
// translate(0, 0)
(transform.name == 'translate' &&
!transform.data[0] &&
!transform.data[1]) ||
// scale(1)
(transform.name == 'scale' &&
transform.data[0] == 1 &&
(transform.data.length < 2 || transform.data[1] == 1)) ||
// matrix(1 0 0 1 0 0)
(transform.name == 'matrix' &&
transform.data[0] == 1 &&
transform.data[3] == 1 &&
!(
transform.data[1] ||
transform.data[2] ||
transform.data[4] ||
transform.data[5]
))
) {
return false;
}
return true;
});
};
/**
* Convert transforms JS representation to string.
*
* @type {(transformJS: Array<TransformItem>, params: TransformParams) => string}
*/
const js2transform = (transformJS, params) => {
var transformString = '';
// collect output value string
transformJS.forEach((transform) => {
roundTransform(transform, params);
transformString +=
(transformString && ' ') +
transform.name +
'(' +
cleanupOutData(transform.data, params) +
')';
});
return transformString;
};
/**
* @type {(transform: TransformItem, params: TransformParams) => TransformItem}
*/
const roundTransform = (transform, params) => {
switch (transform.name) {
case 'translate':
transform.data = floatRound(transform.data, params);
break;
case 'rotate':
transform.data = [
...degRound(transform.data.slice(0, 1), params),
...floatRound(transform.data.slice(1), params),
];
break;
case 'skewX':
case 'skewY':
transform.data = degRound(transform.data, params);
break;
case 'scale':
transform.data = transformRound(transform.data, params);
break;
case 'matrix':
transform.data = [
...transformRound(transform.data.slice(0, 4), params),
...floatRound(transform.data.slice(4), params),
];
break;
}
return transform;
};
/**
* Rounds numbers in array.
*
* @type {(data: Array<number>) => Array<number>}
*/
const round = (data) => {
return data.map(Math.round);
};
/**
* Decrease accuracy of floating-point numbers
* in transforms keeping a specified number of decimals.
* Smart rounds values like 2.349 to 2.35.
*
* @type {(precision: number, data: Array<number>) => Array<number>}
*/
const smartRound = (precision, data) => {
for (
var i = data.length,
tolerance = +Math.pow(0.1, precision).toFixed(precision);
i--;
) {
if (Number(data[i].toFixed(precision)) !== data[i]) {
var rounded = +data[i].toFixed(precision - 1);
data[i] =
+Math.abs(rounded - data[i]).toFixed(precision + 1) >= tolerance
? +data[i].toFixed(precision)
: rounded;
}
}
return data;
};
var removeEmptyAttrs$1 = {};
const { attrsGroups: attrsGroups$1 } = _collections;
removeEmptyAttrs$1.name = 'removeEmptyAttrs';
removeEmptyAttrs$1.description = 'removes empty attributes';
/**
* Remove attributes with empty values.
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'removeEmptyAttrs'>}
*/
removeEmptyAttrs$1.fn = () => {
return {
element: {
enter: (node) => {
for (const [name, value] of Object.entries(node.attributes)) {
if (
value === '' &&
// empty conditional processing attributes prevents elements from rendering
attrsGroups$1.conditionalProcessing.includes(name) === false
) {
delete node.attributes[name];
}
}
},
},
};
};
var removeEmptyContainers$1 = {};
const { detachNodeFromParent: detachNodeFromParent$8 } = xast;
const { elemsGroups } = _collections;
removeEmptyContainers$1.name = 'removeEmptyContainers';
removeEmptyContainers$1.description = 'removes empty container elements';
/**
* Remove empty containers.
*
* @see https://www.w3.org/TR/SVG11/intro.html#TermContainerElement
*
* @example
* <defs/>
*
* @example
* <g><marker><a/></marker></g>
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'removeEmptyContainers'>}
*/
removeEmptyContainers$1.fn = () => {
return {
element: {
exit: (node, parentNode) => {
// remove only empty non-svg containers
if (
node.name === 'svg' ||
elemsGroups.container.includes(node.name) === false ||
node.children.length !== 0
) {
return;
}
// empty patterns may contain reusable configuration
if (
node.name === 'pattern' &&
Object.keys(node.attributes).length !== 0
) {
return;
}
// The <g> may not have content, but the filter may cause a rectangle
// to be created and filled with pattern.
if (node.name === 'g' && node.attributes.filter != null) {
return;
}
// empty <mask> hides masked element
if (node.name === 'mask' && node.attributes.id != null) {
return;
}
detachNodeFromParent$8(node, parentNode);
},
},
};
};
var mergePaths$1 = {};
const { detachNodeFromParent: detachNodeFromParent$7 } = xast;
const { collectStylesheet, computeStyle } = style;
const { path2js, js2path, intersects: intersects$1 } = _path;
mergePaths$1.name = 'mergePaths';
mergePaths$1.description = 'merges multiple paths in one if possible';
/**
* Merge multiple Paths into one.
*
* @author Kir Belevich, Lev Solntsev
*
* @type {import('./plugins-types').Plugin<'mergePaths'>}
*/
mergePaths$1.fn = (root, params) => {
const {
force = false,
floatPrecision,
noSpaceAfterFlags = false, // a20 60 45 0 1 30 20 → a20 60 45 0130 20
} = params;
const stylesheet = collectStylesheet(root);
return {
element: {
enter: (node) => {
let prevChild = null;
for (const child of node.children) {
// skip if previous element is not path or contains animation elements
if (
prevChild == null ||
prevChild.type !== 'element' ||
prevChild.name !== 'path' ||
prevChild.children.length !== 0 ||
prevChild.attributes.d == null
) {
prevChild = child;
continue;
}
// skip if element is not path or contains animation elements
if (
child.type !== 'element' ||
child.name !== 'path' ||
child.children.length !== 0 ||
child.attributes.d == null
) {
prevChild = child;
continue;
}
// preserve paths with markers
const computedStyle = computeStyle(stylesheet, child);
if (
computedStyle['marker-start'] ||
computedStyle['marker-mid'] ||
computedStyle['marker-end']
) {
prevChild = child;
continue;
}
const prevChildAttrs = Object.keys(prevChild.attributes);
const childAttrs = Object.keys(child.attributes);
let attributesAreEqual = prevChildAttrs.length === childAttrs.length;
for (const name of childAttrs) {
if (name !== 'd') {
if (
prevChild.attributes[name] == null ||
prevChild.attributes[name] !== child.attributes[name]
) {
attributesAreEqual = false;
}
}
}
const prevPathJS = path2js(prevChild);
const curPathJS = path2js(child);
if (
attributesAreEqual &&
(force || !intersects$1(prevPathJS, curPathJS))
) {
js2path(prevChild, prevPathJS.concat(curPathJS), {
floatPrecision,
noSpaceAfterFlags,
});
detachNodeFromParent$7(child, node);
continue;
}
prevChild = child;
}
},
},
};
};
var removeUnusedNS$1 = {};
removeUnusedNS$1.name = 'removeUnusedNS';
removeUnusedNS$1.description = 'removes unused namespaces declaration';
/**
* Remove unused namespaces declaration from svg element
* which are not used in elements or attributes
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'removeUnusedNS'>}
*/
removeUnusedNS$1.fn = () => {
/**
* @type {Set<string>}
*/
const unusedNamespaces = new Set();
return {
element: {
enter: (node, parentNode) => {
// collect all namespaces from svg element
// (such as xmlns:xlink="http://www.w3.org/1999/xlink")
if (node.name === 'svg' && parentNode.type === 'root') {
for (const name of Object.keys(node.attributes)) {
if (name.startsWith('xmlns:')) {
const local = name.slice('xmlns:'.length);
unusedNamespaces.add(local);
}
}
}
if (unusedNamespaces.size !== 0) {
// preserve namespace used in nested elements names
if (node.name.includes(':')) {
const [ns] = node.name.split(':');
if (unusedNamespaces.has(ns)) {
unusedNamespaces.delete(ns);
}
}
// preserve namespace used in nested elements attributes
for (const name of Object.keys(node.attributes)) {
if (name.includes(':')) {
const [ns] = name.split(':');
unusedNamespaces.delete(ns);
}
}
}
},
exit: (node, parentNode) => {
// remove unused namespace attributes from svg element
if (node.name === 'svg' && parentNode.type === 'root') {
for (const name of unusedNamespaces) {
delete node.attributes[`xmlns:${name}`];
}
}
},
},
};
};
var sortAttrs$1 = {};
sortAttrs$1.name = 'sortAttrs';
sortAttrs$1.description = 'Sort element attributes for better compression';
/**
* Sort element attributes for better compression
*
* @author Nikolay Frantsev
*
* @type {import('./plugins-types').Plugin<'sortAttrs'>}
*/
sortAttrs$1.fn = (_root, params) => {
const {
order = [
'id',
'width',
'height',
'x',
'x1',
'x2',
'y',
'y1',
'y2',
'cx',
'cy',
'r',
'fill',
'stroke',
'marker',
'd',
'points',
],
xmlnsOrder = 'front',
} = params;
/**
* @type {(name: string) => number}
*/
const getNsPriority = (name) => {
if (xmlnsOrder === 'front') {
// put xmlns first
if (name === 'xmlns') {
return 3;
}
// xmlns:* attributes second
if (name.startsWith('xmlns:')) {
return 2;
}
}
// other namespaces after and sort them alphabetically
if (name.includes(':')) {
return 1;
}
// other attributes
return 0;
};
/**
* @type {(a: [string, string], b: [string, string]) => number}
*/
const compareAttrs = ([aName], [bName]) => {
// sort namespaces
const aPriority = getNsPriority(aName);
const bPriority = getNsPriority(bName);
const priorityNs = bPriority - aPriority;
if (priorityNs !== 0) {
return priorityNs;
}
// extract the first part from attributes
// for example "fill" from "fill" and "fill-opacity"
const [aPart] = aName.split('-');
const [bPart] = bName.split('-');
// rely on alphabetical sort when the first part is the same
if (aPart !== bPart) {
const aInOrderFlag = order.includes(aPart) ? 1 : 0;
const bInOrderFlag = order.includes(bPart) ? 1 : 0;
// sort by position in order param
if (aInOrderFlag === 1 && bInOrderFlag === 1) {
return order.indexOf(aPart) - order.indexOf(bPart);
}
// put attributes from order param before others
const priorityOrder = bInOrderFlag - aInOrderFlag;
if (priorityOrder !== 0) {
return priorityOrder;
}
}
// sort alphabetically
return aName < bName ? -1 : 1;
};
return {
element: {
enter: (node) => {
const attrs = Object.entries(node.attributes);
attrs.sort(compareAttrs);
/**
* @type {Record<string, string>}
*/
const sortedAttributes = {};
for (const [name, value] of attrs) {
sortedAttributes[name] = value;
}
node.attributes = sortedAttributes;
},
},
};
};
var sortDefsChildren$1 = {};
sortDefsChildren$1.name = 'sortDefsChildren';
sortDefsChildren$1.description = 'Sorts children of <defs> to improve compression';
/**
* Sorts children of defs in order to improve compression.
* Sorted first by frequency then by element name length then by element name (to ensure grouping).
*
* @author David Leston
*
* @type {import('./plugins-types').Plugin<'sortDefsChildren'>}
*/
sortDefsChildren$1.fn = () => {
return {
element: {
enter: (node) => {
if (node.name === 'defs') {
/**
* @type {Map<string, number>}
*/
const frequencies = new Map();
for (const child of node.children) {
if (child.type === 'element') {
const frequency = frequencies.get(child.name);
if (frequency == null) {
frequencies.set(child.name, 1);
} else {
frequencies.set(child.name, frequency + 1);
}
}
}
node.children.sort((a, b) => {
if (a.type !== 'element' || b.type !== 'element') {
return 0;
}
const aFrequency = frequencies.get(a.name);
const bFrequency = frequencies.get(b.name);
if (aFrequency != null && bFrequency != null) {
const frequencyComparison = bFrequency - aFrequency;
if (frequencyComparison !== 0) {
return frequencyComparison;
}
}
const lengthComparison = b.name.length - a.name.length;
if (lengthComparison !== 0) {
return lengthComparison;
}
if (a.name !== b.name) {
return a.name > b.name ? -1 : 1;
}
return 0;
});
}
},
},
};
};
var removeTitle$1 = {};
const { detachNodeFromParent: detachNodeFromParent$6 } = xast;
removeTitle$1.name = 'removeTitle';
removeTitle$1.description = 'removes <title>';
/**
* Remove <title>.
*
* https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title
*
* @author Igor Kalashnikov
*
* @type {import('./plugins-types').Plugin<'removeTitle'>}
*/
removeTitle$1.fn = () => {
return {
element: {
enter: (node, parentNode) => {
if (node.name === 'title') {
detachNodeFromParent$6(node, parentNode);
}
},
},
};
};
var removeDesc$1 = {};
const { detachNodeFromParent: detachNodeFromParent$5 } = xast;
removeDesc$1.name = 'removeDesc';
removeDesc$1.description = 'removes <desc>';
const standardDescs = /^(Created with|Created using)/;
/**
* Removes <desc>.
* Removes only standard editors content or empty elements 'cause it can be used for accessibility.
* Enable parameter 'removeAny' to remove any description.
*
* https://developer.mozilla.org/en-US/docs/Web/SVG/Element/desc
*
* @author Daniel Wabyick
*
* @type {import('./plugins-types').Plugin<'removeDesc'>}
*/
removeDesc$1.fn = (root, params) => {
const { removeAny = true } = params;
return {
element: {
enter: (node, parentNode) => {
if (node.name === 'desc') {
if (
removeAny ||
node.children.length === 0 ||
(node.children[0].type === 'text' &&
standardDescs.test(node.children[0].value))
) {
detachNodeFromParent$5(node, parentNode);
}
}
},
},
};
};
const { createPreset } = plugins;
const removeDoctype = removeDoctype$1;
const removeXMLProcInst = removeXMLProcInst$1;
const removeComments = removeComments$1;
const removeMetadata = removeMetadata$1;
const removeEditorsNSData = removeEditorsNSData$1;
const cleanupAttrs = cleanupAttrs$1;
const mergeStyles = mergeStyles$1;
const inlineStyles = inlineStyles$1;
const minifyStyles = minifyStyles$1;
const cleanupIds = cleanupIds$1;
const removeUselessDefs = removeUselessDefs$1;
const cleanupNumericValues = cleanupNumericValues$1;
const convertColors = convertColors$1;
const removeUnknownsAndDefaults = removeUnknownsAndDefaults$1;
const removeNonInheritableGroupAttrs = removeNonInheritableGroupAttrs$1;
const removeUselessStrokeAndFill = removeUselessStrokeAndFill$1;
const removeViewBox = removeViewBox$1;
const cleanupEnableBackground = cleanupEnableBackground$1;
const removeHiddenElems = removeHiddenElems$1;
const removeEmptyText = removeEmptyText$1;
const convertShapeToPath = convertShapeToPath$1;
const convertEllipseToCircle = convertEllipseToCircle$1;
const moveElemsAttrsToGroup = moveElemsAttrsToGroup$1;
const moveGroupAttrsToElems = moveGroupAttrsToElems$1;
const collapseGroups = collapseGroups$1;
const convertPathData = convertPathData$1;
const convertTransform = convertTransform$2;
const removeEmptyAttrs = removeEmptyAttrs$1;
const removeEmptyContainers = removeEmptyContainers$1;
const mergePaths = mergePaths$1;
const removeUnusedNS = removeUnusedNS$1;
const sortAttrs = sortAttrs$1;
const sortDefsChildren = sortDefsChildren$1;
const removeTitle = removeTitle$1;
const removeDesc = removeDesc$1;
const presetDefault = createPreset({
name: 'preset-default',
plugins: [
removeDoctype,
removeXMLProcInst,
removeComments,
removeMetadata,
removeEditorsNSData,
cleanupAttrs,
mergeStyles,
inlineStyles,
minifyStyles,
cleanupIds,
removeUselessDefs,
cleanupNumericValues,
convertColors,
removeUnknownsAndDefaults,
removeNonInheritableGroupAttrs,
removeUselessStrokeAndFill,
removeViewBox,
cleanupEnableBackground,
removeHiddenElems,
removeEmptyText,
convertShapeToPath,
convertEllipseToCircle,
moveElemsAttrsToGroup,
moveGroupAttrsToElems,
collapseGroups,
convertPathData,
convertTransform,
removeEmptyAttrs,
removeEmptyContainers,
mergePaths,
removeUnusedNS,
sortAttrs,
sortDefsChildren,
removeTitle,
removeDesc,
],
});
var presetDefault_1 = presetDefault;
var addAttributesToSVGElement = {};
addAttributesToSVGElement.name = 'addAttributesToSVGElement';
addAttributesToSVGElement.description = 'adds attributes to an outer <svg> element';
var ENOCLS$1 = `Error in plugin "addAttributesToSVGElement": absent parameters.
It should have a list of "attributes" or one "attribute".
Config example:
plugins: [
{
name: 'addAttributesToSVGElement',
params: {
attribute: "mySvg"
}
}
]
plugins: [
{
name: 'addAttributesToSVGElement',
params: {
attributes: ["mySvg", "size-big"]
}
}
]
plugins: [
{
name: 'addAttributesToSVGElement',
params: {
attributes: [
{
focusable: false
},
{
'data-image': icon
}
]
}
}
]
`;
/**
* Add attributes to an outer <svg> element. Example config:
*
* @author April Arcus
*
* @type {import('./plugins-types').Plugin<'addAttributesToSVGElement'>}
*/
addAttributesToSVGElement.fn = (root, params) => {
if (!Array.isArray(params.attributes) && !params.attribute) {
console.error(ENOCLS$1);
return null;
}
const attributes = params.attributes || [params.attribute];
return {
element: {
enter: (node, parentNode) => {
if (node.name === 'svg' && parentNode.type === 'root') {
for (const attribute of attributes) {
if (typeof attribute === 'string') {
if (node.attributes[attribute] == null) {
// @ts-ignore disallow explicit nullable attribute value
node.attributes[attribute] = undefined;
}
}
if (typeof attribute === 'object') {
for (const key of Object.keys(attribute)) {
if (node.attributes[key] == null) {
// @ts-ignore disallow explicit nullable attribute value
node.attributes[key] = attribute[key];
}
}
}
}
}
},
},
};
};
var addClassesToSVGElement = {};
addClassesToSVGElement.name = 'addClassesToSVGElement';
addClassesToSVGElement.description = 'adds classnames to an outer <svg> element';
var ENOCLS = `Error in plugin "addClassesToSVGElement": absent parameters.
It should have a list of classes in "classNames" or one "className".
Config example:
plugins: [
{
name: "addClassesToSVGElement",
params: {
className: "mySvg"
}
}
]
plugins: [
{
name: "addClassesToSVGElement",
params: {
classNames: ["mySvg", "size-big"]
}
}
]
`;
/**
* Add classnames to an outer <svg> element. Example config:
*
* plugins: [
* {
* name: "addClassesToSVGElement",
* params: {
* className: "mySvg"
* }
* }
* ]
*
* plugins: [
* {
* name: "addClassesToSVGElement",
* params: {
* classNames: ["mySvg", "size-big"]
* }
* }
* ]
*
* @author April Arcus
*
* @type {import('./plugins-types').Plugin<'addClassesToSVGElement'>}
*/
addClassesToSVGElement.fn = (root, params) => {
if (
!(Array.isArray(params.classNames) && params.classNames.some(String)) &&
!params.className
) {
console.error(ENOCLS);
return null;
}
const classNames = params.classNames || [params.className];
return {
element: {
enter: (node, parentNode) => {
if (node.name === 'svg' && parentNode.type === 'root') {
const classList = new Set(
node.attributes.class == null
? null
: node.attributes.class.split(' ')
);
for (const className of classNames) {
if (className != null) {
classList.add(className);
}
}
node.attributes.class = Array.from(classList).join(' ');
}
},
},
};
};
var cleanupListOfValues = {};
const { removeLeadingZero } = tools;
cleanupListOfValues.name = 'cleanupListOfValues';
cleanupListOfValues.description = 'rounds list of values to the fixed precision';
const regNumericValues =
/^([-+]?\d*\.?\d+([eE][-+]?\d+)?)(px|pt|pc|mm|cm|m|in|ft|em|ex|%)?$/;
const regSeparator = /\s+,?\s*|,\s*/;
const absoluteLengths = {
// relative to px
cm: 96 / 2.54,
mm: 96 / 25.4,
in: 96,
pt: 4 / 3,
pc: 16,
px: 1,
};
/**
* Round list of values to the fixed precision.
*
* @example
* <svg viewBox="0 0 200.28423 200.28423" enable-background="new 0 0 200.28423 200.28423">
* ⬇
* <svg viewBox="0 0 200.284 200.284" enable-background="new 0 0 200.284 200.284">
*
* <polygon points="208.250977 77.1308594 223.069336 ... "/>
* ⬇
* <polygon points="208.251 77.131 223.069 ... "/>
*
* @author kiyopikko
*
* @type {import('./plugins-types').Plugin<'cleanupListOfValues'>}
*/
cleanupListOfValues.fn = (_root, params) => {
const {
floatPrecision = 3,
leadingZero = true,
defaultPx = true,
convertToPx = true,
} = params;
/**
* @type {(lists: string) => string}
*/
const roundValues = (lists) => {
const roundedList = [];
for (const elem of lists.split(regSeparator)) {
const match = elem.match(regNumericValues);
const matchNew = elem.match(/new/);
// if attribute value matches regNumericValues
if (match) {
// round it to the fixed precision
let num = Number(Number(match[1]).toFixed(floatPrecision));
/**
* @type {any}
*/
let matchedUnit = match[3] || '';
/**
* @type{'' | keyof typeof absoluteLengths}
*/
let units = matchedUnit;
// convert absolute values to pixels
if (convertToPx && units && units in absoluteLengths) {
const pxNum = Number(
(absoluteLengths[units] * Number(match[1])).toFixed(floatPrecision)
);
if (pxNum.toString().length < match[0].length) {
num = pxNum;
units = 'px';
}
}
// and remove leading zero
let str;
if (leadingZero) {
str = removeLeadingZero(num);
} else {
str = num.toString();
}
// remove default 'px' units
if (defaultPx && units === 'px') {
units = '';
}
roundedList.push(str + units);
}
// if attribute value is "new"(only enable-background).
else if (matchNew) {
roundedList.push('new');
} else if (elem) {
roundedList.push(elem);
}
}
return roundedList.join(' ');
};
return {
element: {
enter: (node) => {
if (node.attributes.points != null) {
node.attributes.points = roundValues(node.attributes.points);
}
if (node.attributes['enable-background'] != null) {
node.attributes['enable-background'] = roundValues(
node.attributes['enable-background']
);
}
if (node.attributes.viewBox != null) {
node.attributes.viewBox = roundValues(node.attributes.viewBox);
}
if (node.attributes['stroke-dasharray'] != null) {
node.attributes['stroke-dasharray'] = roundValues(
node.attributes['stroke-dasharray']
);
}
if (node.attributes.dx != null) {
node.attributes.dx = roundValues(node.attributes.dx);
}
if (node.attributes.dy != null) {
node.attributes.dy = roundValues(node.attributes.dy);
}
if (node.attributes.x != null) {
node.attributes.x = roundValues(node.attributes.x);
}
if (node.attributes.y != null) {
node.attributes.y = roundValues(node.attributes.y);
}
},
},
};
};
var convertStyleToAttrs = {};
const { attrsGroups } = _collections;
convertStyleToAttrs.name = 'convertStyleToAttrs';
convertStyleToAttrs.description = 'converts style to attributes';
/**
* @type {(...args: string[]) => string}
*/
const g = (...args) => {
return '(?:' + args.join('|') + ')';
};
const stylingProps = attrsGroups.presentation;
const rEscape = '\\\\(?:[0-9a-f]{1,6}\\s?|\\r\\n|.)'; // Like \" or \2051. Code points consume one space.
const rAttr = '\\s*(' + g('[^:;\\\\]', rEscape) + '*?)\\s*'; // attribute name like fill
const rSingleQuotes = "'(?:[^'\\n\\r\\\\]|" + rEscape + ")*?(?:'|$)"; // string in single quotes: 'smth'
const rQuotes = '"(?:[^"\\n\\r\\\\]|' + rEscape + ')*?(?:"|$)'; // string in double quotes: "smth"
const rQuotedString = new RegExp('^' + g(rSingleQuotes, rQuotes) + '$');
// Parentheses, E.g.: url(data:image/png;base64,iVBO...).
// ':' and ';' inside of it should be threated as is. (Just like in strings.)
const rParenthesis =
'\\(' + g('[^\'"()\\\\]+', rEscape, rSingleQuotes, rQuotes) + '*?' + '\\)';
// The value. It can have strings and parentheses (see above). Fallbacks to anything in case of unexpected input.
const rValue =
'\\s*(' +
g(
'[^!\'"();\\\\]+?',
rEscape,
rSingleQuotes,
rQuotes,
rParenthesis,
'[^;]*?'
) +
'*?' +
')';
// End of declaration. Spaces outside of capturing groups help to do natural trimming.
const rDeclEnd = '\\s*(?:;\\s*|$)';
// Important rule
const rImportant = '(\\s*!important(?![-(\\w]))?';
// Final RegExp to parse CSS declarations.
const regDeclarationBlock = new RegExp(
rAttr + ':' + rValue + rImportant + rDeclEnd,
'ig'
);
// Comments expression. Honors escape sequences and strings.
const regStripComments = new RegExp(
g(rEscape, rSingleQuotes, rQuotes, '/\\*[^]*?\\*/'),
'ig'
);
/**
* Convert style in attributes. Cleanups comments and illegal declarations (without colon) as a side effect.
*
* @example
* <g style="fill:#000; color: #fff;">
* ⬇
* <g fill="#000" color="#fff">
*
* @example
* <g style="fill:#000; color: #fff; -webkit-blah: blah">
* ⬇
* <g fill="#000" color="#fff" style="-webkit-blah: blah">
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'convertStyleToAttrs'>}
*/
convertStyleToAttrs.fn = (_root, params) => {
const { keepImportant = false } = params;
return {
element: {
enter: (node) => {
if (node.attributes.style != null) {
// ['opacity: 1', 'color: #000']
let styles = [];
/**
* @type {Record<string, string>}
*/
const newAttributes = {};
// Strip CSS comments preserving escape sequences and strings.
const styleValue = node.attributes.style.replace(
regStripComments,
(match) => {
return match[0] == '/'
? ''
: match[0] == '\\' && /[-g-z]/i.test(match[1])
? match[1]
: match;
}
);
regDeclarationBlock.lastIndex = 0;
// eslint-disable-next-line no-cond-assign
for (var rule; (rule = regDeclarationBlock.exec(styleValue)); ) {
if (!keepImportant || !rule[3]) {
styles.push([rule[1], rule[2]]);
}
}
if (styles.length) {
styles = styles.filter(function (style) {
if (style[0]) {
var prop = style[0].toLowerCase(),
val = style[1];
if (rQuotedString.test(val)) {
val = val.slice(1, -1);
}
if (stylingProps.includes(prop)) {
newAttributes[prop] = val;
return false;
}
}
return true;
});
Object.assign(node.attributes, newAttributes);
if (styles.length) {
node.attributes.style = styles
.map((declaration) => declaration.join(':'))
.join(';');
} else {
delete node.attributes.style;
}
}
}
},
},
};
};
var prefixIds = {};
const csstree = cjs$2;
const { referencesProps } = _collections;
prefixIds.name = 'prefixIds';
prefixIds.description = 'prefix IDs';
/**
* extract basename from path
* @type {(path: string) => string}
*/
const getBasename = (path) => {
// extract everything after latest slash or backslash
const matched = path.match(/[/\\]?([^/\\]+)$/);
if (matched) {
return matched[1];
}
return '';
};
/**
* escapes a string for being used as ID
* @type {(string: string) => string}
*/
const escapeIdentifierName = (str) => {
return str.replace(/[. ]/g, '_');
};
/**
* @type {(string: string) => string}
*/
const unquote = (string) => {
if (
(string.startsWith('"') && string.endsWith('"')) ||
(string.startsWith("'") && string.endsWith("'"))
) {
return string.slice(1, -1);
}
return string;
};
/**
* prefix an ID
* @type {(prefix: string, name: string) => string}
*/
const prefixId = (prefix, value) => {
if (value.startsWith(prefix)) {
return value;
}
return prefix + value;
};
/**
* prefix an #ID
* @type {(prefix: string, name: string) => string | null}
*/
const prefixReference = (prefix, value) => {
if (value.startsWith('#')) {
return '#' + prefixId(prefix, value.slice(1));
}
return null;
};
/** @type {(value: any) => any} */
const toAny = (value) => value;
/**
* Prefixes identifiers
*
* @author strarsis <strarsis@gmail.com>
*
* @type {import('./plugins-types').Plugin<'prefixIds'>}
*/
prefixIds.fn = (_root, params, info) => {
const { delim = '__', prefixIds = true, prefixClassNames = true } = params;
return {
element: {
enter: (node) => {
/**
* prefix, from file name or option
* @type {string}
*/
let prefix = 'prefix' + delim;
if (typeof params.prefix === 'function') {
prefix = params.prefix(node, info) + delim;
} else if (typeof params.prefix === 'string') {
prefix = params.prefix + delim;
} else if (params.prefix === false) {
prefix = '';
} else if (info.path != null && info.path.length > 0) {
prefix = escapeIdentifierName(getBasename(info.path)) + delim;
}
// prefix id/class selectors and url() references in styles
if (node.name === 'style') {
// skip empty <style/> elements
if (node.children.length === 0) {
return;
}
// parse styles
let cssText = '';
if (
node.children[0].type === 'text' ||
node.children[0].type === 'cdata'
) {
cssText = node.children[0].value;
}
/**
* @type {null | csstree.CssNode}
*/
let cssAst = null;
try {
cssAst = csstree.parse(cssText, {
parseValue: true,
parseCustomProperty: false,
});
} catch {
return;
}
csstree.walk(cssAst, (node) => {
// #ID, .class selectors
if (
(prefixIds && node.type === 'IdSelector') ||
(prefixClassNames && node.type === 'ClassSelector')
) {
node.name = prefixId(prefix, node.name);
return;
}
// url(...) references
// csstree v2 changed this type
if (node.type === 'Url' && toAny(node.value).length > 0) {
const prefixed = prefixReference(
prefix,
unquote(toAny(node.value))
);
if (prefixed != null) {
toAny(node).value = prefixed;
}
}
});
// update styles
if (
node.children[0].type === 'text' ||
node.children[0].type === 'cdata'
) {
node.children[0].value = csstree.generate(cssAst);
}
return;
}
// prefix an ID attribute value
if (
prefixIds &&
node.attributes.id != null &&
node.attributes.id.length !== 0
) {
node.attributes.id = prefixId(prefix, node.attributes.id);
}
// prefix a class attribute value
if (
prefixClassNames &&
node.attributes.class != null &&
node.attributes.class.length !== 0
) {
node.attributes.class = node.attributes.class
.split(/\s+/)
.map((name) => prefixId(prefix, name))
.join(' ');
}
// prefix a href attribute value
// xlink:href is deprecated, must be still supported
for (const name of ['href', 'xlink:href']) {
if (
node.attributes[name] != null &&
node.attributes[name].length !== 0
) {
const prefixed = prefixReference(prefix, node.attributes[name]);
if (prefixed != null) {
node.attributes[name] = prefixed;
}
}
}
// prefix an URL attribute value
for (const name of referencesProps) {
if (
node.attributes[name] != null &&
node.attributes[name].length !== 0
) {
node.attributes[name] = node.attributes[name].replace(
/url\((.*?)\)/gi,
(match, url) => {
const prefixed = prefixReference(prefix, url);
if (prefixed == null) {
return match;
}
return `url(${prefixed})`;
}
);
}
}
// prefix begin/end attribute value
for (const name of ['begin', 'end']) {
if (
node.attributes[name] != null &&
node.attributes[name].length !== 0
) {
const parts = node.attributes[name].split(/\s*;\s+/).map((val) => {
if (val.endsWith('.end') || val.endsWith('.start')) {
const [id, postfix] = val.split('.');
return `${prefixId(prefix, id)}.${postfix}`;
}
return val;
});
node.attributes[name] = parts.join('; ');
}
}
},
},
};
};
var removeAttributesBySelector = {};
const { querySelectorAll } = xast;
removeAttributesBySelector.name = 'removeAttributesBySelector';
removeAttributesBySelector.description =
'removes attributes of elements that match a css selector';
/**
* Removes attributes of elements that match a css selector.
*
* @example
* <caption>A selector removing a single attribute</caption>
* plugins: [
* {
* name: "removeAttributesBySelector",
* params: {
* selector: "[fill='#00ff00']"
* attributes: "fill"
* }
* }
* ]
*
* <rect x="0" y="0" width="100" height="100" fill="#00ff00" stroke="#00ff00"/>
* ↓
* <rect x="0" y="0" width="100" height="100" stroke="#00ff00"/>
*
* <caption>A selector removing multiple attributes</caption>
* plugins: [
* {
* name: "removeAttributesBySelector",
* params: {
* selector: "[fill='#00ff00']",
* attributes: [
* "fill",
* "stroke"
* ]
* }
* }
* ]
*
* <rect x="0" y="0" width="100" height="100" fill="#00ff00" stroke="#00ff00"/>
* ↓
* <rect x="0" y="0" width="100" height="100"/>
*
* <caption>Multiple selectors removing attributes</caption>
* plugins: [
* {
* name: "removeAttributesBySelector",
* params: {
* selectors: [
* {
* selector: "[fill='#00ff00']",
* attributes: "fill"
* },
* {
* selector: "#remove",
* attributes: [
* "stroke",
* "id"
* ]
* }
* ]
* }
* }
* ]
*
* <rect x="0" y="0" width="100" height="100" fill="#00ff00" stroke="#00ff00"/>
* ↓
* <rect x="0" y="0" width="100" height="100"/>
*
* @link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors|MDN CSS Selectors
*
* @author Bradley Mease
*
* @type {import('./plugins-types').Plugin<'removeAttributesBySelector'>}
*/
removeAttributesBySelector.fn = (root, params) => {
const selectors = Array.isArray(params.selectors)
? params.selectors
: [params];
for (const { selector, attributes } of selectors) {
const nodes = querySelectorAll(root, selector);
for (const node of nodes) {
if (node.type === 'element') {
if (Array.isArray(attributes)) {
for (const name of attributes) {
delete node.attributes[name];
}
} else {
delete node.attributes[attributes];
}
}
}
}
return {};
};
var removeAttrs = {};
removeAttrs.name = 'removeAttrs';
removeAttrs.description = 'removes specified attributes';
const DEFAULT_SEPARATOR = ':';
const ENOATTRS = `Warning: The plugin "removeAttrs" requires the "attrs" parameter.
It should have a pattern to remove, otherwise the plugin is a noop.
Config example:
plugins: [
{
name: "removeAttrs",
params: {
attrs: "(fill|stroke)"
}
}
]
`;
/**
* Remove attributes
*
* @example elemSeparator
* format: string
*
* @example preserveCurrentColor
* format: boolean
*
* @example attrs:
*
* format: [ element* : attribute* : value* ]
*
* element : regexp (wrapped into ^...$), single * or omitted > all elements (must be present when value is used)
* attribute : regexp (wrapped into ^...$)
* value : regexp (wrapped into ^...$), single * or omitted > all values
*
* examples:
*
* > basic: remove fill attribute
* ---
* removeAttrs:
* attrs: 'fill'
*
* > remove fill attribute on path element
* ---
* attrs: 'path:fill'
*
* > remove fill attribute on path element where value is none
* ---
* attrs: 'path:fill:none'
*
*
* > remove all fill and stroke attribute
* ---
* attrs:
* - 'fill'
* - 'stroke'
*
* [is same as]
*
* attrs: '(fill|stroke)'
*
* [is same as]
*
* attrs: '*:(fill|stroke)'
*
* [is same as]
*
* attrs: '.*:(fill|stroke)'
*
* [is same as]
*
* attrs: '.*:(fill|stroke):.*'
*
*
* > remove all stroke related attributes
* ----
* attrs: 'stroke.*'
*
*
* @author Benny Schudel
*
* @type {import('./plugins-types').Plugin<'removeAttrs'>}
*/
removeAttrs.fn = (root, params) => {
if (typeof params.attrs == 'undefined') {
console.warn(ENOATTRS);
return null;
}
const elemSeparator =
typeof params.elemSeparator == 'string'
? params.elemSeparator
: DEFAULT_SEPARATOR;
const preserveCurrentColor =
typeof params.preserveCurrentColor == 'boolean'
? params.preserveCurrentColor
: false;
const attrs = Array.isArray(params.attrs) ? params.attrs : [params.attrs];
return {
element: {
enter: (node) => {
for (let pattern of attrs) {
// if no element separators (:), assume it's attribute name, and apply to all elements *regardless of value*
if (pattern.includes(elemSeparator) === false) {
pattern = ['.*', elemSeparator, pattern, elemSeparator, '.*'].join(
''
);
// if only 1 separator, assume it's element and attribute name, and apply regardless of attribute value
} else if (pattern.split(elemSeparator).length < 3) {
pattern = [pattern, elemSeparator, '.*'].join('');
}
// create regexps for element, attribute name, and attribute value
const list = pattern.split(elemSeparator).map((value) => {
// adjust single * to match anything
if (value === '*') {
value = '.*';
}
return new RegExp(['^', value, '$'].join(''), 'i');
});
// matches element
if (list[0].test(node.name)) {
// loop attributes
for (const [name, value] of Object.entries(node.attributes)) {
const isFillCurrentColor =
preserveCurrentColor &&
name == 'fill' &&
value == 'currentColor';
const isStrokeCurrentColor =
preserveCurrentColor &&
name == 'stroke' &&
value == 'currentColor';
if (
!isFillCurrentColor &&
!isStrokeCurrentColor &&
// matches attribute name
list[1].test(name) &&
// matches attribute value
list[2].test(value)
) {
delete node.attributes[name];
}
}
}
}
},
},
};
};
var removeDimensions = {};
removeDimensions.name = 'removeDimensions';
removeDimensions.description =
'removes width and height in presence of viewBox (opposite to removeViewBox, disable it first)';
/**
* Remove width/height attributes and add the viewBox attribute if it's missing
*
* @example
* <svg width="100" height="50" />
* ↓
* <svg viewBox="0 0 100 50" />
*
* @author Benny Schudel
*
* @type {import('./plugins-types').Plugin<'removeDimensions'>}
*/
removeDimensions.fn = () => {
return {
element: {
enter: (node) => {
if (node.name === 'svg') {
if (node.attributes.viewBox != null) {
delete node.attributes.width;
delete node.attributes.height;
} else if (
node.attributes.width != null &&
node.attributes.height != null &&
Number.isNaN(Number(node.attributes.width)) === false &&
Number.isNaN(Number(node.attributes.height)) === false
) {
const width = Number(node.attributes.width);
const height = Number(node.attributes.height);
node.attributes.viewBox = `0 0 ${width} ${height}`;
delete node.attributes.width;
delete node.attributes.height;
}
}
},
},
};
};
var removeElementsByAttr = {};
const { detachNodeFromParent: detachNodeFromParent$4 } = xast;
removeElementsByAttr.name = 'removeElementsByAttr';
removeElementsByAttr.description =
'removes arbitrary elements by ID or className (disabled by default)';
/**
* Remove arbitrary SVG elements by ID or className.
*
* @example id
* > single: remove element with ID of `elementID`
* ---
* removeElementsByAttr:
* id: 'elementID'
*
* > list: remove multiple elements by ID
* ---
* removeElementsByAttr:
* id:
* - 'elementID'
* - 'anotherID'
*
* @example class
* > single: remove all elements with class of `elementClass`
* ---
* removeElementsByAttr:
* class: 'elementClass'
*
* > list: remove all elements with class of `elementClass` or `anotherClass`
* ---
* removeElementsByAttr:
* class:
* - 'elementClass'
* - 'anotherClass'
*
* @author Eli Dupuis (@elidupuis)
*
* @type {import('./plugins-types').Plugin<'removeElementsByAttr'>}
*/
removeElementsByAttr.fn = (root, params) => {
const ids =
params.id == null ? [] : Array.isArray(params.id) ? params.id : [params.id];
const classes =
params.class == null
? []
: Array.isArray(params.class)
? params.class
: [params.class];
return {
element: {
enter: (node, parentNode) => {
// remove element if it's `id` matches configured `id` params
if (node.attributes.id != null && ids.length !== 0) {
if (ids.includes(node.attributes.id)) {
detachNodeFromParent$4(node, parentNode);
}
}
// remove element if it's `class` contains any of the configured `class` params
if (node.attributes.class && classes.length !== 0) {
const classList = node.attributes.class.split(' ');
for (const item of classes) {
if (classList.includes(item)) {
detachNodeFromParent$4(node, parentNode);
break;
}
}
}
},
},
};
};
var removeOffCanvasPaths = {};
/**
* @typedef {import('../lib/types').PathDataItem} PathDataItem
*/
const { visitSkip, detachNodeFromParent: detachNodeFromParent$3 } = xast;
const { parsePathData } = path;
const { intersects } = _path;
removeOffCanvasPaths.name = 'removeOffCanvasPaths';
removeOffCanvasPaths.description =
'removes elements that are drawn outside of the viewbox (disabled by default)';
/**
* Remove elements that are drawn outside of the viewbox.
*
* @author JoshyPHP
*
* @type {import('./plugins-types').Plugin<'removeOffCanvasPaths'>}
*/
removeOffCanvasPaths.fn = () => {
/**
* @type {null | {
* top: number,
* right: number,
* bottom: number,
* left: number,
* width: number,
* height: number
* }}
*/
let viewBoxData = null;
return {
element: {
enter: (node, parentNode) => {
if (node.name === 'svg' && parentNode.type === 'root') {
let viewBox = '';
// find viewbox
if (node.attributes.viewBox != null) {
// remove commas and plus signs, normalize and trim whitespace
viewBox = node.attributes.viewBox;
} else if (
node.attributes.height != null &&
node.attributes.width != null
) {
viewBox = `0 0 ${node.attributes.width} ${node.attributes.height}`;
}
// parse viewbox
// remove commas and plus signs, normalize and trim whitespace
viewBox = viewBox
.replace(/[,+]|px/g, ' ')
.replace(/\s+/g, ' ')
.replace(/^\s*|\s*$/g, '');
// ensure that the dimensions are 4 values separated by space
const m =
/^(-?\d*\.?\d+) (-?\d*\.?\d+) (\d*\.?\d+) (\d*\.?\d+)$/.exec(
viewBox
);
if (m == null) {
return;
}
const left = Number.parseFloat(m[1]);
const top = Number.parseFloat(m[2]);
const width = Number.parseFloat(m[3]);
const height = Number.parseFloat(m[4]);
// store the viewBox boundaries
viewBoxData = {
left,
top,
right: left + width,
bottom: top + height,
width,
height,
};
}
// consider that any item with a transform attribute is visible
if (node.attributes.transform != null) {
return visitSkip;
}
if (
node.name === 'path' &&
node.attributes.d != null &&
viewBoxData != null
) {
const pathData = parsePathData(node.attributes.d);
// consider that a M command within the viewBox is visible
let visible = false;
for (const pathDataItem of pathData) {
if (pathDataItem.command === 'M') {
const [x, y] = pathDataItem.args;
if (
x >= viewBoxData.left &&
x <= viewBoxData.right &&
y >= viewBoxData.top &&
y <= viewBoxData.bottom
) {
visible = true;
}
}
}
if (visible) {
return;
}
if (pathData.length === 2) {
// close the path too short for intersects()
pathData.push({ command: 'z', args: [] });
}
const { left, top, width, height } = viewBoxData;
/**
* @type {Array<PathDataItem>}
*/
const viewBoxPathData = [
{ command: 'M', args: [left, top] },
{ command: 'h', args: [width] },
{ command: 'v', args: [height] },
{ command: 'H', args: [left] },
{ command: 'z', args: [] },
];
if (intersects(viewBoxPathData, pathData) === false) {
detachNodeFromParent$3(node, parentNode);
}
}
},
},
};
};
var removeRasterImages = {};
const { detachNodeFromParent: detachNodeFromParent$2 } = xast;
removeRasterImages.name = 'removeRasterImages';
removeRasterImages.description = 'removes raster images (disabled by default)';
/**
* Remove raster images references in <image>.
*
* @see https://bugs.webkit.org/show_bug.cgi?id=63548
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'removeRasterImages'>}
*/
removeRasterImages.fn = () => {
return {
element: {
enter: (node, parentNode) => {
if (
node.name === 'image' &&
node.attributes['xlink:href'] != null &&
/(\.|image\/)(jpg|png|gif)/.test(node.attributes['xlink:href'])
) {
detachNodeFromParent$2(node, parentNode);
}
},
},
};
};
var removeScriptElement = {};
const { detachNodeFromParent: detachNodeFromParent$1 } = xast;
removeScriptElement.name = 'removeScriptElement';
removeScriptElement.description = 'removes <script> elements (disabled by default)';
/**
* Remove <script>.
*
* https://www.w3.org/TR/SVG11/script.html
*
* @author Patrick Klingemann
*
* @type {import('./plugins-types').Plugin<'removeScriptElement'>}
*/
removeScriptElement.fn = () => {
return {
element: {
enter: (node, parentNode) => {
if (node.name === 'script') {
detachNodeFromParent$1(node, parentNode);
}
},
},
};
};
var removeStyleElement = {};
const { detachNodeFromParent } = xast;
removeStyleElement.name = 'removeStyleElement';
removeStyleElement.description = 'removes <style> element (disabled by default)';
/**
* Remove <style>.
*
* https://www.w3.org/TR/SVG11/styling.html#StyleElement
*
* @author Betsy Dupuis
*
* @type {import('./plugins-types').Plugin<'removeStyleElement'>}
*/
removeStyleElement.fn = () => {
return {
element: {
enter: (node, parentNode) => {
if (node.name === 'style') {
detachNodeFromParent(node, parentNode);
}
},
},
};
};
var removeXMLNS = {};
removeXMLNS.name = 'removeXMLNS';
removeXMLNS.description =
'removes xmlns attribute (for inline svg, disabled by default)';
/**
* Remove the xmlns attribute when present.
*
* @example
* <svg viewBox="0 0 100 50" xmlns="http://www.w3.org/2000/svg">
* ↓
* <svg viewBox="0 0 100 50">
*
* @author Ricardo Tomasi
*
* @type {import('./plugins-types').Plugin<'removeXMLNS'>}
*/
removeXMLNS.fn = () => {
return {
element: {
enter: (node) => {
if (node.name === 'svg') {
delete node.attributes.xmlns;
delete node.attributes['xmlns:xlink'];
}
},
},
};
};
var reusePaths = {};
/**
* @typedef {import('../lib/types').XastElement} XastElement
* @typedef {import('../lib/types').XastParent} XastParent
* @typedef {import('../lib/types').XastNode} XastNode
*/
reusePaths.name = 'reusePaths';
reusePaths.description =
'Finds <path> elements with the same d, fill, and ' +
'stroke, and converts them to <use> elements ' +
'referencing a single <path> def.';
/**
* Finds <path> elements with the same d, fill, and stroke, and converts them to
* <use> elements referencing a single <path> def.
*
* @author Jacob Howcroft
*
* @type {import('./plugins-types').Plugin<'reusePaths'>}
*/
reusePaths.fn = () => {
/**
* @type {Map<string, Array<XastElement>>}
*/
const paths = new Map();
return {
element: {
enter: (node) => {
if (node.name === 'path' && node.attributes.d != null) {
const d = node.attributes.d;
const fill = node.attributes.fill || '';
const stroke = node.attributes.stroke || '';
const key = d + ';s:' + stroke + ';f:' + fill;
let list = paths.get(key);
if (list == null) {
list = [];
paths.set(key, list);
}
list.push(node);
}
},
exit: (node, parentNode) => {
if (node.name === 'svg' && parentNode.type === 'root') {
/**
* @type {XastElement}
*/
const defsTag = {
type: 'element',
name: 'defs',
attributes: {},
children: [],
};
// TODO remove legacy parentNode in v4
Object.defineProperty(defsTag, 'parentNode', {
writable: true,
value: node,
});
let index = 0;
for (const list of paths.values()) {
if (list.length > 1) {
// add reusable path to defs
/**
* @type {XastElement}
*/
const reusablePath = {
type: 'element',
name: 'path',
attributes: { ...list[0].attributes },
children: [],
};
delete reusablePath.attributes.transform;
let id;
if (reusablePath.attributes.id == null) {
id = 'reuse-' + index;
index += 1;
reusablePath.attributes.id = id;
} else {
id = reusablePath.attributes.id;
delete list[0].attributes.id;
}
// TODO remove legacy parentNode in v4
Object.defineProperty(reusablePath, 'parentNode', {
writable: true,
value: defsTag,
});
defsTag.children.push(reusablePath);
// convert paths to <use>
for (const pathNode of list) {
pathNode.name = 'use';
pathNode.attributes['xlink:href'] = '#' + id;
delete pathNode.attributes.d;
delete pathNode.attributes.stroke;
delete pathNode.attributes.fill;
}
}
}
if (defsTag.children.length !== 0) {
if (node.attributes['xmlns:xlink'] == null) {
node.attributes['xmlns:xlink'] = 'http://www.w3.org/1999/xlink';
}
node.children.unshift(defsTag);
}
}
},
},
};
};
builtin$1.builtin = [
presetDefault_1,
addAttributesToSVGElement,
addClassesToSVGElement,
cleanupAttrs$1,
cleanupEnableBackground$1,
cleanupIds$1,
cleanupListOfValues,
cleanupNumericValues$1,
collapseGroups$1,
convertColors$1,
convertEllipseToCircle$1,
convertPathData$1,
convertShapeToPath$1,
convertStyleToAttrs,
convertTransform$2,
mergeStyles$1,
inlineStyles$1,
mergePaths$1,
minifyStyles$1,
moveElemsAttrsToGroup$1,
moveGroupAttrsToElems$1,
prefixIds,
removeAttributesBySelector,
removeAttrs,
removeComments$1,
removeDesc$1,
removeDimensions,
removeDoctype$1,
removeEditorsNSData$1,
removeElementsByAttr,
removeEmptyAttrs$1,
removeEmptyContainers$1,
removeEmptyText$1,
removeHiddenElems$1,
removeMetadata$1,
removeNonInheritableGroupAttrs$1,
removeOffCanvasPaths,
removeRasterImages,
removeScriptElement,
removeStyleElement,
removeTitle$1,
removeUnknownsAndDefaults$1,
removeUnusedNS$1,
removeUselessDefs$1,
removeUselessStrokeAndFill$1,
removeViewBox$1,
removeXMLNS,
removeXMLProcInst$1,
reusePaths,
sortAttrs$1,
sortDefsChildren$1,
];
const { parseSvg } = parser$4;
const { stringifySvg } = stringifier;
const { builtin } = builtin$1;
const { invokePlugins } = plugins;
const { encodeSVGDatauri } = tools;
const pluginsMap = {};
for (const plugin of builtin) {
pluginsMap[plugin.name] = plugin;
}
const resolvePluginConfig = (plugin) => {
if (typeof plugin === 'string') {
// resolve builtin plugin specified as string
const builtinPlugin = pluginsMap[plugin];
if (builtinPlugin == null) {
throw Error(`Unknown builtin plugin "${plugin}" specified.`);
}
return {
name: plugin,
params: {},
fn: builtinPlugin.fn,
};
}
if (typeof plugin === 'object' && plugin != null) {
if (plugin.name == null) {
throw Error(`Plugin name should be specified`);
}
// use custom plugin implementation
let fn = plugin.fn;
if (fn == null) {
// resolve builtin plugin implementation
const builtinPlugin = pluginsMap[plugin.name];
if (builtinPlugin == null) {
throw Error(`Unknown builtin plugin "${plugin.name}" specified.`);
}
fn = builtinPlugin.fn;
}
return {
name: plugin.name,
params: plugin.params,
fn,
};
}
return null;
};
const optimize$1 = (input, config) => {
if (config == null) {
config = {};
}
if (typeof config !== 'object') {
throw Error('Config should be an object');
}
const maxPassCount = config.multipass ? 10 : 1;
let prevResultSize = Number.POSITIVE_INFINITY;
let output = '';
const info = {};
if (config.path != null) {
info.path = config.path;
}
for (let i = 0; i < maxPassCount; i += 1) {
info.multipassCount = i;
const ast = parseSvg(input, config.path);
const plugins = config.plugins || ['preset-default'];
if (Array.isArray(plugins) === false) {
throw Error(
"Invalid plugins list. Provided 'plugins' in config should be an array."
);
}
const resolvedPlugins = plugins.map(resolvePluginConfig);
const globalOverrides = {};
if (config.floatPrecision != null) {
globalOverrides.floatPrecision = config.floatPrecision;
}
invokePlugins(ast, info, resolvedPlugins, null, globalOverrides);
output = stringifySvg(ast, config.js2svg);
if (output.length < prevResultSize) {
input = output;
prevResultSize = output.length;
} else {
break;
}
}
if (config.datauri) {
output = encodeSVGDatauri(output, config.datauri);
}
return {
data: output,
};
};
svgo.optimize = optimize$1;
const os = require$$0$a;
const { optimize: optimizeAgnostic } = svgo;
const optimize = (input, config) => {
if (config == null) {
config = {};
}
if (typeof config !== 'object') {
throw Error('Config should be an object');
}
return optimizeAgnostic(input, {
...config,
js2svg: {
// platform specific default for end of line
eol: os.EOL === '\r\n' ? 'crlf' : 'lf',
...config.js2svg,
},
});
};
var optimize_1 = optimize;
const splitAttrsTokenizer = /([a-z0-9_\:\-]*)\s*?=\s*?(['"]?)(.*?)\2\s+/gim;
const domParserTokenizer = /(?:<(\/?)([a-zA-Z][a-zA-Z0-9\:]*)(?:\s([^>]*?))?((?:\s*\/)?)>|(<\!\-\-)([\s\S]*?)(\-\->)|(<\!\[CDATA\[)([\s\S]*?)(\]\]>))/gm;
const splitAttrs = (str) => {
let res = {};
let token;
if (str) {
splitAttrsTokenizer.lastIndex = 0;
str = " " + (str || "") + " ";
while (token = splitAttrsTokenizer.exec(str)) {
res[token[1]] = token[3];
}
}
return res;
};
function optimizeSvg(contents, name, options) {
return optimize_1(contents, {
plugins: [
"removeDoctype",
"removeXMLProcInst",
"removeComments",
"removeMetadata",
"removeXMLNS",
"removeEditorsNSData",
"cleanupAttrs",
"minifyStyles",
"convertStyleToAttrs",
"cleanupIds",
{
name: "prefixIds",
params: { prefix: `${SPRITESHEET_NAMESPACE}:${name}` }
},
"removeRasterImages",
"removeUselessDefs",
"cleanupNumericValues",
"cleanupListOfValues",
"convertColors",
"removeUnknownsAndDefaults",
"removeNonInheritableGroupAttrs",
"removeUselessStrokeAndFill",
"removeViewBox",
"cleanupEnableBackground",
"removeHiddenElems",
"removeEmptyText",
"convertShapeToPath",
"moveElemsAttrsToGroup",
"moveGroupAttrsToElems",
"collapseGroups",
"convertPathData",
"convertTransform",
"removeEmptyAttrs",
"removeEmptyContainers",
"mergePaths",
"removeUnusedNS",
"sortAttrs",
"removeTitle",
"removeDesc",
"removeDimensions",
"removeStyleElement",
"removeScriptElement"
]
}).data;
}
const preprocessCache = /* @__PURE__ */ new Map();
function preprocess(contents, name, { optimize }) {
if (preprocessCache.has(contents)) {
return preprocessCache.get(contents);
}
if (optimize) {
contents = optimizeSvg(contents, name);
}
domParserTokenizer.lastIndex = 0;
let result = contents;
let token;
if (contents) {
while (token = domParserTokenizer.exec(contents)) {
const tag = token[2];
if (tag === "svg") {
const attrs = splitAttrs(token[3]);
result = contents.slice(domParserTokenizer.lastIndex).replace(/<\/svg>/gim, "").trim();
const value = { innerHTML: result, defaultProps: attrs };
preprocessCache.set(contents, value);
return value;
}
}
}
}
function normalizeProps(inputProps) {
const size = inputProps.size;
delete inputProps.size;
const w = inputProps.width ?? size;
const h = inputProps.height ?? size;
const width = w ? toAttributeSize(w) : void 0;
const height = h ? toAttributeSize(h) : void 0;
return { ...inputProps, width, height };
}
const toAttributeSize = (size) => String(size).replace(/(?<=[0-9])x$/, "em");
async function load(name, inputProps, optimize) {
const key = name;
if (!name) {
throw new Error("<Icon> requires a name!");
}
let svg = "";
let filepath = "";
if (name.includes(":")) {
const [pack, ..._name] = name.split(":");
name = _name.join(":");
filepath = `/src/icons/${pack}`;
let get$1;
try {
const files = /* #__PURE__ */ Object.assign({
});
const keys = Object.fromEntries(
Object.keys(files).map((key2) => [key2.replace(/\.[cm]?[jt]s$/, ""), key2])
);
if (!(filepath in keys)) {
throw new Error(`Could not find the file "${filepath}"`);
}
const mod = files[keys[filepath]];
if (typeof mod.default !== "function") {
throw new Error(
`[astro-icon] "${filepath}" did not export a default function!`
);
}
get$1 = mod.default;
} catch (e) {
}
if (typeof get$1 === "undefined") {
get$1 = get.bind(null, pack);
}
const contents = await get$1(name, inputProps);
if (!contents) {
throw new Error(
`<Icon pack="${pack}" name="${name}" /> did not return an icon!`
);
}
if (!/<svg/gim.test(contents)) {
throw new Error(
`Unable to process "<Icon pack="${pack}" name="${name}" />" because an SVG string was not returned!
Recieved the following content:
${contents}`
);
}
svg = contents;
} else {
filepath = `/src/icons/${name}.svg`;
try {
const files = /* #__PURE__ */ Object.assign({"/src/icons/logomark.svg": __vite_glob_1_0,"/src/icons/theme/dark.svg": __vite_glob_1_1,"/src/icons/theme/light.svg": __vite_glob_1_2,"/src/icons/wordmark.svg": __vite_glob_1_3});
if (!(filepath in files)) {
throw new Error(`Could not find the file "${filepath}"`);
}
const contents = files[filepath];
if (!/<svg/gim.test(contents)) {
throw new Error(
`Unable to process "${filepath}" because it is not an SVG!
Recieved the following content:
${contents}`
);
}
svg = contents;
} catch (e) {
throw new Error(
`[astro-icon] Unable to load "${filepath}". Does the file exist?`
);
}
}
const { innerHTML, defaultProps } = preprocess(svg, key, { optimize });
if (!innerHTML.trim()) {
throw new Error(`Unable to parse "${filepath}"!`);
}
return {
innerHTML,
props: { ...defaultProps, ...normalizeProps(inputProps) }
};
}
const $$Astro$8 = createAstro("https://astro-reactive.dev");
const $$Icon = createComponent(async ($$result, $$props, $$slots) => {
const Astro2 = $$result.createAstro($$Astro$8, $$props, $$slots);
Astro2.self = $$Icon;
let { name, pack, title, optimize = true, class: className, ...inputProps } = Astro2.props;
let props = {};
if (pack) {
name = `${pack}:${name}`;
}
let innerHTML = "";
try {
const svg = await load(name, { ...inputProps, class: className }, optimize);
innerHTML = svg.innerHTML;
props = svg.props;
} catch (e) {
{
throw new Error(`[astro-icon] Unable to load icon "${name}"!
${e}`);
}
}
return renderTemplate`${maybeRenderHead()}<svg${spreadAttributes(props)}${addAttribute(name, "astro-icon")}>${unescapeHTML((title ? `<title>${title}</title>` : "") + innerHTML)}</svg>`;
}, "/Users/ayoayco/Projects/@astro-reactive/astro-reactive/node_modules/astro-iconify/lib/Icon.astro", void 0);
const sprites = /* @__PURE__ */ new WeakMap();
function trackSprite(request, name) {
let currentSet = sprites.get(request);
if (!currentSet) {
currentSet = /* @__PURE__ */ new Set([name]);
} else {
currentSet.add(name);
}
sprites.set(request, currentSet);
}
const warned = /* @__PURE__ */ new Set();
async function getUsedSprites(request) {
const currentSet = sprites.get(request);
if (currentSet) {
return Array.from(currentSet);
}
if (!warned.has(request)) {
const { pathname } = new URL(request.url);
console.log(`[astro-icon] No sprites found while rendering "${pathname}"`);
warned.add(request);
}
return [];
}
const $$Astro$7 = createAstro("https://astro-reactive.dev");
const $$Spritesheet = createComponent(async ($$result, $$props, $$slots) => {
const Astro2 = $$result.createAstro($$Astro$7, $$props, $$slots);
Astro2.self = $$Spritesheet;
const { optimize = true, style, ...props } = Astro2.props;
const names = await getUsedSprites(Astro2.request);
const icons = await Promise.all(names.map((name) => {
return load(name, {}, optimize).then((res) => ({ ...res, name })).catch((e) => {
{
throw new Error(`[astro-icon] Unable to load icon "${name}"!
${e}`);
}
});
}));
return renderTemplate`${maybeRenderHead()}<svg${addAttribute(`position: absolute; width: 0; height: 0; overflow: hidden; ${style ?? ""}`.trim(), "style")}${spreadAttributes({ "aria-hidden": true, ...props })} astro-icon-spritesheet>${icons.map((icon) => renderTemplate`<symbol${spreadAttributes(icon.props)}${addAttribute(`${SPRITESHEET_NAMESPACE}:${icon.name}`, "id")}>${unescapeHTML(icon.innerHTML)}</symbol>`)}</svg>`;
}, "/Users/ayoayco/Projects/@astro-reactive/astro-reactive/node_modules/astro-iconify/lib/Spritesheet.astro", void 0);
const $$Astro$6 = createAstro("https://astro-reactive.dev");
const $$SpriteProvider = createComponent(async ($$result, $$props, $$slots) => {
const Astro2 = $$result.createAstro($$Astro$6, $$props, $$slots);
Astro2.self = $$SpriteProvider;
const content = await Astro2.slots.render("default");
return renderTemplate`${renderComponent($$result, "Fragment", Fragment, {}, { "default": ($$result2) => renderTemplate`${unescapeHTML(content)}` })}${renderComponent($$result, "Spritesheet", $$Spritesheet, {})}`;
}, "/Users/ayoayco/Projects/@astro-reactive/astro-reactive/node_modules/astro-iconify/lib/SpriteProvider.astro", void 0);
const $$Astro$5 = createAstro("https://astro-reactive.dev");
const $$Sprite = createComponent(async ($$result, $$props, $$slots) => {
const Astro2 = $$result.createAstro($$Astro$5, $$props, $$slots);
Astro2.self = $$Sprite;
let { name, pack, title, class: className, x, y, ...inputProps } = Astro2.props;
const props = normalizeProps(inputProps);
if (pack) {
name = `${pack}:${name}`;
}
const href = `#${SPRITESHEET_NAMESPACE}:${name}`;
trackSprite(Astro2.request, name);
return renderTemplate`${maybeRenderHead()}<svg${spreadAttributes(props)}${addAttribute(className, "class")}${addAttribute(name, "astro-icon")}>${title ? renderTemplate`<title>${title}</title>` : ""}<use${spreadAttributes({ "xlink:href": href, width: props.width, height: props.height, x, y })}></use></svg>`;
}, "/Users/ayoayco/Projects/@astro-reactive/astro-reactive/node_modules/astro-iconify/lib/Sprite.astro", void 0);
Object.assign($$Sprite, { Provider: $$SpriteProvider });
const $$Astro$4 = createAstro("https://astro-reactive.dev");
const $$Header = createComponent(async ($$result, $$props, $$slots) => {
const Astro2 = $$result.createAstro($$Astro$4, $$props, $$slots);
Astro2.self = $$Header;
const socials = [
{
name: "GitHub",
url: "https://github.com/astro-reactive/astro-reactive",
icon: "fa-brands:github-alt"
},
{
name: "Discord",
url: "https://discord.gg/kkvW7GYNAp",
icon: "fa-brands:discord"
}
];
return renderTemplate`${maybeRenderHead()}<header id="page-header" class="absolute bottom-0 z-10 flex items-center justify-between w-full px-8 py-4 text-white border-b border-transparent" data-astro-cid-hpnw4vwy><div class="flex items-center gap-3 hover:!text-default" data-astro-cid-hpnw4vwy><!-- <h1 class="text-">Astro Reactive</h1> --></div><div data-astro-cid-hpnw4vwy><div class="flex items-center gap-6" data-astro-cid-hpnw4vwy><ul class="flex gap-4" data-astro-cid-hpnw4vwy>${socials.map((social) => renderTemplate`<li class="list-none" data-astro-cid-hpnw4vwy><a class="flex items-center justify-center w-12 h-12 p-3 border-2 border-current rounded-full"${addAttribute(social.url, "href")} data-astro-cid-hpnw4vwy>${renderComponent($$result, "Icon", $$Icon, { "name": social.icon, "class": "h-full", "data-astro-cid-hpnw4vwy": true })}</a></li>`)}</ul><!-- <button
id="open-nav-button"
type="button"
class="btn sm:hidden"
aria-label="Navigation"
>
<Icon pack="mdi" name="menu" class="h-8" />
</button>
<ThemeSwitcher /--></div><div id="menu-modal" class="hidden modal" aria-hidden="true" data-astro-cid-hpnw4vwy><div class="fixed inset-0 px-8 py-4 bg-default text-default" data-astro-cid-hpnw4vwy><div class="space-y-4" role="dialog" aria-modal="true" data-astro-cid-hpnw4vwy><header class="text-right" data-astro-cid-hpnw4vwy><button id="close-nav-button" type="button" class="btn" aria-label="Close navigation" data-astro-cid-hpnw4vwy>${renderComponent($$result, "Icon", $$Icon, { "pack": "mdi", "name": "close", "class": "h-8", "data-astro-cid-hpnw4vwy": true })}</button></header><div class="flex justify-center" data-astro-cid-hpnw4vwy>${renderComponent($$result, "Icon", $$Icon, { "name": "logomark", "class": "h-16", "data-astro-cid-hpnw4vwy": true })}</div></div></div></div></div></header><noscript><style>
#open-nav-button {
display: none;
}
</style></noscript>`;
}, "/Users/ayoayco/Projects/@astro-reactive/astro-reactive/apps/landing-page/src/components/header.astro", void 0);
const $$Astro$3 = createAstro("https://astro-reactive.dev");
const $$Copynpm = createComponent(async ($$result, $$props, $$slots) => {
const Astro2 = $$result.createAstro($$Astro$3, $$props, $$slots);
Astro2.self = $$Copynpm;
return renderTemplate`${maybeRenderHead()}<div id="toast-success" class="items-center p-4 mb-4 w-full max-w-xs text-gray-500 bg-white rounded-lg shadow dark:text-gray-400 dark:bg-gray-800 flex transition" role="alert" data-astro-cid-wriaavej><div class="inline-flex flex-shrink-0 justify-center items-center w-8 h-8 text-green-500 bg-green-100 rounded-lg dark:bg-green-800 dark:text-green-200" data-astro-cid-wriaavej><svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" data-astro-cid-wriaavej><path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" data-astro-cid-wriaavej></path></svg><span class="sr-only" data-astro-cid-wriaavej>Check icon</span></div><div class="ml-3 text-sm font-normal" data-astro-cid-wriaavej>Copied to clipboard!</div><button type="button" class="ml-auto -mx-1.5 -my-1.5 bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-2 focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex h-8 w-8 dark:text-gray-500 dark:hover:text-white dark:bg-gray-800 dark:hover:bg-gray-700" id="toast-close-btn" aria-label="Close" data-astro-cid-wriaavej><span class="sr-only" data-astro-cid-wriaavej>Close</span><svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" data-astro-cid-wriaavej><path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" data-astro-cid-wriaavej></path></svg></button></div><button class="copy-btn flex items-center w-4/5 mt-3 justify-center max-w-xs astro-md:w-1/2 astro-lg:w-sm astro-lg:mt-0 astro-lg:ml-3" id="copy-command-button" data-astro-cid-wriaavej><span id="command" data-astro-cid-wriaavej>&gt; npm install @astro-reactive/form</span>${renderComponent($$result, "Icon", $$Icon, { "name": "mdi:content-copy", "width": "30px", "height": "30px", "data-astro-cid-wriaavej": true })}</button>`;
}, "/Users/ayoayco/Projects/@astro-reactive/astro-reactive/apps/landing-page/src/components/copynpm.astro", void 0);
const $$Astro$2 = createAstro("https://astro-reactive.dev");
const $$Splash = createComponent(async ($$result, $$props, $$slots) => {
const Astro2 = $$result.createAstro($$Astro$2, $$props, $$slots);
Astro2.self = $$Splash;
return renderTemplate`${maybeRenderHead()}<section class="h-screen flex flex-col astro relative" data-astro-cid-3egmgwtg><div class="relative flex flex-col-reverse justify-end h-full content-center grid pt-0" data-astro-cid-3egmgwtg><div class="flex flex-col w-screen p-8" data-astro-cid-3egmgwtg><h2 class="flex flex-col items-center gap-2" data-astro-cid-3egmgwtg><div class="font-extrabold tracking-tighter text-center text-8xl gradient-text" data-astro-cid-3egmgwtg>
Astro. Reactive.
</div></h2><div class="mt-8 flex justify-center flex-col items-center astro-lg:flex-row astro-lg:justify-center" data-astro-cid-3egmgwtg><a href="https://docs.astro-reactive.dev/en/api/form/form-component/" class="flex items-center w-4/5 astro-md:w-1/2 justify-center bg-blue-500 hover:bg-blue-400 hover:text-white text-white font-bold py-2 px-4 border-b-4 border-blue-700 hover:border-blue-500 rounded transition-colors astro-lg:w-auto" data-astro-cid-3egmgwtg><span class="pr-2" data-astro-cid-3egmgwtg>Get Started</span>${renderComponent($$result, "Icon", $$Icon, { "name": "mdi:arrow-right", "width": "20px", "height": "20px", "data-astro-cid-3egmgwtg": true })}</a>${renderComponent($$result, "Copynpm", $$Copynpm, { "data-astro-cid-3egmgwtg": true })}</div></div></div></section>`;
}, "/Users/ayoayco/Projects/@astro-reactive/astro-reactive/apps/landing-page/src/components/splash.astro", void 0);
const $$Astro$1 = createAstro("https://astro-reactive.dev");
const $$Starfield = createComponent(async ($$result, $$props, $$slots) => {
const Astro2 = $$result.createAstro($$Astro$1, $$props, $$slots);
Astro2.self = $$Starfield;
return renderTemplate`${maybeRenderHead()}<div id="starfield" class="absolute -z-10 inset-0"><canvas id="starfield-canvas"></canvas></div>`;
}, "/Users/ayoayco/Projects/@astro-reactive/astro-reactive/apps/landing-page/src/components/starfield.astro", void 0);
var __freeze = Object.freeze;
var __defProp = Object.defineProperty;
var __template = (cooked, raw) => __freeze(__defProp(cooked, "raw", { value: __freeze(raw || cooked.slice()) }));
var _a;
const $$Astro = createAstro("https://astro-reactive.dev");
const $$Index = createComponent(async ($$result, $$props, $$slots) => {
const Astro2 = $$result.createAstro($$Astro, $$props, $$slots);
Astro2.self = $$Index;
const { site } = Astro2;
const image = new URL("social.jpg", site);
const description = "Library of components and utilities for building reactive user interfaces with Astro";
return renderTemplate(_a || (_a = __template(['<html lang="en" class="h-full motion-safe:scroll-smooth" data-theme="dark"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width"><link rel="icon" href="/favicon.ico" sizes="any"><title>Astro Reactive | ', ' \u{1F680}</title><meta name="description"', `><!-- fonts --><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link rel="preload" as="style" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;800&display=swap"><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;800&display=swap" media="print" onload="th
is.media=' a ll'">`, '<noscript><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;800&display=swap"></noscript><!-- social media --><meta property="og:title" content="Astro"><meta property="og:type" content="website"><meta property="og:description"', '><meta property="og:image"', '><meta property="og:url"', `><meta name="twitter:card" content="summary_large_image"><!-- initialize theme --><script>
document.documentElement.dataset.theme = 'dark';
// const themeSaved = localStorage.getItem("theme");
// const forceTheme = "dark";
// if (themeSaved) {
// document.documentElement.dataset.theme = themeSaved;
// } else {
// // const prefersDark = window.matchMedia(
// // "(prefers-color-scheme: dark)"
// // ).matches;
// document.documentElement.dataset.theme = forceTheme; // prefersDark ? "dark" : "light";
// }
// window
// .matchMedia("(prefers-color-scheme: dark)")
// ?.addEventListener("change", (event) => {
// if (!localStorage.getItem("theme")) {
// document.documentElement.dataset.theme = event.matches
// ? "dark"
// : "light";
// }
// });
<\/script>`, '</head><body class="h-full overflow-x-hidden text-base bg-default text-default selection:bg-secondary selection:text-white">', "", "", "<!--AstroSection /--></body></html>"])), description, addAttribute(description, "content"), maybeRenderHead(), addAttribute(description, "content"), addAttribute(image, "content"), addAttribute(site, "content"), renderHead(), renderComponent($$result, "Starfield", $$Starfield, {}), renderComponent($$result, "Header", $$Header, {}), renderComponent($$result, "Splash", $$Splash, {}));
}, "/Users/ayoayco/Projects/@astro-reactive/astro-reactive/apps/landing-page/src/pages/index.astro", void 0);
const $$file = "/Users/ayoayco/Projects/@astro-reactive/astro-reactive/apps/landing-page/src/pages/index.astro";
const $$url = "";
export { $$Index as default, $$file as file, $$url as url };