sheetom 0.1.1 → 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.cjs +352 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +64 -9
- package/dist/index.d.ts +64 -9
- package/dist/index.js +345 -38
- package/dist/index.js.map +1 -1
- package/docs/api.md +19 -1
- package/engine-abi.json +3 -3
- package/package.json +16 -15
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:
|
|
8
|
-
sheetomVersion: "0.
|
|
9
|
-
syntaxEngineSetSha256: "
|
|
7
|
+
abiVersion: 5,
|
|
8
|
+
sheetomVersion: "0.2.0",
|
|
9
|
+
syntaxEngineSetSha256: "954d76058dc35ad2a5c85e41fd66e35d308856e554c93563e7eee8a4704d4b70"
|
|
10
10
|
});
|
|
11
11
|
var SheetOMEngineBindingError = class extends Error {
|
|
12
12
|
code;
|
|
@@ -356,8 +356,8 @@ function isNativeRuleDescription(value) {
|
|
|
356
356
|
}
|
|
357
357
|
//#endregion
|
|
358
358
|
//#region src/internal/native-rule-syntax.ts
|
|
359
|
-
function normalizeNativeSelector(source, resourceBudget = defaultResourceBudget) {
|
|
360
|
-
return callNative(() => engineBinding.normalizeSelector(source, ...nativeBudgetArguments(resourceBudget)));
|
|
359
|
+
function normalizeNativeSelector(source, resourceBudget = defaultResourceBudget, namespaces = "") {
|
|
360
|
+
return callNative(() => engineBinding.normalizeSelector(source, namespaces, ...nativeBudgetArguments(resourceBudget)));
|
|
361
361
|
}
|
|
362
362
|
function normalizeNativeMedia(source, resourceBudget = defaultResourceBudget) {
|
|
363
363
|
return callNative(() => engineBinding.normalizeMedia(source, ...nativeBudgetArguments(resourceBudget)));
|
|
@@ -396,6 +396,9 @@ function callNative(operation) {
|
|
|
396
396
|
return null;
|
|
397
397
|
}
|
|
398
398
|
}
|
|
399
|
+
function supportsNativeCss(source, value) {
|
|
400
|
+
return engineBinding.supportsCss(source, value);
|
|
401
|
+
}
|
|
399
402
|
//#endregion
|
|
400
403
|
//#region src/internal/rule-tree.ts
|
|
401
404
|
/** Owns child-list identity and parent propagation for every live rule node. */
|
|
@@ -575,6 +578,39 @@ function assertInternalConstructor(name) {
|
|
|
575
578
|
}
|
|
576
579
|
//#endregion
|
|
577
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
|
+
});
|
|
578
614
|
const arrayIndexPattern = /^(0|[1-9]\d*)$/;
|
|
579
615
|
const regularSheetMetadata = /* @__PURE__ */ new WeakMap();
|
|
580
616
|
const ruleParentage = /* @__PURE__ */ new WeakMap();
|
|
@@ -582,7 +618,19 @@ const ruleResourceBudgets = /* @__PURE__ */ new WeakMap();
|
|
|
582
618
|
const sheetResourceBudgets = /* @__PURE__ */ new WeakMap();
|
|
583
619
|
const sheetRuleArrays = /* @__PURE__ */ new WeakMap();
|
|
584
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
|
+
}
|
|
585
632
|
const functionRuleHeaders = /* @__PURE__ */ new WeakMap();
|
|
633
|
+
const mixinRuleHeaders = /* @__PURE__ */ new WeakMap();
|
|
586
634
|
const unsignedLongRange = 2 ** 32;
|
|
587
635
|
const pageMarginRuleNames = /* @__PURE__ */ new Set([
|
|
588
636
|
"top-left-corner",
|
|
@@ -635,8 +683,8 @@ function namedPropertyToCSS(property) {
|
|
|
635
683
|
if (/^(webkit|moz|ms|o)-/.test(cssName)) cssName = `-${cssName}`;
|
|
636
684
|
return cssName;
|
|
637
685
|
}
|
|
638
|
-
function normalizeSelectorText(value, resourceBudget = defaultResourceBudget) {
|
|
639
|
-
return normalizeNativeSelector(value, resourceBudget);
|
|
686
|
+
function normalizeSelectorText(value, resourceBudget = defaultResourceBudget, namespaces = "") {
|
|
687
|
+
return normalizeNativeSelector(value, resourceBudget, namespaces);
|
|
640
688
|
}
|
|
641
689
|
function toUnsignedLong(value) {
|
|
642
690
|
const number = Number(value);
|
|
@@ -1028,6 +1076,112 @@ var CSSFunctionRule = class extends CSSGroupingRule {
|
|
|
1028
1076
|
}
|
|
1029
1077
|
set cssText(_value) {}
|
|
1030
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
|
+
}
|
|
1031
1185
|
function serializeFunctionHeader(name, parameters, returnType) {
|
|
1032
1186
|
const serializedParameters = parameters.map((parameter) => {
|
|
1033
1187
|
const type = serializeFunctionType(parameter.type);
|
|
@@ -1290,7 +1444,7 @@ var CSSStyleDeclaration = class {
|
|
|
1290
1444
|
};
|
|
1291
1445
|
(ruleDiagnostics.get(this.parentRule) ?? ignoreDiagnostic)(diagnostic);
|
|
1292
1446
|
};
|
|
1293
|
-
this.#block = new NativeDeclarationBlock(reportDeclarationDiagnostic, reportSerializationDiagnostic, parentRule instanceof CSSFontFaceRule ? "font-face" : parentRule instanceof CSSFunctionDeclarations ? "function" : "style", ruleResourceBudgets.get(parentRule) ?? defaultResourceBudget, () => declarationSerializationDepth(parentRule), initialCssText);
|
|
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);
|
|
1294
1448
|
return new Proxy(this, {
|
|
1295
1449
|
get(target, property) {
|
|
1296
1450
|
if (typeof property === "string" && arrayIndexPattern.test(property)) return target.item(Number(property)) || void 0;
|
|
@@ -1467,15 +1621,76 @@ var CSSPageRule = class extends CSSGroupingRule {
|
|
|
1467
1621
|
}
|
|
1468
1622
|
set cssText(_value) {}
|
|
1469
1623
|
};
|
|
1470
|
-
/**
|
|
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. */
|
|
1471
1680
|
var CSSPositionTryRule = class extends CSSRule {
|
|
1472
1681
|
name;
|
|
1473
|
-
style;
|
|
1682
|
+
#style;
|
|
1474
1683
|
constructor(name, initialCssText) {
|
|
1475
1684
|
super(0);
|
|
1476
1685
|
this.name = name;
|
|
1477
|
-
this
|
|
1478
|
-
lockOwnProperties(this, "name"
|
|
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}`;
|
|
1479
1694
|
}
|
|
1480
1695
|
get cssText() {
|
|
1481
1696
|
return `@position-try ${this.name} {${this.style.cssText === "" ? "" : ` ${this.style.cssText}`} }`;
|
|
@@ -1822,6 +2037,9 @@ var CSSFontFeatureValuesRule = class extends CSSRule {
|
|
|
1822
2037
|
var CSSStyleRule = class extends CSSGroupingRule {
|
|
1823
2038
|
style;
|
|
1824
2039
|
#selectorText;
|
|
2040
|
+
#namespaces() {
|
|
2041
|
+
return namespaceText(this.parentStyleSheet);
|
|
2042
|
+
}
|
|
1825
2043
|
constructor(selectorText, normalized, initialCssText) {
|
|
1826
2044
|
super(CSSRule.STYLE_RULE);
|
|
1827
2045
|
this.#selectorText = normalized === normalizedSelectorText ? selectorText : normalizeSelectorText(`${selectorText}`, currentConstructionResourceBudget()) ?? `${selectorText}`;
|
|
@@ -1832,7 +2050,7 @@ var CSSStyleRule = class extends CSSGroupingRule {
|
|
|
1832
2050
|
return this.#selectorText;
|
|
1833
2051
|
}
|
|
1834
2052
|
set selectorText(value) {
|
|
1835
|
-
const normalized = normalizeSelectorText(`${value}`, ruleResourceBudgets.get(this) ?? defaultResourceBudget);
|
|
2053
|
+
const normalized = normalizeSelectorText(`${value}`, ruleResourceBudgets.get(this) ?? defaultResourceBudget, this.#namespaces());
|
|
1836
2054
|
if (normalized === null) return;
|
|
1837
2055
|
this.#selectorText = normalized;
|
|
1838
2056
|
}
|
|
@@ -1888,17 +2106,24 @@ function describeRuleSafe(rule, strict) {
|
|
|
1888
2106
|
declarations: rule.style.serializeSafe(" ", strict),
|
|
1889
2107
|
children: ruleTree.children(rule)
|
|
1890
2108
|
};
|
|
2109
|
+
if (rule instanceof CSSApplyStatementRule && rule.getArguments().length === 1 && rule.getArguments()[0] === "") return {
|
|
2110
|
+
kind: "raw",
|
|
2111
|
+
cssText: `@apply ${rule.name}({ });`
|
|
2112
|
+
};
|
|
1891
2113
|
if (!(rule instanceof CSSGroupingRule)) return {
|
|
1892
2114
|
kind: "raw",
|
|
1893
2115
|
cssText: rule.cssText
|
|
1894
2116
|
};
|
|
1895
2117
|
return {
|
|
1896
2118
|
kind: "block",
|
|
1897
|
-
header: groupingRuleHeader(rule),
|
|
2119
|
+
header: rule instanceof CSSApplyBlockRule && rule.getArguments().length === 1 && rule.getArguments()[0] === "" ? `@apply ${rule.name}({ })` : groupingRuleHeader(rule),
|
|
1898
2120
|
children: ruleTree.children(rule)
|
|
1899
2121
|
};
|
|
1900
2122
|
}
|
|
1901
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;
|
|
1902
2127
|
if (rule instanceof CSSFunctionRule) return functionRuleHeaders.get(rule) ?? "@function";
|
|
1903
2128
|
if (rule instanceof CSSMediaRule) return `@media ${rule.media.mediaText}`;
|
|
1904
2129
|
if (rule instanceof CSSSupportsRule) return `@supports ${rule.conditionText}`;
|
|
@@ -1950,12 +2175,13 @@ function parseImportPrelude(prelude) {
|
|
|
1950
2175
|
supports
|
|
1951
2176
|
};
|
|
1952
2177
|
}
|
|
1953
|
-
function createRuleFromNative(description, reportDiagnostic, preserveImports, resourceBudget) {
|
|
1954
|
-
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);
|
|
1955
2180
|
}
|
|
1956
|
-
function createRuleTreeFromNative(description, reportDiagnostic, preserveImports, resourceBudget) {
|
|
2181
|
+
function createRuleTreeFromNative(description, reportDiagnostic, preserveImports, resourceBudget, parentRule) {
|
|
1957
2182
|
const root = createRuleShellFromNative(description, reportDiagnostic, preserveImports, resourceBudget);
|
|
1958
2183
|
if (!root) return null;
|
|
2184
|
+
attachRuleTree(root, parentRule, parentRule?.parentStyleSheet ?? null);
|
|
1959
2185
|
const pending = [{
|
|
1960
2186
|
description,
|
|
1961
2187
|
rule: root
|
|
@@ -1967,9 +2193,10 @@ function createRuleTreeFromNative(description, reportDiagnostic, preserveImports
|
|
|
1967
2193
|
const childFrames = [];
|
|
1968
2194
|
for (const childDescription of current.description.children) {
|
|
1969
2195
|
if (isNativeMetadataRule(childDescription)) continue;
|
|
2196
|
+
if (!isMixinContextAllowed(childDescription.kind, current.rule)) continue;
|
|
1970
2197
|
const child = createRuleShellFromNative(childDescription, reportDiagnostic, preserveImports, resourceBudget);
|
|
1971
2198
|
if (!child) continue;
|
|
1972
|
-
if (child instanceof CSSFunctionDeclarations && child.style.length === 0) continue;
|
|
2199
|
+
if ((child instanceof CSSFunctionDeclarations || child instanceof CSSNestedDeclarations) && child.style.length === 0) continue;
|
|
1973
2200
|
if (current.rule instanceof CSSKeyframesRule && !(child instanceof CSSKeyframeRule)) continue;
|
|
1974
2201
|
children.push(child);
|
|
1975
2202
|
childFrames.push({
|
|
@@ -1987,7 +2214,7 @@ function createRuleTreeFromNative(description, reportDiagnostic, preserveImports
|
|
|
1987
2214
|
return root;
|
|
1988
2215
|
}
|
|
1989
2216
|
function isNativeMetadataRule(description) {
|
|
1990
|
-
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";
|
|
1991
2218
|
}
|
|
1992
2219
|
function createRuleShellFromNative(description, reportDiagnostic, preserveImports, resourceBudget) {
|
|
1993
2220
|
let rule;
|
|
@@ -2075,7 +2302,8 @@ function createRuleShellFromNative(description, reportDiagnostic, preserveImport
|
|
|
2075
2302
|
description.children.filter((candidate) => candidate.kind === "view-transition-type").map((candidate) => candidate.prelude),
|
|
2076
2303
|
description.cssText
|
|
2077
2304
|
]);
|
|
2078
|
-
case "function":
|
|
2305
|
+
case "function":
|
|
2306
|
+
case "mixin": {
|
|
2079
2307
|
const parameters = description.children.filter((candidate) => candidate.kind === "function-parameter").map((candidate) => {
|
|
2080
2308
|
const defaultValue = candidate.children.find((child) => child.kind === "property-descriptor" && child.prelude === "default-value");
|
|
2081
2309
|
return defaultValue ? {
|
|
@@ -2087,13 +2315,35 @@ function createRuleShellFromNative(description, reportDiagnostic, preserveImport
|
|
|
2087
2315
|
type: candidate.declarations
|
|
2088
2316
|
};
|
|
2089
2317
|
});
|
|
2090
|
-
rule = constructWebIDL(CSSFunctionRule, [
|
|
2318
|
+
rule = description.kind === "mixin" ? constructWebIDL(CSSMixinRule, [description.prelude, parameters]) : constructWebIDL(CSSFunctionRule, [
|
|
2091
2319
|
description.prelude,
|
|
2092
2320
|
parameters,
|
|
2093
2321
|
description.declarations
|
|
2094
2322
|
]);
|
|
2095
2323
|
break;
|
|
2096
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;
|
|
2097
2347
|
case "namespace": return constructWebIDL(CSSNamespaceRule, [
|
|
2098
2348
|
nativeRuleDescriptor(description, "namespace-uri"),
|
|
2099
2349
|
nativeRuleDescriptor(description, "prefix"),
|
|
@@ -2131,7 +2381,7 @@ function nativeRuleDescriptor(description, name) {
|
|
|
2131
2381
|
function hydrateCounterStyleDescriptors(rule, declarations, resourceBudget) {
|
|
2132
2382
|
for (const descriptor of parseNativeCounterStyleDescriptors(declarations, resourceBudget)) rule.setParsedDescriptor(descriptor.name, descriptor.value);
|
|
2133
2383
|
}
|
|
2134
|
-
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)) {
|
|
2135
2385
|
if (parentRule instanceof CSSPageRule) {
|
|
2136
2386
|
const page = parseNativeRule(`@page { ${ruleText} }`, resourceBudget);
|
|
2137
2387
|
if (page?.kind !== "page" || page.children.length !== 1) return null;
|
|
@@ -2141,7 +2391,41 @@ function parseStrictRule(ruleText, reportDiagnostic, preserveImports = false, pa
|
|
|
2141
2391
|
}
|
|
2142
2392
|
const description = parseNativeRule(ruleText, resourceBudget) ?? (parentRule && hasFunctionAncestor(parentRule) ? parseNativeRuleWithErrorRecovery(ruleText, resourceBudget) : null);
|
|
2143
2393
|
if (!description || description.kind === "import" && !preserveImports) return null;
|
|
2144
|
-
|
|
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;
|
|
2145
2429
|
}
|
|
2146
2430
|
function hasFunctionAncestor(rule) {
|
|
2147
2431
|
let current = rule;
|
|
@@ -2165,11 +2449,17 @@ function genericRuleType(name) {
|
|
|
2165
2449
|
}
|
|
2166
2450
|
}
|
|
2167
2451
|
function parseStyleSheetRules(cssText, reportDiagnostic, preserveImports, resourceBudget) {
|
|
2452
|
+
let namespaces = "";
|
|
2453
|
+
let namespaceRulesAllowed = true;
|
|
2168
2454
|
const rules = [];
|
|
2169
2455
|
let parsedRuleCount = 0;
|
|
2170
2456
|
for (const rawRule of scanTopLevelRules(cssText, resourceBudget)) {
|
|
2171
|
-
const rule = parseStrictRule(rawRule, reportDiagnostic, preserveImports, null, resourceBudget);
|
|
2457
|
+
const rule = parseStrictRule(rawRule, reportDiagnostic, preserveImports, null, resourceBudget, namespaces);
|
|
2172
2458
|
if (rule) {
|
|
2459
|
+
if (rule instanceof CSSNamespaceRule) {
|
|
2460
|
+
if (!namespaceRulesAllowed) continue;
|
|
2461
|
+
namespaces += rule.cssText;
|
|
2462
|
+
} else if (!(rule instanceof CSSImportRule)) namespaceRulesAllowed = false;
|
|
2173
2463
|
parsedRuleCount += ruleForestSize([rule]);
|
|
2174
2464
|
assertRuleCountBudget(parsedRuleCount, resourceBudget);
|
|
2175
2465
|
rules.push(rule);
|
|
@@ -2181,38 +2471,50 @@ function parseStyleSheetRules(cssText, reportDiagnostic, preserveImports, resour
|
|
|
2181
2471
|
assertRuleCountBudget(parsedRuleCount, resourceBudget);
|
|
2182
2472
|
rules.push(opaque);
|
|
2183
2473
|
}
|
|
2184
|
-
return
|
|
2474
|
+
return {
|
|
2475
|
+
rules,
|
|
2476
|
+
namespaces
|
|
2477
|
+
};
|
|
2185
2478
|
}
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2479
|
+
const stylesheetConstructionKey = Symbol("StyleSheet construction");
|
|
2480
|
+
/** Shared stylesheet metadata. Instances are created through CSSStyleSheet. */
|
|
2481
|
+
var StyleSheet = class {
|
|
2189
2482
|
media;
|
|
2190
2483
|
ownerNode = null;
|
|
2191
2484
|
parentStyleSheet = null;
|
|
2192
|
-
ownerRule = null;
|
|
2193
2485
|
title = null;
|
|
2194
2486
|
type = "text/css";
|
|
2195
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;
|
|
2196
2502
|
#rules = [];
|
|
2197
2503
|
#diagnostics;
|
|
2198
2504
|
#constructedBaseURL;
|
|
2199
2505
|
constructor(options = {}) {
|
|
2200
2506
|
const normalizedOptions = options ?? {};
|
|
2201
2507
|
const resourceBudget = normalizeResourceBudget(normalizedOptions.resourceBudget);
|
|
2508
|
+
super(normalizedOptions, resourceBudget, stylesheetConstructionKey);
|
|
2202
2509
|
sheetResourceBudgets.set(this, resourceBudget);
|
|
2203
2510
|
sheetRuleArrays.set(this, this.#rules);
|
|
2204
2511
|
sheetRuleCounts.set(this, 0);
|
|
2512
|
+
sheetNamespaces.set(this, "");
|
|
2205
2513
|
this.#diagnostics = Boolean(normalizedOptions.diagnostics) ? [] : null;
|
|
2206
2514
|
this.#constructedBaseURL = normalizedOptions.baseURL === void 0 ? "about:blank" : `${normalizedOptions.baseURL}`;
|
|
2207
|
-
const media = normalizedOptions.media === void 0 ? "" : `${normalizedOptions.media}`;
|
|
2208
|
-
this.media = constructWithResourceBudget(() => constructWebIDL(MediaList, [media]), resourceBudget);
|
|
2209
|
-
this.disabled = Boolean(normalizedOptions.disabled);
|
|
2210
2515
|
this.cssRules = constructInternally(() => constructWebIDL(CSSRuleList, [this.#rules]));
|
|
2211
2516
|
lockOwnProperties(this, "cssRules", "media", "ownerNode", "parentStyleSheet", "ownerRule", "title", "type");
|
|
2212
2517
|
}
|
|
2213
|
-
get href() {
|
|
2214
|
-
return regularSheetMetadata.get(this)?.href ?? null;
|
|
2215
|
-
}
|
|
2216
2518
|
get baseURL() {
|
|
2217
2519
|
return regularSheetMetadata.get(this)?.baseURL ?? this.#constructedBaseURL;
|
|
2218
2520
|
}
|
|
@@ -2225,14 +2527,16 @@ var CSSStyleSheet = class {
|
|
|
2225
2527
|
if (normalizedIndex > this.#rules.length) throw new DOMException("The index is outside the allowed range.", "IndexSizeError");
|
|
2226
2528
|
const regular = regularSheetMetadata.has(this);
|
|
2227
2529
|
const resourceBudget = sheetResourceBudgets.get(this) ?? defaultResourceBudget;
|
|
2228
|
-
const rule = parseStrictRule(`${ruleText}`, this.#reportDiagnostic, regular, null, resourceBudget);
|
|
2530
|
+
const rule = parseStrictRule(`${ruleText}`, this.#reportDiagnostic, regular, null, resourceBudget, namespaceText(this));
|
|
2229
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");
|
|
2230
2533
|
const precedingRules = this.#rules.slice(0, normalizedIndex);
|
|
2231
2534
|
const followingRules = this.#rules.slice(normalizedIndex);
|
|
2232
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");
|
|
2233
2536
|
const insertedCount = assertRuleInsertionBudget(this, rule, resourceBudget);
|
|
2234
2537
|
attachRuleTree(rule, null, this);
|
|
2235
2538
|
this.#rules.splice(normalizedIndex, 0, rule);
|
|
2539
|
+
if (rule instanceof CSSNamespaceRule) sheetNamespaces.set(this, namespaceRulesText(this.#rules));
|
|
2236
2540
|
adjustSheetRuleCount(this, insertedCount);
|
|
2237
2541
|
return normalizedIndex;
|
|
2238
2542
|
}
|
|
@@ -2240,15 +2544,18 @@ var CSSStyleSheet = class {
|
|
|
2240
2544
|
requireArguments(arguments.length, 1, "CSSStyleSheet", "deleteRule");
|
|
2241
2545
|
const normalizedIndex = toUnsignedLong(index);
|
|
2242
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");
|
|
2243
2548
|
const [removed] = this.#rules.splice(normalizedIndex, 1);
|
|
2244
2549
|
if (!removed) return;
|
|
2550
|
+
if (removed instanceof CSSNamespaceRule) sheetNamespaces.set(this, namespaceRulesText(this.#rules));
|
|
2245
2551
|
adjustSheetRuleCount(this, -ruleForestSize([removed]));
|
|
2246
2552
|
attachRuleTree(removed, null, null);
|
|
2247
2553
|
}
|
|
2248
2554
|
replaceSync(cssText) {
|
|
2249
2555
|
requireArguments(arguments.length, 1, "CSSStyleSheet", "replaceSync");
|
|
2250
|
-
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);
|
|
2251
2557
|
for (const rule of this.#rules) attachRuleTree(rule, null, null);
|
|
2558
|
+
sheetNamespaces.set(this, namespaces);
|
|
2252
2559
|
for (const rule of replacement) attachRuleTree(rule, null, this);
|
|
2253
2560
|
this.#rules.splice(0, this.#rules.length, ...replacement);
|
|
2254
2561
|
sheetRuleCounts.set(this, ruleForestSize(replacement));
|
|
@@ -2284,6 +2591,6 @@ function parseStyleSheet(cssText, options = {}) {
|
|
|
2284
2591
|
return sheet;
|
|
2285
2592
|
}
|
|
2286
2593
|
//#endregion
|
|
2287
|
-
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 };
|
|
2288
2595
|
|
|
2289
2596
|
//# sourceMappingURL=index.js.map
|