sheetom 0.1.1 → 0.2.1

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.cjs CHANGED
@@ -28,9 +28,9 @@ let node_url = require("node:url");
28
28
  //#endregion
29
29
  //#region src/internal/engine-binding.ts
30
30
  const expectedEngineAbiIdentity = Object.freeze({
31
- abiVersion: 4,
32
- sheetomVersion: "0.1.1",
33
- syntaxEngineSetSha256: "a0f10d0c1f0fe9e5bac9002e8ee548e7b5f6e2c7add1af3d953ae718d25cb37b"
31
+ abiVersion: 5,
32
+ sheetomVersion: "0.2.1",
33
+ syntaxEngineSetSha256: "e53060705956d09b629c87a9779a63ab07c35fae1111cb333866ba9c05dea86b"
34
34
  });
35
35
  var SheetOMEngineBindingError = class extends Error {
36
36
  code;
@@ -380,8 +380,8 @@ function isNativeRuleDescription(value) {
380
380
  }
381
381
  //#endregion
382
382
  //#region src/internal/native-rule-syntax.ts
383
- function normalizeNativeSelector(source, resourceBudget = defaultResourceBudget) {
384
- return callNative(() => engineBinding.normalizeSelector(source, ...nativeBudgetArguments(resourceBudget)));
383
+ function normalizeNativeSelector(source, resourceBudget = defaultResourceBudget, namespaces = "") {
384
+ return callNative(() => engineBinding.normalizeSelector(source, namespaces, ...nativeBudgetArguments(resourceBudget)));
385
385
  }
386
386
  function normalizeNativeMedia(source, resourceBudget = defaultResourceBudget) {
387
387
  return callNative(() => engineBinding.normalizeMedia(source, ...nativeBudgetArguments(resourceBudget)));
@@ -420,6 +420,9 @@ function callNative(operation) {
420
420
  return null;
421
421
  }
422
422
  }
423
+ function supportsNativeCss(source, value) {
424
+ return engineBinding.supportsCss(source, value);
425
+ }
423
426
  //#endregion
424
427
  //#region src/internal/rule-tree.ts
425
428
  /** Owns child-list identity and parent propagation for every live rule node. */
@@ -599,6 +602,39 @@ function assertInternalConstructor(name) {
599
602
  }
600
603
  //#endregion
601
604
  //#region src/index.ts
605
+ /** CSS authoring utilities, without installing or replacing the global CSS namespace. */
606
+ const CSS = {
607
+ /** Serialize a DOMString as a CSS identifier, including lone UTF-16 surrogates. */
608
+ escape(value) {
609
+ requireArguments(arguments.length, 1, "CSS", "escape");
610
+ const input = `${value}`;
611
+ let output = "";
612
+ for (let index = 0; index < input.length; index += 1) {
613
+ const code = input.charCodeAt(index);
614
+ const character = input[index];
615
+ if (code === 0) output += "�";
616
+ else if (code <= 31 || code === 127 || code >= 48 && code <= 57 && (index === 0 || index === 1 && input[0] === "-")) output += `\\${code.toString(16)} `;
617
+ else if (input === "-") output += "\\-";
618
+ else if (code >= 128 || /[a-zA-Z0-9_-]/u.test(character)) output += character;
619
+ else output += `\\${character}`;
620
+ }
621
+ return output;
622
+ },
623
+ /** Test a declaration or supports condition against the pinned authoring capabilities. */
624
+ supports(propertyOrCondition, value) {
625
+ requireArguments(arguments.length, 1, "CSS", "supports");
626
+ try {
627
+ return arguments.length > 1 ? supportsNativeCss(`${propertyOrCondition}`, `${value}`) : supportsNativeCss(`${propertyOrCondition}`);
628
+ } catch (error) {
629
+ rethrowResourceBudgetError(error);
630
+ throw error;
631
+ }
632
+ }
633
+ };
634
+ Object.defineProperty(CSS, Symbol.toStringTag, {
635
+ value: "CSS",
636
+ configurable: true
637
+ });
602
638
  const arrayIndexPattern = /^(0|[1-9]\d*)$/;
603
639
  const regularSheetMetadata = /* @__PURE__ */ new WeakMap();
604
640
  const ruleParentage = /* @__PURE__ */ new WeakMap();
@@ -606,7 +642,19 @@ const ruleResourceBudgets = /* @__PURE__ */ new WeakMap();
606
642
  const sheetResourceBudgets = /* @__PURE__ */ new WeakMap();
607
643
  const sheetRuleArrays = /* @__PURE__ */ new WeakMap();
608
644
  const sheetRuleCounts = /* @__PURE__ */ new WeakMap();
645
+ const sheetNamespaces = /* @__PURE__ */ new WeakMap();
646
+ function namespaceText(sheet) {
647
+ if (!sheet) return "";
648
+ return sheetNamespaces.get(sheet) ?? "";
649
+ }
650
+ function namespaceRulesText(rules) {
651
+ return rules.filter((rule) => rule instanceof CSSNamespaceRule).map((rule) => rule.cssText).join("");
652
+ }
653
+ function permitsNamespaceMutation(rules) {
654
+ return rules.every((rule) => rule instanceof CSSNamespaceRule || rule instanceof CSSImportRule);
655
+ }
609
656
  const functionRuleHeaders = /* @__PURE__ */ new WeakMap();
657
+ const mixinRuleHeaders = /* @__PURE__ */ new WeakMap();
610
658
  const unsignedLongRange = 2 ** 32;
611
659
  const pageMarginRuleNames = /* @__PURE__ */ new Set([
612
660
  "top-left-corner",
@@ -659,8 +707,8 @@ function namedPropertyToCSS(property) {
659
707
  if (/^(webkit|moz|ms|o)-/.test(cssName)) cssName = `-${cssName}`;
660
708
  return cssName;
661
709
  }
662
- function normalizeSelectorText(value, resourceBudget = defaultResourceBudget) {
663
- return normalizeNativeSelector(value, resourceBudget);
710
+ function normalizeSelectorText(value, resourceBudget = defaultResourceBudget, namespaces = "") {
711
+ return normalizeNativeSelector(value, resourceBudget, namespaces);
664
712
  }
665
713
  function toUnsignedLong(value) {
666
714
  const number = Number(value);
@@ -1052,6 +1100,112 @@ var CSSFunctionRule = class extends CSSGroupingRule {
1052
1100
  }
1053
1101
  set cssText(_value) {}
1054
1102
  };
1103
+ /** Experimental revision-pinned native CSS mixin definition. */
1104
+ var CSSMixinRule = class extends CSSGroupingRule {
1105
+ name;
1106
+ contents = true;
1107
+ #parameters;
1108
+ constructor(name, parameters) {
1109
+ super(0);
1110
+ this.name = serializeNativeIdentifier(name);
1111
+ this.#parameters = parameters.map((parameter) => ({ ...parameter }));
1112
+ const header = serializeFunctionHeader(name, parameters, "*").replace(/^@function /u, "@mixin ");
1113
+ mixinRuleHeaders.set(this, parameters.length === 0 ? header.slice(0, -2) : header);
1114
+ lockOwnProperties(this, "name", "contents");
1115
+ }
1116
+ getParameters() {
1117
+ return this.#parameters.map((parameter) => ({ ...parameter }));
1118
+ }
1119
+ get cssText() {
1120
+ return serializeMixinCssText(this);
1121
+ }
1122
+ set cssText(_value) {}
1123
+ };
1124
+ /** Experimental native CSS mixin application with a contents block. */
1125
+ var CSSApplyBlockRule = class extends CSSGroupingRule {
1126
+ name;
1127
+ #arguments;
1128
+ constructor(name, args, header) {
1129
+ super(0);
1130
+ this.name = serializeNativeIdentifier(name);
1131
+ this.#arguments = [...args];
1132
+ mixinRuleHeaders.set(this, header);
1133
+ lockOwnProperties(this, "name");
1134
+ }
1135
+ getArguments() {
1136
+ return [...this.#arguments];
1137
+ }
1138
+ get cssText() {
1139
+ return serializeMixinCssText(this);
1140
+ }
1141
+ set cssText(_value) {}
1142
+ };
1143
+ /** Experimental native CSS mixin application without a contents block. */
1144
+ var CSSApplyStatementRule = class extends CSSRule {
1145
+ name;
1146
+ #arguments;
1147
+ #header;
1148
+ constructor(name, args, header) {
1149
+ super(0);
1150
+ this.name = serializeNativeIdentifier(name);
1151
+ this.#arguments = [...args];
1152
+ this.#header = header;
1153
+ lockOwnProperties(this, "name");
1154
+ }
1155
+ getArguments() {
1156
+ return [...this.#arguments];
1157
+ }
1158
+ get cssText() {
1159
+ return `${this.#header};`;
1160
+ }
1161
+ set cssText(_value) {}
1162
+ };
1163
+ /** Experimental native CSS mixin contents placeholder with a fallback block. */
1164
+ var CSSContentsBlockRule = class extends CSSGroupingRule {
1165
+ constructor() {
1166
+ super(0);
1167
+ mixinRuleHeaders.set(this, "@contents");
1168
+ }
1169
+ get cssText() {
1170
+ return serializeMixinCssText(this);
1171
+ }
1172
+ set cssText(_value) {}
1173
+ };
1174
+ /** Experimental native CSS mixin contents placeholder without a fallback. */
1175
+ var CSSContentsStatementRule = class extends CSSRule {
1176
+ constructor() {
1177
+ super(0);
1178
+ }
1179
+ get cssText() {
1180
+ return "@contents;";
1181
+ }
1182
+ set cssText(_value) {}
1183
+ };
1184
+ function serializeMixinCssText(root) {
1185
+ const chunks = [];
1186
+ const pending = [root];
1187
+ while (pending.length > 0) {
1188
+ const item = pending.pop();
1189
+ if (typeof item === "string") {
1190
+ chunks.push(item);
1191
+ continue;
1192
+ }
1193
+ if (!(item instanceof CSSGroupingRule)) {
1194
+ chunks.push(item.cssText);
1195
+ continue;
1196
+ }
1197
+ const header = groupingRuleHeader(item);
1198
+ chunks.push(header, item instanceof CSSMixinRule ? "{ " : " { ");
1199
+ pending.push(" }");
1200
+ const children = ruleTree.children(item);
1201
+ for (let index = children.length - 1; index >= 0; index -= 1) {
1202
+ pending.push(children[index]);
1203
+ if (index > 0) pending.push(" ");
1204
+ }
1205
+ if (item instanceof CSSStyleRule && item.style.cssText !== "") pending.push(children.length ? `${item.style.cssText} ` : item.style.cssText);
1206
+ }
1207
+ return chunks.join("");
1208
+ }
1055
1209
  function serializeFunctionHeader(name, parameters, returnType) {
1056
1210
  const serializedParameters = parameters.map((parameter) => {
1057
1211
  const type = serializeFunctionType(parameter.type);
@@ -1314,7 +1468,7 @@ var CSSStyleDeclaration = class {
1314
1468
  };
1315
1469
  (ruleDiagnostics.get(this.parentRule) ?? ignoreDiagnostic)(diagnostic);
1316
1470
  };
1317
- this.#block = new NativeDeclarationBlock(reportDeclarationDiagnostic, reportSerializationDiagnostic, parentRule instanceof CSSFontFaceRule ? "font-face" : parentRule instanceof CSSFunctionDeclarations ? "function" : "style", ruleResourceBudgets.get(parentRule) ?? defaultResourceBudget, () => declarationSerializationDepth(parentRule), initialCssText);
1471
+ 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);
1318
1472
  return new Proxy(this, {
1319
1473
  get(target, property) {
1320
1474
  if (typeof property === "string" && arrayIndexPattern.test(property)) return target.item(Number(property)) || void 0;
@@ -1491,15 +1645,76 @@ var CSSPageRule = class extends CSSGroupingRule {
1491
1645
  }
1492
1646
  set cssText(_value) {}
1493
1647
  };
1494
- /** A live `@position-try` declaration rule. */
1648
+ /** The allowed descriptors of an anchor positioning fallback rule. */
1649
+ var CSSPositionTryDescriptors = class extends CSSStyleDeclaration {};
1650
+ for (const name of [
1651
+ "margin",
1652
+ "margin-top",
1653
+ "margin-right",
1654
+ "margin-bottom",
1655
+ "margin-left",
1656
+ "margin-block",
1657
+ "margin-block-start",
1658
+ "margin-block-end",
1659
+ "margin-inline",
1660
+ "margin-inline-start",
1661
+ "margin-inline-end",
1662
+ "inset",
1663
+ "top",
1664
+ "right",
1665
+ "bottom",
1666
+ "left",
1667
+ "inset-block",
1668
+ "inset-block-start",
1669
+ "inset-block-end",
1670
+ "inset-inline",
1671
+ "inset-inline-start",
1672
+ "inset-inline-end",
1673
+ "width",
1674
+ "min-width",
1675
+ "max-width",
1676
+ "height",
1677
+ "min-height",
1678
+ "max-height",
1679
+ "block-size",
1680
+ "min-block-size",
1681
+ "max-block-size",
1682
+ "inline-size",
1683
+ "min-inline-size",
1684
+ "max-inline-size",
1685
+ "place-self",
1686
+ "align-self",
1687
+ "justify-self",
1688
+ "position-anchor",
1689
+ "position-area"
1690
+ ]) {
1691
+ const camelCase = name.replace(/-([a-z])/gu, (_match, letter) => letter.toUpperCase());
1692
+ for (const accessor of /* @__PURE__ */ new Set([name, camelCase])) Object.defineProperty(CSSPositionTryDescriptors.prototype, accessor, {
1693
+ configurable: true,
1694
+ enumerable: true,
1695
+ get() {
1696
+ return this.getPropertyValue(name);
1697
+ },
1698
+ set(value) {
1699
+ this.setProperty(name, value);
1700
+ }
1701
+ });
1702
+ }
1703
+ /** A named anchor positioning fallback rule. */
1495
1704
  var CSSPositionTryRule = class extends CSSRule {
1496
1705
  name;
1497
- style;
1706
+ #style;
1498
1707
  constructor(name, initialCssText) {
1499
1708
  super(0);
1500
1709
  this.name = name;
1501
- this.style = constructWebIDL(CSSStyleDeclaration, [this, initialCssText]);
1502
- lockOwnProperties(this, "name", "style");
1710
+ this.#style = constructWebIDL(CSSPositionTryDescriptors, [this, initialCssText]);
1711
+ lockOwnProperties(this, "name");
1712
+ }
1713
+ get style() {
1714
+ return this.#style;
1715
+ }
1716
+ set style(cssText) {
1717
+ this.#style.cssText = `${cssText}`;
1503
1718
  }
1504
1719
  get cssText() {
1505
1720
  return `@position-try ${this.name} {${this.style.cssText === "" ? "" : ` ${this.style.cssText}`} }`;
@@ -1846,6 +2061,9 @@ var CSSFontFeatureValuesRule = class extends CSSRule {
1846
2061
  var CSSStyleRule = class extends CSSGroupingRule {
1847
2062
  style;
1848
2063
  #selectorText;
2064
+ #namespaces() {
2065
+ return namespaceText(this.parentStyleSheet);
2066
+ }
1849
2067
  constructor(selectorText, normalized, initialCssText) {
1850
2068
  super(CSSRule.STYLE_RULE);
1851
2069
  this.#selectorText = normalized === normalizedSelectorText ? selectorText : normalizeSelectorText(`${selectorText}`, currentConstructionResourceBudget()) ?? `${selectorText}`;
@@ -1856,7 +2074,7 @@ var CSSStyleRule = class extends CSSGroupingRule {
1856
2074
  return this.#selectorText;
1857
2075
  }
1858
2076
  set selectorText(value) {
1859
- const normalized = normalizeSelectorText(`${value}`, ruleResourceBudgets.get(this) ?? defaultResourceBudget);
2077
+ const normalized = normalizeSelectorText(`${value}`, ruleResourceBudgets.get(this) ?? defaultResourceBudget, this.#namespaces());
1860
2078
  if (normalized === null) return;
1861
2079
  this.#selectorText = normalized;
1862
2080
  }
@@ -1912,17 +2130,24 @@ function describeRuleSafe(rule, strict) {
1912
2130
  declarations: rule.style.serializeSafe(" ", strict),
1913
2131
  children: ruleTree.children(rule)
1914
2132
  };
2133
+ if (rule instanceof CSSApplyStatementRule && rule.getArguments().length === 1 && rule.getArguments()[0] === "") return {
2134
+ kind: "raw",
2135
+ cssText: `@apply ${rule.name}({ });`
2136
+ };
1915
2137
  if (!(rule instanceof CSSGroupingRule)) return {
1916
2138
  kind: "raw",
1917
2139
  cssText: rule.cssText
1918
2140
  };
1919
2141
  return {
1920
2142
  kind: "block",
1921
- header: groupingRuleHeader(rule),
2143
+ header: rule instanceof CSSApplyBlockRule && rule.getArguments().length === 1 && rule.getArguments()[0] === "" ? `@apply ${rule.name}({ })` : groupingRuleHeader(rule),
1922
2144
  children: ruleTree.children(rule)
1923
2145
  };
1924
2146
  }
1925
2147
  function groupingRuleHeader(rule) {
2148
+ const mixinHeader = mixinRuleHeaders.get(rule);
2149
+ if (mixinHeader !== void 0) return mixinHeader;
2150
+ if (rule instanceof CSSStyleRule) return rule.selectorText;
1926
2151
  if (rule instanceof CSSFunctionRule) return functionRuleHeaders.get(rule) ?? "@function";
1927
2152
  if (rule instanceof CSSMediaRule) return `@media ${rule.media.mediaText}`;
1928
2153
  if (rule instanceof CSSSupportsRule) return `@supports ${rule.conditionText}`;
@@ -1974,12 +2199,13 @@ function parseImportPrelude(prelude) {
1974
2199
  supports
1975
2200
  };
1976
2201
  }
1977
- function createRuleFromNative(description, reportDiagnostic, preserveImports, resourceBudget) {
1978
- return constructWithResourceBudget(() => createRuleTreeFromNative(description, reportDiagnostic, preserveImports, resourceBudget), resourceBudget);
2202
+ function createRuleFromNative(description, reportDiagnostic, preserveImports, resourceBudget, parentRule = null) {
2203
+ return constructWithResourceBudget(() => createRuleTreeFromNative(description, reportDiagnostic, preserveImports, resourceBudget, parentRule), resourceBudget);
1979
2204
  }
1980
- function createRuleTreeFromNative(description, reportDiagnostic, preserveImports, resourceBudget) {
2205
+ function createRuleTreeFromNative(description, reportDiagnostic, preserveImports, resourceBudget, parentRule) {
1981
2206
  const root = createRuleShellFromNative(description, reportDiagnostic, preserveImports, resourceBudget);
1982
2207
  if (!root) return null;
2208
+ attachRuleTree(root, parentRule, parentRule?.parentStyleSheet ?? null);
1983
2209
  const pending = [{
1984
2210
  description,
1985
2211
  rule: root
@@ -1991,9 +2217,10 @@ function createRuleTreeFromNative(description, reportDiagnostic, preserveImports
1991
2217
  const childFrames = [];
1992
2218
  for (const childDescription of current.description.children) {
1993
2219
  if (isNativeMetadataRule(childDescription)) continue;
2220
+ if (!isMixinContextAllowed(childDescription.kind, current.rule)) continue;
1994
2221
  const child = createRuleShellFromNative(childDescription, reportDiagnostic, preserveImports, resourceBudget);
1995
2222
  if (!child) continue;
1996
- if (child instanceof CSSFunctionDeclarations && child.style.length === 0) continue;
2223
+ if ((child instanceof CSSFunctionDeclarations || child instanceof CSSNestedDeclarations) && child.style.length === 0) continue;
1997
2224
  if (current.rule instanceof CSSKeyframesRule && !(child instanceof CSSKeyframeRule)) continue;
1998
2225
  children.push(child);
1999
2226
  childFrames.push({
@@ -2011,7 +2238,7 @@ function createRuleTreeFromNative(description, reportDiagnostic, preserveImports
2011
2238
  return root;
2012
2239
  }
2013
2240
  function isNativeMetadataRule(description) {
2014
- return description.kind === "function-parameter" || description.kind === "property-descriptor" || description.kind === "view-transition-type" || description.kind === "layer-name";
2241
+ return description.kind === "function-parameter" || description.kind === "mixin-argument" || description.kind === "property-descriptor" || description.kind === "view-transition-type" || description.kind === "layer-name";
2015
2242
  }
2016
2243
  function createRuleShellFromNative(description, reportDiagnostic, preserveImports, resourceBudget) {
2017
2244
  let rule;
@@ -2099,7 +2326,8 @@ function createRuleShellFromNative(description, reportDiagnostic, preserveImport
2099
2326
  description.children.filter((candidate) => candidate.kind === "view-transition-type").map((candidate) => candidate.prelude),
2100
2327
  description.cssText
2101
2328
  ]);
2102
- case "function": {
2329
+ case "function":
2330
+ case "mixin": {
2103
2331
  const parameters = description.children.filter((candidate) => candidate.kind === "function-parameter").map((candidate) => {
2104
2332
  const defaultValue = candidate.children.find((child) => child.kind === "property-descriptor" && child.prelude === "default-value");
2105
2333
  return defaultValue ? {
@@ -2111,13 +2339,35 @@ function createRuleShellFromNative(description, reportDiagnostic, preserveImport
2111
2339
  type: candidate.declarations
2112
2340
  };
2113
2341
  });
2114
- rule = constructWebIDL(CSSFunctionRule, [
2342
+ rule = description.kind === "mixin" ? constructWebIDL(CSSMixinRule, [description.prelude, parameters]) : constructWebIDL(CSSFunctionRule, [
2115
2343
  description.prelude,
2116
2344
  parameters,
2117
2345
  description.declarations
2118
2346
  ]);
2119
2347
  break;
2120
2348
  }
2349
+ case "apply-block":
2350
+ case "apply-statement": {
2351
+ const arguments_ = description.children.filter((child) => child.kind === "mixin-argument");
2352
+ const args = arguments_.map((argument) => argument.declarations);
2353
+ const header = `@apply ${serializeNativeIdentifier(description.prelude)}${args.length ? `(${arguments_.map((argument) => argument.cssText).join(", ")})` : ""}`;
2354
+ rule = description.kind === "apply-block" ? constructWebIDL(CSSApplyBlockRule, [
2355
+ description.prelude,
2356
+ args,
2357
+ header
2358
+ ]) : constructWebIDL(CSSApplyStatementRule, [
2359
+ description.prelude,
2360
+ args,
2361
+ header
2362
+ ]);
2363
+ break;
2364
+ }
2365
+ case "contents-block":
2366
+ rule = constructWebIDL(CSSContentsBlockRule);
2367
+ break;
2368
+ case "contents-statement":
2369
+ rule = constructWebIDL(CSSContentsStatementRule);
2370
+ break;
2121
2371
  case "namespace": return constructWebIDL(CSSNamespaceRule, [
2122
2372
  nativeRuleDescriptor(description, "namespace-uri"),
2123
2373
  nativeRuleDescriptor(description, "prefix"),
@@ -2155,7 +2405,7 @@ function nativeRuleDescriptor(description, name) {
2155
2405
  function hydrateCounterStyleDescriptors(rule, declarations, resourceBudget) {
2156
2406
  for (const descriptor of parseNativeCounterStyleDescriptors(declarations, resourceBudget)) rule.setParsedDescriptor(descriptor.name, descriptor.value);
2157
2407
  }
2158
- function parseStrictRule(ruleText, reportDiagnostic, preserveImports = false, parentRule = null, resourceBudget = defaultResourceBudget) {
2408
+ function parseStrictRule(ruleText, reportDiagnostic, preserveImports = false, parentRule = null, resourceBudget = defaultResourceBudget, namespaces = namespaceText(parentRule?.parentStyleSheet ?? null)) {
2159
2409
  if (parentRule instanceof CSSPageRule) {
2160
2410
  const page = parseNativeRule(`@page { ${ruleText} }`, resourceBudget);
2161
2411
  if (page?.kind !== "page" || page.children.length !== 1) return null;
@@ -2165,7 +2415,41 @@ function parseStrictRule(ruleText, reportDiagnostic, preserveImports = false, pa
2165
2415
  }
2166
2416
  const description = parseNativeRule(ruleText, resourceBudget) ?? (parentRule && hasFunctionAncestor(parentRule) ? parseNativeRuleWithErrorRecovery(ruleText, resourceBudget) : null);
2167
2417
  if (!description || description.kind === "import" && !preserveImports) return null;
2168
- return createRuleFromNative(description, reportDiagnostic, preserveImports, resourceBudget);
2418
+ if (!isMixinContextAllowed(description.kind, parentRule)) return null;
2419
+ const validSelector = (rule) => {
2420
+ if (rule.kind !== "style" || !rule.prelude.includes("|")) return true;
2421
+ const normalized = normalizeNativeSelector(rule.prelude, resourceBudget, namespaces);
2422
+ if (normalized === null) return false;
2423
+ rule.prelude = normalized;
2424
+ return true;
2425
+ };
2426
+ if (!validSelector(description)) return null;
2427
+ const pending = [description];
2428
+ while (pending.length) {
2429
+ const current = pending.pop();
2430
+ current.children = current.children.filter(validSelector);
2431
+ for (const child of current.children) pending.push(child);
2432
+ }
2433
+ return createRuleFromNative(description, reportDiagnostic, preserveImports, resourceBudget, parentRule);
2434
+ }
2435
+ function isMixinContextAllowed(kind, parent) {
2436
+ if (![
2437
+ "mixin",
2438
+ "apply-block",
2439
+ "apply-statement",
2440
+ "contents-block",
2441
+ "contents-statement",
2442
+ "private"
2443
+ ].includes(kind)) return true;
2444
+ let nested = false;
2445
+ let mixin = false;
2446
+ for (let current = parent; current; current = current.parentRule) {
2447
+ if (current instanceof CSSFunctionRule) return false;
2448
+ if (current instanceof CSSStyleRule || current instanceof CSSMixinRule) nested = true;
2449
+ if (current instanceof CSSMixinRule) mixin = true;
2450
+ }
2451
+ if (kind === "mixin") return !nested;
2452
+ return kind.startsWith("contents-") ? mixin : nested;
2169
2453
  }
2170
2454
  function hasFunctionAncestor(rule) {
2171
2455
  let current = rule;
@@ -2189,11 +2473,17 @@ function genericRuleType(name) {
2189
2473
  }
2190
2474
  }
2191
2475
  function parseStyleSheetRules(cssText, reportDiagnostic, preserveImports, resourceBudget) {
2476
+ let namespaces = "";
2477
+ let namespaceRulesAllowed = true;
2192
2478
  const rules = [];
2193
2479
  let parsedRuleCount = 0;
2194
2480
  for (const rawRule of scanTopLevelRules(cssText, resourceBudget)) {
2195
- const rule = parseStrictRule(rawRule, reportDiagnostic, preserveImports, null, resourceBudget);
2481
+ const rule = parseStrictRule(rawRule, reportDiagnostic, preserveImports, null, resourceBudget, namespaces);
2196
2482
  if (rule) {
2483
+ if (rule instanceof CSSNamespaceRule) {
2484
+ if (!namespaceRulesAllowed) continue;
2485
+ namespaces += rule.cssText;
2486
+ } else if (!(rule instanceof CSSImportRule)) namespaceRulesAllowed = false;
2197
2487
  parsedRuleCount += ruleForestSize([rule]);
2198
2488
  assertRuleCountBudget(parsedRuleCount, resourceBudget);
2199
2489
  rules.push(rule);
@@ -2205,38 +2495,50 @@ function parseStyleSheetRules(cssText, reportDiagnostic, preserveImports, resour
2205
2495
  assertRuleCountBudget(parsedRuleCount, resourceBudget);
2206
2496
  rules.push(opaque);
2207
2497
  }
2208
- return rules;
2498
+ return {
2499
+ rules,
2500
+ namespaces
2501
+ };
2209
2502
  }
2210
- /** A mutable, browser-shaped authoring stylesheet. */
2211
- var CSSStyleSheet = class {
2212
- cssRules;
2503
+ const stylesheetConstructionKey = Symbol("StyleSheet construction");
2504
+ /** Shared stylesheet metadata. Instances are created through CSSStyleSheet. */
2505
+ var StyleSheet = class {
2213
2506
  media;
2214
2507
  ownerNode = null;
2215
2508
  parentStyleSheet = null;
2216
- ownerRule = null;
2217
2509
  title = null;
2218
2510
  type = "text/css";
2219
2511
  disabled;
2512
+ constructor(options = {}, resourceBudget = defaultResourceBudget, key) {
2513
+ if (key !== stylesheetConstructionKey) throw new TypeError("Illegal constructor");
2514
+ const media = options.media === void 0 ? "" : `${options.media}`;
2515
+ this.media = constructWithResourceBudget(() => constructWebIDL(MediaList, [media]), resourceBudget);
2516
+ this.disabled = Boolean(options.disabled);
2517
+ }
2518
+ get href() {
2519
+ return regularSheetMetadata.get(this)?.href ?? null;
2520
+ }
2521
+ };
2522
+ /** A mutable, browser-shaped authoring stylesheet. */
2523
+ var CSSStyleSheet = class extends StyleSheet {
2524
+ cssRules;
2525
+ ownerRule = null;
2220
2526
  #rules = [];
2221
2527
  #diagnostics;
2222
2528
  #constructedBaseURL;
2223
2529
  constructor(options = {}) {
2224
2530
  const normalizedOptions = options ?? {};
2225
2531
  const resourceBudget = normalizeResourceBudget(normalizedOptions.resourceBudget);
2532
+ super(normalizedOptions, resourceBudget, stylesheetConstructionKey);
2226
2533
  sheetResourceBudgets.set(this, resourceBudget);
2227
2534
  sheetRuleArrays.set(this, this.#rules);
2228
2535
  sheetRuleCounts.set(this, 0);
2536
+ sheetNamespaces.set(this, "");
2229
2537
  this.#diagnostics = Boolean(normalizedOptions.diagnostics) ? [] : null;
2230
2538
  this.#constructedBaseURL = normalizedOptions.baseURL === void 0 ? "about:blank" : `${normalizedOptions.baseURL}`;
2231
- const media = normalizedOptions.media === void 0 ? "" : `${normalizedOptions.media}`;
2232
- this.media = constructWithResourceBudget(() => constructWebIDL(MediaList, [media]), resourceBudget);
2233
- this.disabled = Boolean(normalizedOptions.disabled);
2234
2539
  this.cssRules = constructInternally(() => constructWebIDL(CSSRuleList, [this.#rules]));
2235
2540
  lockOwnProperties(this, "cssRules", "media", "ownerNode", "parentStyleSheet", "ownerRule", "title", "type");
2236
2541
  }
2237
- get href() {
2238
- return regularSheetMetadata.get(this)?.href ?? null;
2239
- }
2240
2542
  get baseURL() {
2241
2543
  return regularSheetMetadata.get(this)?.baseURL ?? this.#constructedBaseURL;
2242
2544
  }
@@ -2249,14 +2551,16 @@ var CSSStyleSheet = class {
2249
2551
  if (normalizedIndex > this.#rules.length) throw new DOMException("The index is outside the allowed range.", "IndexSizeError");
2250
2552
  const regular = regularSheetMetadata.has(this);
2251
2553
  const resourceBudget = sheetResourceBudgets.get(this) ?? defaultResourceBudget;
2252
- const rule = parseStrictRule(`${ruleText}`, this.#reportDiagnostic, regular, null, resourceBudget);
2554
+ const rule = parseStrictRule(`${ruleText}`, this.#reportDiagnostic, regular, null, resourceBudget, namespaceText(this));
2253
2555
  if (!rule) throw new DOMException("The rule could not be parsed.", "SyntaxError");
2556
+ if (rule instanceof CSSNamespaceRule && !permitsNamespaceMutation(this.#rules)) throw new DOMException("Namespace rules cannot change after other rules exist.", "InvalidStateError");
2254
2557
  const precedingRules = this.#rules.slice(0, normalizedIndex);
2255
2558
  const followingRules = this.#rules.slice(normalizedIndex);
2256
2559
  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");
2257
2560
  const insertedCount = assertRuleInsertionBudget(this, rule, resourceBudget);
2258
2561
  attachRuleTree(rule, null, this);
2259
2562
  this.#rules.splice(normalizedIndex, 0, rule);
2563
+ if (rule instanceof CSSNamespaceRule) sheetNamespaces.set(this, namespaceRulesText(this.#rules));
2260
2564
  adjustSheetRuleCount(this, insertedCount);
2261
2565
  return normalizedIndex;
2262
2566
  }
@@ -2264,15 +2568,18 @@ var CSSStyleSheet = class {
2264
2568
  requireArguments(arguments.length, 1, "CSSStyleSheet", "deleteRule");
2265
2569
  const normalizedIndex = toUnsignedLong(index);
2266
2570
  if (normalizedIndex >= this.#rules.length) throw new DOMException("The index is outside the allowed range.", "IndexSizeError");
2571
+ if (this.#rules[normalizedIndex] instanceof CSSNamespaceRule && !permitsNamespaceMutation(this.#rules)) throw new DOMException("Namespace rules cannot change while other rules exist.", "InvalidStateError");
2267
2572
  const [removed] = this.#rules.splice(normalizedIndex, 1);
2268
2573
  if (!removed) return;
2574
+ if (removed instanceof CSSNamespaceRule) sheetNamespaces.set(this, namespaceRulesText(this.#rules));
2269
2575
  adjustSheetRuleCount(this, -ruleForestSize([removed]));
2270
2576
  attachRuleTree(removed, null, null);
2271
2577
  }
2272
2578
  replaceSync(cssText) {
2273
2579
  requireArguments(arguments.length, 1, "CSSStyleSheet", "replaceSync");
2274
- const replacement = parseStyleSheetRules(`${cssText}`, this.#reportDiagnostic, regularSheetMetadata.has(this), sheetResourceBudgets.get(this) ?? defaultResourceBudget);
2580
+ const { rules: replacement, namespaces } = parseStyleSheetRules(`${cssText}`, this.#reportDiagnostic, regularSheetMetadata.has(this), sheetResourceBudgets.get(this) ?? defaultResourceBudget);
2275
2581
  for (const rule of this.#rules) attachRuleTree(rule, null, null);
2582
+ sheetNamespaces.set(this, namespaces);
2276
2583
  for (const rule of replacement) attachRuleTree(rule, null, this);
2277
2584
  this.#rules.splice(0, this.#rules.length, ...replacement);
2278
2585
  sheetRuleCounts.set(this, ruleForestSize(replacement));
@@ -2308,8 +2615,13 @@ function parseStyleSheet(cssText, options = {}) {
2308
2615
  return sheet;
2309
2616
  }
2310
2617
  //#endregion
2618
+ exports.CSS = CSS;
2619
+ exports.CSSApplyBlockRule = CSSApplyBlockRule;
2620
+ exports.CSSApplyStatementRule = CSSApplyStatementRule;
2311
2621
  exports.CSSConditionRule = CSSConditionRule;
2312
2622
  exports.CSSContainerRule = CSSContainerRule;
2623
+ exports.CSSContentsBlockRule = CSSContentsBlockRule;
2624
+ exports.CSSContentsStatementRule = CSSContentsStatementRule;
2313
2625
  exports.CSSCounterStyleRule = CSSCounterStyleRule;
2314
2626
  exports.CSSFontFaceRule = CSSFontFaceRule;
2315
2627
  exports.CSSFontFeatureValuesMap = CSSFontFeatureValuesMap;
@@ -2326,9 +2638,11 @@ exports.CSSLayerBlockRule = CSSLayerBlockRule;
2326
2638
  exports.CSSLayerStatementRule = CSSLayerStatementRule;
2327
2639
  exports.CSSMarginRule = CSSMarginRule;
2328
2640
  exports.CSSMediaRule = CSSMediaRule;
2641
+ exports.CSSMixinRule = CSSMixinRule;
2329
2642
  exports.CSSNamespaceRule = CSSNamespaceRule;
2330
2643
  exports.CSSNestedDeclarations = CSSNestedDeclarations;
2331
2644
  exports.CSSPageRule = CSSPageRule;
2645
+ exports.CSSPositionTryDescriptors = CSSPositionTryDescriptors;
2332
2646
  exports.CSSPositionTryRule = CSSPositionTryRule;
2333
2647
  exports.CSSPropertyRule = CSSPropertyRule;
2334
2648
  exports.CSSRule = CSSRule;
@@ -2342,6 +2656,7 @@ exports.CSSSupportsRule = CSSSupportsRule;
2342
2656
  exports.CSSViewTransitionRule = CSSViewTransitionRule;
2343
2657
  exports.MediaList = MediaList;
2344
2658
  exports.SheetOMSerializationError = SheetOMSerializationError;
2659
+ exports.StyleSheet = StyleSheet;
2345
2660
  exports.parseStyleSheet = parseStyleSheet;
2346
2661
 
2347
2662
  //# sourceMappingURL=index.cjs.map