sheetom 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4,9 +4,9 @@ import { fileURLToPath } from "node:url";
4
4
  //#endregion
5
5
  //#region src/internal/engine-binding.ts
6
6
  const expectedEngineAbiIdentity = Object.freeze({
7
- abiVersion: 3,
8
- sheetomVersion: "0.1.0",
9
- syntaxEngineSetSha256: "31990c26ede4e17c3a8941027f92b2be96a167984d0ab6529e724c3d6126be50"
7
+ abiVersion: 5,
8
+ sheetomVersion: "0.2.0",
9
+ syntaxEngineSetSha256: "954d76058dc35ad2a5c85e41fd66e35d308856e554c93563e7eee8a4704d4b70"
10
10
  });
11
11
  var SheetOMEngineBindingError = class extends Error {
12
12
  code;
@@ -41,7 +41,7 @@ function loadBinding() {
41
41
  validateEngineBindingIdentity(addon);
42
42
  return {
43
43
  ...addon,
44
- createDeclarationState: (context, ...budget) => new addon.NativeDeclarationState(context, ...budget)
44
+ createDeclarationState: (context, ...arguments_) => new addon.NativeDeclarationState(context, ...arguments_)
45
45
  };
46
46
  }
47
47
  //#endregion
@@ -128,11 +128,16 @@ var NativeDeclarationBlock = class {
128
128
  #reservedNestingDepth;
129
129
  #observableCache;
130
130
  #serializationCache = /* @__PURE__ */ new Map();
131
- constructor(reportDiagnostic, reportSerializationDiagnostic, context = "style", resourceBudget = defaultResourceBudget, reservedNestingDepth = () => 0) {
131
+ constructor(reportDiagnostic, reportSerializationDiagnostic, context = "style", resourceBudget = defaultResourceBudget, reservedNestingDepth = () => 0, initialCssText) {
132
132
  this.#reportDiagnostic = reportDiagnostic;
133
133
  this.#reportSerializationDiagnostic = reportSerializationDiagnostic;
134
134
  this.#reservedNestingDepth = reservedNestingDepth;
135
- this.#state = engineBinding.createDeclarationState(context, ...nativeBudgetArguments(resourceBudget));
135
+ try {
136
+ this.#state = engineBinding.createDeclarationState(context, ...nativeBudgetArguments(resourceBudget), initialCssText);
137
+ } catch (error) {
138
+ rethrowResourceBudgetError(error);
139
+ throw error;
140
+ }
136
141
  }
137
142
  get cssText() {
138
143
  this.#observableCache ??= this.#state.cssText;
@@ -351,8 +356,8 @@ function isNativeRuleDescription(value) {
351
356
  }
352
357
  //#endregion
353
358
  //#region src/internal/native-rule-syntax.ts
354
- function normalizeNativeSelector(source, resourceBudget = defaultResourceBudget) {
355
- return callNative(() => engineBinding.normalizeSelector(source, ...nativeBudgetArguments(resourceBudget)));
359
+ function normalizeNativeSelector(source, resourceBudget = defaultResourceBudget, namespaces = "") {
360
+ return callNative(() => engineBinding.normalizeSelector(source, namespaces, ...nativeBudgetArguments(resourceBudget)));
356
361
  }
357
362
  function normalizeNativeMedia(source, resourceBudget = defaultResourceBudget) {
358
363
  return callNative(() => engineBinding.normalizeMedia(source, ...nativeBudgetArguments(resourceBudget)));
@@ -391,6 +396,9 @@ function callNative(operation) {
391
396
  return null;
392
397
  }
393
398
  }
399
+ function supportsNativeCss(source, value) {
400
+ return engineBinding.supportsCss(source, value);
401
+ }
394
402
  //#endregion
395
403
  //#region src/internal/rule-tree.ts
396
404
  /** Owns child-list identity and parent propagation for every live rule node. */
@@ -570,6 +578,39 @@ function assertInternalConstructor(name) {
570
578
  }
571
579
  //#endregion
572
580
  //#region src/index.ts
581
+ /** CSS authoring utilities, without installing or replacing the global CSS namespace. */
582
+ const CSS = {
583
+ /** Serialize a DOMString as a CSS identifier, including lone UTF-16 surrogates. */
584
+ escape(value) {
585
+ requireArguments(arguments.length, 1, "CSS", "escape");
586
+ const input = `${value}`;
587
+ let output = "";
588
+ for (let index = 0; index < input.length; index += 1) {
589
+ const code = input.charCodeAt(index);
590
+ const character = input[index];
591
+ if (code === 0) output += "�";
592
+ else if (code <= 31 || code === 127 || code >= 48 && code <= 57 && (index === 0 || index === 1 && input[0] === "-")) output += `\\${code.toString(16)} `;
593
+ else if (input === "-") output += "\\-";
594
+ else if (code >= 128 || /[a-zA-Z0-9_-]/u.test(character)) output += character;
595
+ else output += `\\${character}`;
596
+ }
597
+ return output;
598
+ },
599
+ /** Test a declaration or supports condition against the pinned authoring capabilities. */
600
+ supports(propertyOrCondition, value) {
601
+ requireArguments(arguments.length, 1, "CSS", "supports");
602
+ try {
603
+ return arguments.length > 1 ? supportsNativeCss(`${propertyOrCondition}`, `${value}`) : supportsNativeCss(`${propertyOrCondition}`);
604
+ } catch (error) {
605
+ rethrowResourceBudgetError(error);
606
+ throw error;
607
+ }
608
+ }
609
+ };
610
+ Object.defineProperty(CSS, Symbol.toStringTag, {
611
+ value: "CSS",
612
+ configurable: true
613
+ });
573
614
  const arrayIndexPattern = /^(0|[1-9]\d*)$/;
574
615
  const regularSheetMetadata = /* @__PURE__ */ new WeakMap();
575
616
  const ruleParentage = /* @__PURE__ */ new WeakMap();
@@ -577,7 +618,19 @@ const ruleResourceBudgets = /* @__PURE__ */ new WeakMap();
577
618
  const sheetResourceBudgets = /* @__PURE__ */ new WeakMap();
578
619
  const sheetRuleArrays = /* @__PURE__ */ new WeakMap();
579
620
  const sheetRuleCounts = /* @__PURE__ */ new WeakMap();
621
+ const sheetNamespaces = /* @__PURE__ */ new WeakMap();
622
+ function namespaceText(sheet) {
623
+ if (!sheet) return "";
624
+ return sheetNamespaces.get(sheet) ?? "";
625
+ }
626
+ function namespaceRulesText(rules) {
627
+ return rules.filter((rule) => rule instanceof CSSNamespaceRule).map((rule) => rule.cssText).join("");
628
+ }
629
+ function permitsNamespaceMutation(rules) {
630
+ return rules.every((rule) => rule instanceof CSSNamespaceRule || rule instanceof CSSImportRule);
631
+ }
580
632
  const functionRuleHeaders = /* @__PURE__ */ new WeakMap();
633
+ const mixinRuleHeaders = /* @__PURE__ */ new WeakMap();
581
634
  const unsignedLongRange = 2 ** 32;
582
635
  const pageMarginRuleNames = /* @__PURE__ */ new Set([
583
636
  "top-left-corner",
@@ -598,6 +651,7 @@ const pageMarginRuleNames = /* @__PURE__ */ new Set([
598
651
  "left-top"
599
652
  ]);
600
653
  const ignoreDiagnostic = () => {};
654
+ const normalizedSelectorText = Symbol("normalizedSelectorText");
601
655
  const ruleDiagnostics = /* @__PURE__ */ new WeakMap();
602
656
  const ruleTree = new RuleTree((rule, parentRule, parentStyleSheet) => {
603
657
  ruleParentage.set(rule, {
@@ -629,8 +683,8 @@ function namedPropertyToCSS(property) {
629
683
  if (/^(webkit|moz|ms|o)-/.test(cssName)) cssName = `-${cssName}`;
630
684
  return cssName;
631
685
  }
632
- function normalizeSelectorText(value, resourceBudget = defaultResourceBudget) {
633
- return normalizeNativeSelector(value, resourceBudget);
686
+ function normalizeSelectorText(value, resourceBudget = defaultResourceBudget, namespaces = "") {
687
+ return normalizeNativeSelector(value, resourceBudget, namespaces);
634
688
  }
635
689
  function toUnsignedLong(value) {
636
690
  const number = Number(value);
@@ -1022,6 +1076,112 @@ var CSSFunctionRule = class extends CSSGroupingRule {
1022
1076
  }
1023
1077
  set cssText(_value) {}
1024
1078
  };
1079
+ /** Experimental revision-pinned native CSS mixin definition. */
1080
+ var CSSMixinRule = class extends CSSGroupingRule {
1081
+ name;
1082
+ contents = true;
1083
+ #parameters;
1084
+ constructor(name, parameters) {
1085
+ super(0);
1086
+ this.name = serializeNativeIdentifier(name);
1087
+ this.#parameters = parameters.map((parameter) => ({ ...parameter }));
1088
+ const header = serializeFunctionHeader(name, parameters, "*").replace(/^@function /u, "@mixin ");
1089
+ mixinRuleHeaders.set(this, parameters.length === 0 ? header.slice(0, -2) : header);
1090
+ lockOwnProperties(this, "name", "contents");
1091
+ }
1092
+ getParameters() {
1093
+ return this.#parameters.map((parameter) => ({ ...parameter }));
1094
+ }
1095
+ get cssText() {
1096
+ return serializeMixinCssText(this);
1097
+ }
1098
+ set cssText(_value) {}
1099
+ };
1100
+ /** Experimental native CSS mixin application with a contents block. */
1101
+ var CSSApplyBlockRule = class extends CSSGroupingRule {
1102
+ name;
1103
+ #arguments;
1104
+ constructor(name, args, header) {
1105
+ super(0);
1106
+ this.name = serializeNativeIdentifier(name);
1107
+ this.#arguments = [...args];
1108
+ mixinRuleHeaders.set(this, header);
1109
+ lockOwnProperties(this, "name");
1110
+ }
1111
+ getArguments() {
1112
+ return [...this.#arguments];
1113
+ }
1114
+ get cssText() {
1115
+ return serializeMixinCssText(this);
1116
+ }
1117
+ set cssText(_value) {}
1118
+ };
1119
+ /** Experimental native CSS mixin application without a contents block. */
1120
+ var CSSApplyStatementRule = class extends CSSRule {
1121
+ name;
1122
+ #arguments;
1123
+ #header;
1124
+ constructor(name, args, header) {
1125
+ super(0);
1126
+ this.name = serializeNativeIdentifier(name);
1127
+ this.#arguments = [...args];
1128
+ this.#header = header;
1129
+ lockOwnProperties(this, "name");
1130
+ }
1131
+ getArguments() {
1132
+ return [...this.#arguments];
1133
+ }
1134
+ get cssText() {
1135
+ return `${this.#header};`;
1136
+ }
1137
+ set cssText(_value) {}
1138
+ };
1139
+ /** Experimental native CSS mixin contents placeholder with a fallback block. */
1140
+ var CSSContentsBlockRule = class extends CSSGroupingRule {
1141
+ constructor() {
1142
+ super(0);
1143
+ mixinRuleHeaders.set(this, "@contents");
1144
+ }
1145
+ get cssText() {
1146
+ return serializeMixinCssText(this);
1147
+ }
1148
+ set cssText(_value) {}
1149
+ };
1150
+ /** Experimental native CSS mixin contents placeholder without a fallback. */
1151
+ var CSSContentsStatementRule = class extends CSSRule {
1152
+ constructor() {
1153
+ super(0);
1154
+ }
1155
+ get cssText() {
1156
+ return "@contents;";
1157
+ }
1158
+ set cssText(_value) {}
1159
+ };
1160
+ function serializeMixinCssText(root) {
1161
+ const chunks = [];
1162
+ const pending = [root];
1163
+ while (pending.length > 0) {
1164
+ const item = pending.pop();
1165
+ if (typeof item === "string") {
1166
+ chunks.push(item);
1167
+ continue;
1168
+ }
1169
+ if (!(item instanceof CSSGroupingRule)) {
1170
+ chunks.push(item.cssText);
1171
+ continue;
1172
+ }
1173
+ const header = groupingRuleHeader(item);
1174
+ chunks.push(header, item instanceof CSSMixinRule ? "{ " : " { ");
1175
+ pending.push(" }");
1176
+ const children = ruleTree.children(item);
1177
+ for (let index = children.length - 1; index >= 0; index -= 1) {
1178
+ pending.push(children[index]);
1179
+ if (index > 0) pending.push(" ");
1180
+ }
1181
+ if (item instanceof CSSStyleRule && item.style.cssText !== "") pending.push(children.length ? `${item.style.cssText} ` : item.style.cssText);
1182
+ }
1183
+ return chunks.join("");
1184
+ }
1025
1185
  function serializeFunctionHeader(name, parameters, returnType) {
1026
1186
  const serializedParameters = parameters.map((parameter) => {
1027
1187
  const type = serializeFunctionType(parameter.type);
@@ -1254,7 +1414,7 @@ var CSSViewTransitionRule = class extends CSSRule {
1254
1414
  var CSSStyleDeclaration = class {
1255
1415
  parentRule;
1256
1416
  #block;
1257
- constructor(parentRule) {
1417
+ constructor(parentRule, initialCssText) {
1258
1418
  assertInternalConstructor("CSSStyleDeclaration");
1259
1419
  this.parentRule = parentRule;
1260
1420
  lockOwnProperties(this, "parentRule");
@@ -1284,7 +1444,7 @@ var CSSStyleDeclaration = class {
1284
1444
  };
1285
1445
  (ruleDiagnostics.get(this.parentRule) ?? ignoreDiagnostic)(diagnostic);
1286
1446
  };
1287
- this.#block = new NativeDeclarationBlock(reportDeclarationDiagnostic, reportSerializationDiagnostic, parentRule instanceof CSSFontFaceRule ? "font-face" : parentRule instanceof CSSFunctionDeclarations ? "function" : "style", ruleResourceBudgets.get(parentRule) ?? defaultResourceBudget, () => declarationSerializationDepth(parentRule));
1447
+ this.#block = new NativeDeclarationBlock(reportDeclarationDiagnostic, reportSerializationDiagnostic, parentRule instanceof CSSFontFaceRule ? "font-face" : parentRule instanceof CSSPositionTryRule ? "position-try" : parentRule instanceof CSSFunctionDeclarations ? "function" : "style", ruleResourceBudgets.get(parentRule) ?? defaultResourceBudget, () => declarationSerializationDepth(parentRule), initialCssText);
1288
1448
  return new Proxy(this, {
1289
1449
  get(target, property) {
1290
1450
  if (typeof property === "string" && arrayIndexPattern.test(property)) return target.item(Number(property)) || void 0;
@@ -1369,9 +1529,9 @@ var CSSStyleDeclaration = class {
1369
1529
  /** A live `@font-face` descriptor rule. */
1370
1530
  var CSSFontFaceRule = class extends CSSRule {
1371
1531
  style;
1372
- constructor() {
1532
+ constructor(initialCssText) {
1373
1533
  super(CSSRule.FONT_FACE_RULE);
1374
- this.style = constructWebIDL(CSSStyleDeclaration, [this]);
1534
+ this.style = constructWebIDL(CSSStyleDeclaration, [this, initialCssText]);
1375
1535
  lockOwnProperties(this, "style");
1376
1536
  }
1377
1537
  get cssText() {
@@ -1382,9 +1542,9 @@ var CSSFontFaceRule = class extends CSSRule {
1382
1542
  /** Declarations ordered after a nested style rule. */
1383
1543
  var CSSNestedDeclarations = class extends CSSRule {
1384
1544
  #style;
1385
- constructor() {
1545
+ constructor(initialCssText) {
1386
1546
  super(0);
1387
- this.#style = constructWebIDL(CSSStyleDeclaration, [this]);
1547
+ this.#style = constructWebIDL(CSSStyleDeclaration, [this, initialCssText]);
1388
1548
  }
1389
1549
  get style() {
1390
1550
  return this.#style;
@@ -1400,9 +1560,9 @@ var CSSNestedDeclarations = class extends CSSRule {
1400
1560
  /** A run of live descriptors inside a custom function. */
1401
1561
  var CSSFunctionDeclarations = class extends CSSRule {
1402
1562
  #style;
1403
- constructor() {
1563
+ constructor(initialCssText) {
1404
1564
  super(0);
1405
- this.#style = constructWebIDL(CSSFunctionDescriptors, [this]);
1565
+ this.#style = constructWebIDL(CSSFunctionDescriptors, [this, initialCssText]);
1406
1566
  }
1407
1567
  get style() {
1408
1568
  return this.#style;
@@ -1426,10 +1586,10 @@ var CSSFunctionDescriptors = class extends CSSStyleDeclaration {
1426
1586
  var CSSMarginRule = class extends CSSRule {
1427
1587
  name;
1428
1588
  style;
1429
- constructor(name) {
1589
+ constructor(name, initialCssText) {
1430
1590
  super(CSSRule.MARGIN_RULE);
1431
1591
  this.name = name;
1432
- this.style = constructWebIDL(CSSStyleDeclaration, [this]);
1592
+ this.style = constructWebIDL(CSSStyleDeclaration, [this, initialCssText]);
1433
1593
  lockOwnProperties(this, "name", "style");
1434
1594
  }
1435
1595
  get cssText() {
@@ -1441,10 +1601,10 @@ var CSSMarginRule = class extends CSSRule {
1441
1601
  var CSSPageRule = class extends CSSGroupingRule {
1442
1602
  style;
1443
1603
  #selectorText;
1444
- constructor(selectorText) {
1604
+ constructor(selectorText, initialCssText) {
1445
1605
  super(CSSRule.PAGE_RULE);
1446
1606
  this.#selectorText = selectorText;
1447
- this.style = constructWebIDL(CSSStyleDeclaration, [this]);
1607
+ this.style = constructWebIDL(CSSStyleDeclaration, [this, initialCssText]);
1448
1608
  lockOwnProperties(this, "style");
1449
1609
  }
1450
1610
  get selectorText() {
@@ -1461,15 +1621,76 @@ var CSSPageRule = class extends CSSGroupingRule {
1461
1621
  }
1462
1622
  set cssText(_value) {}
1463
1623
  };
1464
- /** A live `@position-try` declaration rule. */
1624
+ /** The allowed descriptors of an anchor positioning fallback rule. */
1625
+ var CSSPositionTryDescriptors = class extends CSSStyleDeclaration {};
1626
+ for (const name of [
1627
+ "margin",
1628
+ "margin-top",
1629
+ "margin-right",
1630
+ "margin-bottom",
1631
+ "margin-left",
1632
+ "margin-block",
1633
+ "margin-block-start",
1634
+ "margin-block-end",
1635
+ "margin-inline",
1636
+ "margin-inline-start",
1637
+ "margin-inline-end",
1638
+ "inset",
1639
+ "top",
1640
+ "right",
1641
+ "bottom",
1642
+ "left",
1643
+ "inset-block",
1644
+ "inset-block-start",
1645
+ "inset-block-end",
1646
+ "inset-inline",
1647
+ "inset-inline-start",
1648
+ "inset-inline-end",
1649
+ "width",
1650
+ "min-width",
1651
+ "max-width",
1652
+ "height",
1653
+ "min-height",
1654
+ "max-height",
1655
+ "block-size",
1656
+ "min-block-size",
1657
+ "max-block-size",
1658
+ "inline-size",
1659
+ "min-inline-size",
1660
+ "max-inline-size",
1661
+ "place-self",
1662
+ "align-self",
1663
+ "justify-self",
1664
+ "position-anchor",
1665
+ "position-area"
1666
+ ]) {
1667
+ const camelCase = name.replace(/-([a-z])/gu, (_match, letter) => letter.toUpperCase());
1668
+ for (const accessor of /* @__PURE__ */ new Set([name, camelCase])) Object.defineProperty(CSSPositionTryDescriptors.prototype, accessor, {
1669
+ configurable: true,
1670
+ enumerable: true,
1671
+ get() {
1672
+ return this.getPropertyValue(name);
1673
+ },
1674
+ set(value) {
1675
+ this.setProperty(name, value);
1676
+ }
1677
+ });
1678
+ }
1679
+ /** A named anchor positioning fallback rule. */
1465
1680
  var CSSPositionTryRule = class extends CSSRule {
1466
1681
  name;
1467
- style;
1468
- constructor(name) {
1682
+ #style;
1683
+ constructor(name, initialCssText) {
1469
1684
  super(0);
1470
1685
  this.name = name;
1471
- this.style = constructWebIDL(CSSStyleDeclaration, [this]);
1472
- lockOwnProperties(this, "name", "style");
1686
+ this.#style = constructWebIDL(CSSPositionTryDescriptors, [this, initialCssText]);
1687
+ lockOwnProperties(this, "name");
1688
+ }
1689
+ get style() {
1690
+ return this.#style;
1691
+ }
1692
+ set style(cssText) {
1693
+ this.#style.cssText = `${cssText}`;
1473
1694
  }
1474
1695
  get cssText() {
1475
1696
  return `@position-try ${this.name} {${this.style.cssText === "" ? "" : ` ${this.style.cssText}`} }`;
@@ -1502,10 +1723,10 @@ function normalizeKeyText(value) {
1502
1723
  var CSSKeyframeRule = class extends CSSRule {
1503
1724
  style;
1504
1725
  #keyText;
1505
- constructor(keyText) {
1726
+ constructor(keyText, initialCssText) {
1506
1727
  super(CSSRule.KEYFRAME_RULE);
1507
1728
  this.#keyText = normalizeKeyText(keyText) ?? keyText;
1508
- this.style = constructWebIDL(CSSStyleDeclaration, [this]);
1729
+ this.style = constructWebIDL(CSSStyleDeclaration, [this, initialCssText]);
1509
1730
  lockOwnProperties(this, "style");
1510
1731
  }
1511
1732
  get keyText() {
@@ -1816,17 +2037,20 @@ var CSSFontFeatureValuesRule = class extends CSSRule {
1816
2037
  var CSSStyleRule = class extends CSSGroupingRule {
1817
2038
  style;
1818
2039
  #selectorText;
1819
- constructor(selectorText) {
2040
+ #namespaces() {
2041
+ return namespaceText(this.parentStyleSheet);
2042
+ }
2043
+ constructor(selectorText, normalized, initialCssText) {
1820
2044
  super(CSSRule.STYLE_RULE);
1821
- this.#selectorText = normalizeSelectorText(`${selectorText}`, currentConstructionResourceBudget()) ?? `${selectorText}`;
1822
- this.style = constructWebIDL(CSSStyleDeclaration, [this]);
2045
+ this.#selectorText = normalized === normalizedSelectorText ? selectorText : normalizeSelectorText(`${selectorText}`, currentConstructionResourceBudget()) ?? `${selectorText}`;
2046
+ this.style = constructWebIDL(CSSStyleDeclaration, [this, initialCssText]);
1823
2047
  lockOwnProperties(this, "style");
1824
2048
  }
1825
2049
  get selectorText() {
1826
2050
  return this.#selectorText;
1827
2051
  }
1828
2052
  set selectorText(value) {
1829
- const normalized = normalizeSelectorText(`${value}`, ruleResourceBudgets.get(this) ?? defaultResourceBudget);
2053
+ const normalized = normalizeSelectorText(`${value}`, ruleResourceBudgets.get(this) ?? defaultResourceBudget, this.#namespaces());
1830
2054
  if (normalized === null) return;
1831
2055
  this.#selectorText = normalized;
1832
2056
  }
@@ -1882,17 +2106,24 @@ function describeRuleSafe(rule, strict) {
1882
2106
  declarations: rule.style.serializeSafe(" ", strict),
1883
2107
  children: ruleTree.children(rule)
1884
2108
  };
2109
+ if (rule instanceof CSSApplyStatementRule && rule.getArguments().length === 1 && rule.getArguments()[0] === "") return {
2110
+ kind: "raw",
2111
+ cssText: `@apply ${rule.name}({ });`
2112
+ };
1885
2113
  if (!(rule instanceof CSSGroupingRule)) return {
1886
2114
  kind: "raw",
1887
2115
  cssText: rule.cssText
1888
2116
  };
1889
2117
  return {
1890
2118
  kind: "block",
1891
- header: groupingRuleHeader(rule),
2119
+ header: rule instanceof CSSApplyBlockRule && rule.getArguments().length === 1 && rule.getArguments()[0] === "" ? `@apply ${rule.name}({ })` : groupingRuleHeader(rule),
1892
2120
  children: ruleTree.children(rule)
1893
2121
  };
1894
2122
  }
1895
2123
  function groupingRuleHeader(rule) {
2124
+ const mixinHeader = mixinRuleHeaders.get(rule);
2125
+ if (mixinHeader !== void 0) return mixinHeader;
2126
+ if (rule instanceof CSSStyleRule) return rule.selectorText;
1896
2127
  if (rule instanceof CSSFunctionRule) return functionRuleHeaders.get(rule) ?? "@function";
1897
2128
  if (rule instanceof CSSMediaRule) return `@media ${rule.media.mediaText}`;
1898
2129
  if (rule instanceof CSSSupportsRule) return `@supports ${rule.conditionText}`;
@@ -1944,12 +2175,13 @@ function parseImportPrelude(prelude) {
1944
2175
  supports
1945
2176
  };
1946
2177
  }
1947
- function createRuleFromNative(description, reportDiagnostic, preserveImports, resourceBudget) {
1948
- return constructWithResourceBudget(() => createRuleTreeFromNative(description, reportDiagnostic, preserveImports, resourceBudget), resourceBudget);
2178
+ function createRuleFromNative(description, reportDiagnostic, preserveImports, resourceBudget, parentRule = null) {
2179
+ return constructWithResourceBudget(() => createRuleTreeFromNative(description, reportDiagnostic, preserveImports, resourceBudget, parentRule), resourceBudget);
1949
2180
  }
1950
- function createRuleTreeFromNative(description, reportDiagnostic, preserveImports, resourceBudget) {
2181
+ function createRuleTreeFromNative(description, reportDiagnostic, preserveImports, resourceBudget, parentRule) {
1951
2182
  const root = createRuleShellFromNative(description, reportDiagnostic, preserveImports, resourceBudget);
1952
2183
  if (!root) return null;
2184
+ attachRuleTree(root, parentRule, parentRule?.parentStyleSheet ?? null);
1953
2185
  const pending = [{
1954
2186
  description,
1955
2187
  rule: root
@@ -1961,9 +2193,10 @@ function createRuleTreeFromNative(description, reportDiagnostic, preserveImports
1961
2193
  const childFrames = [];
1962
2194
  for (const childDescription of current.description.children) {
1963
2195
  if (isNativeMetadataRule(childDescription)) continue;
2196
+ if (!isMixinContextAllowed(childDescription.kind, current.rule)) continue;
1964
2197
  const child = createRuleShellFromNative(childDescription, reportDiagnostic, preserveImports, resourceBudget);
1965
2198
  if (!child) continue;
1966
- if (child instanceof CSSFunctionDeclarations && child.style.length === 0) continue;
2199
+ if ((child instanceof CSSFunctionDeclarations || child instanceof CSSNestedDeclarations) && child.style.length === 0) continue;
1967
2200
  if (current.rule instanceof CSSKeyframesRule && !(child instanceof CSSKeyframeRule)) continue;
1968
2201
  children.push(child);
1969
2202
  childFrames.push({
@@ -1981,29 +2214,24 @@ function createRuleTreeFromNative(description, reportDiagnostic, preserveImports
1981
2214
  return root;
1982
2215
  }
1983
2216
  function isNativeMetadataRule(description) {
1984
- return description.kind === "function-parameter" || description.kind === "property-descriptor" || description.kind === "view-transition-type" || description.kind === "layer-name";
2217
+ return description.kind === "function-parameter" || description.kind === "mixin-argument" || description.kind === "property-descriptor" || description.kind === "view-transition-type" || description.kind === "layer-name";
1985
2218
  }
1986
2219
  function createRuleShellFromNative(description, reportDiagnostic, preserveImports, resourceBudget) {
1987
2220
  let rule;
1988
2221
  switch (description.kind) {
1989
- case "style": {
1990
- const style = constructWebIDL(CSSStyleRule, [description.prelude]);
1991
- style.style.cssText = description.declarations;
1992
- rule = style;
2222
+ case "style":
2223
+ rule = constructWebIDL(CSSStyleRule, [
2224
+ description.prelude,
2225
+ normalizedSelectorText,
2226
+ description.declarations
2227
+ ]);
1993
2228
  break;
1994
- }
1995
- case "nested-declarations": {
1996
- const nested = constructWebIDL(CSSNestedDeclarations);
1997
- nested.style.cssText = description.declarations;
1998
- rule = nested;
2229
+ case "nested-declarations":
2230
+ rule = constructWebIDL(CSSNestedDeclarations, [description.declarations]);
1999
2231
  break;
2000
- }
2001
- case "function-declarations": {
2002
- const declarations = constructWebIDL(CSSFunctionDeclarations);
2003
- declarations.style.cssText = description.declarations;
2004
- rule = declarations;
2232
+ case "function-declarations":
2233
+ rule = constructWebIDL(CSSFunctionDeclarations, [description.declarations]);
2005
2234
  break;
2006
- }
2007
2235
  case "import": {
2008
2236
  if (!preserveImports) return null;
2009
2237
  const parsed = parseImportPrelude(description.cssText.replace(/^@import\s+/iu, "").replace(/;\s*$/u, ""));
@@ -2016,39 +2244,24 @@ function createRuleShellFromNative(description, reportDiagnostic, preserveImport
2016
2244
  ]);
2017
2245
  break;
2018
2246
  }
2019
- case "font-face": {
2020
- const fontFace = constructWebIDL(CSSFontFaceRule);
2021
- fontFace.style.cssText = description.declarations;
2022
- rule = fontFace;
2247
+ case "font-face":
2248
+ rule = constructWebIDL(CSSFontFaceRule, [description.declarations]);
2023
2249
  break;
2024
- }
2025
- case "page": {
2026
- const page = constructWebIDL(CSSPageRule, [description.prelude]);
2027
- page.style.cssText = description.declarations;
2028
- rule = page;
2250
+ case "page":
2251
+ rule = constructWebIDL(CSSPageRule, [description.prelude, description.declarations]);
2029
2252
  break;
2030
- }
2031
- case "margin": {
2032
- const margin = constructWebIDL(CSSMarginRule, [description.prelude]);
2033
- margin.style.cssText = description.declarations;
2034
- rule = margin;
2253
+ case "margin":
2254
+ rule = constructWebIDL(CSSMarginRule, [description.prelude, description.declarations]);
2035
2255
  break;
2036
- }
2037
- case "position-try": {
2038
- const positionTry = constructWebIDL(CSSPositionTryRule, [description.prelude]);
2039
- positionTry.style.cssText = description.declarations;
2040
- rule = positionTry;
2256
+ case "position-try":
2257
+ rule = constructWebIDL(CSSPositionTryRule, [description.prelude, description.declarations]);
2041
2258
  break;
2042
- }
2043
2259
  case "keyframes":
2044
2260
  rule = constructWebIDL(CSSKeyframesRule, [description.prelude]);
2045
2261
  break;
2046
- case "keyframe": {
2047
- const keyframe = constructWebIDL(CSSKeyframeRule, [description.prelude]);
2048
- keyframe.style.cssText = description.declarations;
2049
- rule = keyframe;
2262
+ case "keyframe":
2263
+ rule = constructWebIDL(CSSKeyframeRule, [description.prelude, description.declarations]);
2050
2264
  break;
2051
- }
2052
2265
  case "counter-style": {
2053
2266
  const counterStyle = constructWebIDL(CSSCounterStyleRule, [description.prelude]);
2054
2267
  hydrateCounterStyleDescriptors(counterStyle, description.declarations, resourceBudget);
@@ -2089,7 +2302,8 @@ function createRuleShellFromNative(description, reportDiagnostic, preserveImport
2089
2302
  description.children.filter((candidate) => candidate.kind === "view-transition-type").map((candidate) => candidate.prelude),
2090
2303
  description.cssText
2091
2304
  ]);
2092
- case "function": {
2305
+ case "function":
2306
+ case "mixin": {
2093
2307
  const parameters = description.children.filter((candidate) => candidate.kind === "function-parameter").map((candidate) => {
2094
2308
  const defaultValue = candidate.children.find((child) => child.kind === "property-descriptor" && child.prelude === "default-value");
2095
2309
  return defaultValue ? {
@@ -2101,13 +2315,35 @@ function createRuleShellFromNative(description, reportDiagnostic, preserveImport
2101
2315
  type: candidate.declarations
2102
2316
  };
2103
2317
  });
2104
- rule = constructWebIDL(CSSFunctionRule, [
2318
+ rule = description.kind === "mixin" ? constructWebIDL(CSSMixinRule, [description.prelude, parameters]) : constructWebIDL(CSSFunctionRule, [
2105
2319
  description.prelude,
2106
2320
  parameters,
2107
2321
  description.declarations
2108
2322
  ]);
2109
2323
  break;
2110
2324
  }
2325
+ case "apply-block":
2326
+ case "apply-statement": {
2327
+ const arguments_ = description.children.filter((child) => child.kind === "mixin-argument");
2328
+ const args = arguments_.map((argument) => argument.declarations);
2329
+ const header = `@apply ${serializeNativeIdentifier(description.prelude)}${args.length ? `(${arguments_.map((argument) => argument.cssText).join(", ")})` : ""}`;
2330
+ rule = description.kind === "apply-block" ? constructWebIDL(CSSApplyBlockRule, [
2331
+ description.prelude,
2332
+ args,
2333
+ header
2334
+ ]) : constructWebIDL(CSSApplyStatementRule, [
2335
+ description.prelude,
2336
+ args,
2337
+ header
2338
+ ]);
2339
+ break;
2340
+ }
2341
+ case "contents-block":
2342
+ rule = constructWebIDL(CSSContentsBlockRule);
2343
+ break;
2344
+ case "contents-statement":
2345
+ rule = constructWebIDL(CSSContentsStatementRule);
2346
+ break;
2111
2347
  case "namespace": return constructWebIDL(CSSNamespaceRule, [
2112
2348
  nativeRuleDescriptor(description, "namespace-uri"),
2113
2349
  nativeRuleDescriptor(description, "prefix"),
@@ -2145,7 +2381,7 @@ function nativeRuleDescriptor(description, name) {
2145
2381
  function hydrateCounterStyleDescriptors(rule, declarations, resourceBudget) {
2146
2382
  for (const descriptor of parseNativeCounterStyleDescriptors(declarations, resourceBudget)) rule.setParsedDescriptor(descriptor.name, descriptor.value);
2147
2383
  }
2148
- function parseStrictRule(ruleText, reportDiagnostic, preserveImports = false, parentRule = null, resourceBudget = defaultResourceBudget) {
2384
+ function parseStrictRule(ruleText, reportDiagnostic, preserveImports = false, parentRule = null, resourceBudget = defaultResourceBudget, namespaces = namespaceText(parentRule?.parentStyleSheet ?? null)) {
2149
2385
  if (parentRule instanceof CSSPageRule) {
2150
2386
  const page = parseNativeRule(`@page { ${ruleText} }`, resourceBudget);
2151
2387
  if (page?.kind !== "page" || page.children.length !== 1) return null;
@@ -2155,7 +2391,41 @@ function parseStrictRule(ruleText, reportDiagnostic, preserveImports = false, pa
2155
2391
  }
2156
2392
  const description = parseNativeRule(ruleText, resourceBudget) ?? (parentRule && hasFunctionAncestor(parentRule) ? parseNativeRuleWithErrorRecovery(ruleText, resourceBudget) : null);
2157
2393
  if (!description || description.kind === "import" && !preserveImports) return null;
2158
- return createRuleFromNative(description, reportDiagnostic, preserveImports, resourceBudget);
2394
+ if (!isMixinContextAllowed(description.kind, parentRule)) return null;
2395
+ const validSelector = (rule) => {
2396
+ if (rule.kind !== "style" || !rule.prelude.includes("|")) return true;
2397
+ const normalized = normalizeNativeSelector(rule.prelude, resourceBudget, namespaces);
2398
+ if (normalized === null) return false;
2399
+ rule.prelude = normalized;
2400
+ return true;
2401
+ };
2402
+ if (!validSelector(description)) return null;
2403
+ const pending = [description];
2404
+ while (pending.length) {
2405
+ const current = pending.pop();
2406
+ current.children = current.children.filter(validSelector);
2407
+ for (const child of current.children) pending.push(child);
2408
+ }
2409
+ return createRuleFromNative(description, reportDiagnostic, preserveImports, resourceBudget, parentRule);
2410
+ }
2411
+ function isMixinContextAllowed(kind, parent) {
2412
+ if (![
2413
+ "mixin",
2414
+ "apply-block",
2415
+ "apply-statement",
2416
+ "contents-block",
2417
+ "contents-statement",
2418
+ "private"
2419
+ ].includes(kind)) return true;
2420
+ let nested = false;
2421
+ let mixin = false;
2422
+ for (let current = parent; current; current = current.parentRule) {
2423
+ if (current instanceof CSSFunctionRule) return false;
2424
+ if (current instanceof CSSStyleRule || current instanceof CSSMixinRule) nested = true;
2425
+ if (current instanceof CSSMixinRule) mixin = true;
2426
+ }
2427
+ if (kind === "mixin") return !nested;
2428
+ return kind.startsWith("contents-") ? mixin : nested;
2159
2429
  }
2160
2430
  function hasFunctionAncestor(rule) {
2161
2431
  let current = rule;
@@ -2179,11 +2449,17 @@ function genericRuleType(name) {
2179
2449
  }
2180
2450
  }
2181
2451
  function parseStyleSheetRules(cssText, reportDiagnostic, preserveImports, resourceBudget) {
2452
+ let namespaces = "";
2453
+ let namespaceRulesAllowed = true;
2182
2454
  const rules = [];
2183
2455
  let parsedRuleCount = 0;
2184
2456
  for (const rawRule of scanTopLevelRules(cssText, resourceBudget)) {
2185
- const rule = parseStrictRule(rawRule, reportDiagnostic, preserveImports, null, resourceBudget);
2457
+ const rule = parseStrictRule(rawRule, reportDiagnostic, preserveImports, null, resourceBudget, namespaces);
2186
2458
  if (rule) {
2459
+ if (rule instanceof CSSNamespaceRule) {
2460
+ if (!namespaceRulesAllowed) continue;
2461
+ namespaces += rule.cssText;
2462
+ } else if (!(rule instanceof CSSImportRule)) namespaceRulesAllowed = false;
2187
2463
  parsedRuleCount += ruleForestSize([rule]);
2188
2464
  assertRuleCountBudget(parsedRuleCount, resourceBudget);
2189
2465
  rules.push(rule);
@@ -2195,38 +2471,50 @@ function parseStyleSheetRules(cssText, reportDiagnostic, preserveImports, resour
2195
2471
  assertRuleCountBudget(parsedRuleCount, resourceBudget);
2196
2472
  rules.push(opaque);
2197
2473
  }
2198
- return rules;
2474
+ return {
2475
+ rules,
2476
+ namespaces
2477
+ };
2199
2478
  }
2200
- /** A mutable, browser-shaped authoring stylesheet. */
2201
- var CSSStyleSheet = class {
2202
- cssRules;
2479
+ const stylesheetConstructionKey = Symbol("StyleSheet construction");
2480
+ /** Shared stylesheet metadata. Instances are created through CSSStyleSheet. */
2481
+ var StyleSheet = class {
2203
2482
  media;
2204
2483
  ownerNode = null;
2205
2484
  parentStyleSheet = null;
2206
- ownerRule = null;
2207
2485
  title = null;
2208
2486
  type = "text/css";
2209
2487
  disabled;
2488
+ constructor(options = {}, resourceBudget = defaultResourceBudget, key) {
2489
+ if (key !== stylesheetConstructionKey) throw new TypeError("Illegal constructor");
2490
+ const media = options.media === void 0 ? "" : `${options.media}`;
2491
+ this.media = constructWithResourceBudget(() => constructWebIDL(MediaList, [media]), resourceBudget);
2492
+ this.disabled = Boolean(options.disabled);
2493
+ }
2494
+ get href() {
2495
+ return regularSheetMetadata.get(this)?.href ?? null;
2496
+ }
2497
+ };
2498
+ /** A mutable, browser-shaped authoring stylesheet. */
2499
+ var CSSStyleSheet = class extends StyleSheet {
2500
+ cssRules;
2501
+ ownerRule = null;
2210
2502
  #rules = [];
2211
2503
  #diagnostics;
2212
2504
  #constructedBaseURL;
2213
2505
  constructor(options = {}) {
2214
2506
  const normalizedOptions = options ?? {};
2215
2507
  const resourceBudget = normalizeResourceBudget(normalizedOptions.resourceBudget);
2508
+ super(normalizedOptions, resourceBudget, stylesheetConstructionKey);
2216
2509
  sheetResourceBudgets.set(this, resourceBudget);
2217
2510
  sheetRuleArrays.set(this, this.#rules);
2218
2511
  sheetRuleCounts.set(this, 0);
2512
+ sheetNamespaces.set(this, "");
2219
2513
  this.#diagnostics = Boolean(normalizedOptions.diagnostics) ? [] : null;
2220
2514
  this.#constructedBaseURL = normalizedOptions.baseURL === void 0 ? "about:blank" : `${normalizedOptions.baseURL}`;
2221
- const media = normalizedOptions.media === void 0 ? "" : `${normalizedOptions.media}`;
2222
- this.media = constructWithResourceBudget(() => constructWebIDL(MediaList, [media]), resourceBudget);
2223
- this.disabled = Boolean(normalizedOptions.disabled);
2224
2515
  this.cssRules = constructInternally(() => constructWebIDL(CSSRuleList, [this.#rules]));
2225
2516
  lockOwnProperties(this, "cssRules", "media", "ownerNode", "parentStyleSheet", "ownerRule", "title", "type");
2226
2517
  }
2227
- get href() {
2228
- return regularSheetMetadata.get(this)?.href ?? null;
2229
- }
2230
2518
  get baseURL() {
2231
2519
  return regularSheetMetadata.get(this)?.baseURL ?? this.#constructedBaseURL;
2232
2520
  }
@@ -2239,14 +2527,16 @@ var CSSStyleSheet = class {
2239
2527
  if (normalizedIndex > this.#rules.length) throw new DOMException("The index is outside the allowed range.", "IndexSizeError");
2240
2528
  const regular = regularSheetMetadata.has(this);
2241
2529
  const resourceBudget = sheetResourceBudgets.get(this) ?? defaultResourceBudget;
2242
- const rule = parseStrictRule(`${ruleText}`, this.#reportDiagnostic, regular, null, resourceBudget);
2530
+ const rule = parseStrictRule(`${ruleText}`, this.#reportDiagnostic, regular, null, resourceBudget, namespaceText(this));
2243
2531
  if (!rule) throw new DOMException("The rule could not be parsed.", "SyntaxError");
2532
+ if (rule instanceof CSSNamespaceRule && !permitsNamespaceMutation(this.#rules)) throw new DOMException("Namespace rules cannot change after other rules exist.", "InvalidStateError");
2244
2533
  const precedingRules = this.#rules.slice(0, normalizedIndex);
2245
2534
  const followingRules = this.#rules.slice(normalizedIndex);
2246
2535
  if (rule instanceof CSSImportRule ? precedingRules.some((candidate) => !(candidate instanceof CSSImportRule)) : followingRules.some((candidate) => candidate instanceof CSSImportRule)) throw new DOMException("The rule violates stylesheet ordering.", "HierarchyRequestError");
2247
2536
  const insertedCount = assertRuleInsertionBudget(this, rule, resourceBudget);
2248
2537
  attachRuleTree(rule, null, this);
2249
2538
  this.#rules.splice(normalizedIndex, 0, rule);
2539
+ if (rule instanceof CSSNamespaceRule) sheetNamespaces.set(this, namespaceRulesText(this.#rules));
2250
2540
  adjustSheetRuleCount(this, insertedCount);
2251
2541
  return normalizedIndex;
2252
2542
  }
@@ -2254,15 +2544,18 @@ var CSSStyleSheet = class {
2254
2544
  requireArguments(arguments.length, 1, "CSSStyleSheet", "deleteRule");
2255
2545
  const normalizedIndex = toUnsignedLong(index);
2256
2546
  if (normalizedIndex >= this.#rules.length) throw new DOMException("The index is outside the allowed range.", "IndexSizeError");
2547
+ if (this.#rules[normalizedIndex] instanceof CSSNamespaceRule && !permitsNamespaceMutation(this.#rules)) throw new DOMException("Namespace rules cannot change while other rules exist.", "InvalidStateError");
2257
2548
  const [removed] = this.#rules.splice(normalizedIndex, 1);
2258
2549
  if (!removed) return;
2550
+ if (removed instanceof CSSNamespaceRule) sheetNamespaces.set(this, namespaceRulesText(this.#rules));
2259
2551
  adjustSheetRuleCount(this, -ruleForestSize([removed]));
2260
2552
  attachRuleTree(removed, null, null);
2261
2553
  }
2262
2554
  replaceSync(cssText) {
2263
2555
  requireArguments(arguments.length, 1, "CSSStyleSheet", "replaceSync");
2264
- const replacement = parseStyleSheetRules(`${cssText}`, this.#reportDiagnostic, regularSheetMetadata.has(this), sheetResourceBudgets.get(this) ?? defaultResourceBudget);
2556
+ const { rules: replacement, namespaces } = parseStyleSheetRules(`${cssText}`, this.#reportDiagnostic, regularSheetMetadata.has(this), sheetResourceBudgets.get(this) ?? defaultResourceBudget);
2265
2557
  for (const rule of this.#rules) attachRuleTree(rule, null, null);
2558
+ sheetNamespaces.set(this, namespaces);
2266
2559
  for (const rule of replacement) attachRuleTree(rule, null, this);
2267
2560
  this.#rules.splice(0, this.#rules.length, ...replacement);
2268
2561
  sheetRuleCounts.set(this, ruleForestSize(replacement));
@@ -2298,6 +2591,6 @@ function parseStyleSheet(cssText, options = {}) {
2298
2591
  return sheet;
2299
2592
  }
2300
2593
  //#endregion
2301
- export { CSSConditionRule, CSSContainerRule, CSSCounterStyleRule, CSSFontFaceRule, CSSFontFeatureValuesMap, CSSFontFeatureValuesRule, CSSFontPaletteValuesRule, CSSFunctionDeclarations, CSSFunctionDescriptors, CSSFunctionRule, CSSGroupingRule, CSSImportRule, CSSKeyframeRule, CSSKeyframesRule, CSSLayerBlockRule, CSSLayerStatementRule, CSSMarginRule, CSSMediaRule, CSSNamespaceRule, CSSNestedDeclarations, CSSPageRule, CSSPositionTryRule, CSSPropertyRule, CSSRule, CSSRuleList, CSSScopeRule, CSSStartingStyleRule, CSSStyleDeclaration, CSSStyleRule, CSSStyleSheet, CSSSupportsRule, CSSViewTransitionRule, MediaList, SheetOMSerializationError, parseStyleSheet };
2594
+ export { CSS, CSSApplyBlockRule, CSSApplyStatementRule, CSSConditionRule, CSSContainerRule, CSSContentsBlockRule, CSSContentsStatementRule, CSSCounterStyleRule, CSSFontFaceRule, CSSFontFeatureValuesMap, CSSFontFeatureValuesRule, CSSFontPaletteValuesRule, CSSFunctionDeclarations, CSSFunctionDescriptors, CSSFunctionRule, CSSGroupingRule, CSSImportRule, CSSKeyframeRule, CSSKeyframesRule, CSSLayerBlockRule, CSSLayerStatementRule, CSSMarginRule, CSSMediaRule, CSSMixinRule, CSSNamespaceRule, CSSNestedDeclarations, CSSPageRule, CSSPositionTryDescriptors, CSSPositionTryRule, CSSPropertyRule, CSSRule, CSSRuleList, CSSScopeRule, CSSStartingStyleRule, CSSStyleDeclaration, CSSStyleRule, CSSStyleSheet, CSSSupportsRule, CSSViewTransitionRule, MediaList, SheetOMSerializationError, StyleSheet, parseStyleSheet };
2302
2595
 
2303
2596
  //# sourceMappingURL=index.js.map