@master/css-binding 0.0.0-site.1793659883.g69c9aebcf628

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.
Files changed (66) hide show
  1. package/artifacts/mastercss.node +0 -0
  2. package/artifacts/mcss +0 -0
  3. package/dist/binding-options.d.ts +14 -0
  4. package/dist/binding-options.js +15 -0
  5. package/dist/binding.d.ts +12 -0
  6. package/dist/binding.js +23 -0
  7. package/dist/browser.d.ts +3 -0
  8. package/dist/browser.js +3 -0
  9. package/dist/compiler-binding-adapter.js +55 -0
  10. package/dist/compiler-binding-browser.d.ts +6 -0
  11. package/dist/compiler-binding-browser.js +24 -0
  12. package/dist/compiler-binding-contract.d.ts +45 -0
  13. package/dist/compiler-binding-node.d.ts +5 -0
  14. package/dist/compiler-binding-node.js +20 -0
  15. package/dist/compiler-binding-wasm.js +58 -0
  16. package/dist/compiler-binding.d.ts +6 -0
  17. package/dist/compiler-binding.js +42 -0
  18. package/dist/compiler.js +52 -0
  19. package/dist/engine-binding-adapter.js +61 -0
  20. package/dist/engine-binding-browser.d.ts +8 -0
  21. package/dist/engine-binding-browser.js +35 -0
  22. package/dist/engine-binding-js.js +81 -0
  23. package/dist/engine-binding-node.d.ts +9 -0
  24. package/dist/engine-binding-node.js +38 -0
  25. package/dist/engine-binding-wasm.js +64 -0
  26. package/dist/engine-binding.d.ts +40 -0
  27. package/dist/engine-binding.js +57 -0
  28. package/dist/engine-contract.d.ts +14 -0
  29. package/dist/engine-js/src/animation.js +154 -0
  30. package/dist/engine-js/src/apply.js +207 -0
  31. package/dist/engine-js/src/class-syntax.js +333 -0
  32. package/dist/engine-js/src/condition.js +440 -0
  33. package/dist/engine-js/src/css-syntax.js +247 -0
  34. package/dist/engine-js/src/generate.js +288 -0
  35. package/dist/engine-js/src/mixin.js +328 -0
  36. package/dist/engine-js/src/native-properties.js +5 -0
  37. package/dist/engine-js/src/order.js +97 -0
  38. package/dist/engine-js/src/program-model.js +19 -0
  39. package/dist/engine-js/src/program.js +434 -0
  40. package/dist/engine-js/src/selector.js +195 -0
  41. package/dist/engine-js/src/session.js +540 -0
  42. package/dist/engine-js/src/state.js +62 -0
  43. package/dist/engine-js/src/text.js +51 -0
  44. package/dist/engine-js/src/utility.js +236 -0
  45. package/dist/engine-js/src/value.js +254 -0
  46. package/dist/engine.js +86 -0
  47. package/dist/errors.js +10 -0
  48. package/dist/index.d.ts +4 -0
  49. package/dist/index.js +3 -0
  50. package/dist/native-loader.js +134 -0
  51. package/dist/normalize-error.js +63 -0
  52. package/dist/protocol.d.ts +1119 -0
  53. package/dist/protocol.js +14 -0
  54. package/dist/tooling-binding-adapter.js +23 -0
  55. package/dist/tooling-binding-browser.d.ts +5 -0
  56. package/dist/tooling-binding-browser.js +15 -0
  57. package/dist/tooling-binding-contract.d.ts +92 -0
  58. package/dist/tooling-binding-native.js +46 -0
  59. package/dist/tooling-binding-node.d.ts +4 -0
  60. package/dist/tooling-binding-node.js +11 -0
  61. package/dist/tooling-binding-wasm.js +127 -0
  62. package/dist/tooling-binding.d.ts +5 -0
  63. package/dist/tooling-binding.js +21 -0
  64. package/dist/tooling.js +144 -0
  65. package/dist/version.js +3 -0
  66. package/package.json +78 -0
@@ -0,0 +1,236 @@
1
+ import { trim } from "./text.js";
2
+ import { leadingFunctionName } from "./css-syntax.js";
3
+ import { alphaPercentage } from "./value.js";
4
+ import { cssEscape } from "./program.js";
5
+ import { hasTopLevelValueSeparator, isClassSuffixStart, isMatchStateBoundary, isQuote, parseFunctionalClass, splitDynamicValueState } from "./class-syntax.js";
6
+ import { expandUtility } from "./mixin.js";
7
+ // ../engine-js/src/utility.ts
8
+ /** Token keys are non-empty and neither start nor end with `-`. */
9
+ const isVariableKey = (key) => key !== "" && key[0] !== "-" && key[key.length - 1] !== "-";
10
+ /** A `_` begins a descendant selector in classes, so such a token has no bare utility. */
11
+ const isUtilityKey = (key) => isVariableKey(key) && !key.includes("_");
12
+ /** Recipe keys that are CSS strings never take a custom property as their key. */
13
+ const excludesKey = (utility, key) => utility.emit.type === "recipe" && utility.emit.key && key.includes("--");
14
+ /** The variable a token `key` of a utility names: an explicit alias, then the first `~namespace` that declares `namespace-key`. */
15
+ function utilityVariable(utility, key, program) {
16
+ const { variables } = program;
17
+ if (excludesKey(utility, key) || !isUtilityKey(key)) return;
18
+ for (const reference of utility.variableAliasRefs) {
19
+ const name = `${reference[0] === "~" ? reference.slice(1) : reference}-${key}`;
20
+ if (variables.has(name)) return name;
21
+ }
22
+ }
23
+ const NEGATIVE_PROPERTIES = /* @__PURE__ */ new Set([
24
+ "outline-offset",
25
+ "text-underline-offset",
26
+ "mask-position",
27
+ "perspective-origin",
28
+ "transform-origin",
29
+ "cx",
30
+ "cy",
31
+ "x",
32
+ "y",
33
+ "stroke-dashoffset",
34
+ "top",
35
+ "right",
36
+ "bottom",
37
+ "left",
38
+ "translate",
39
+ "rotate",
40
+ "letter-spacing",
41
+ "word-spacing",
42
+ "text-indent",
43
+ "background-position",
44
+ "object-position",
45
+ "animation-delay",
46
+ "transition-delay",
47
+ "order",
48
+ "z-index"
49
+ ]);
50
+ function allowsNegativeToken(utility) {
51
+ if (utility.emit.type !== "property") return false;
52
+ const { property } = utility.emit;
53
+ return property.startsWith("margin") || property.startsWith("scroll-margin") || property.startsWith("inset") || NEGATIVE_PROPERTIES.has(property);
54
+ }
55
+ const variableReference = (name) => `var(${cssEscape(`--${name}`)})`;
56
+ function resolveUtilityValue(value, utility, program) {
57
+ const slash = value.indexOf("/");
58
+ if (slash >= 0) {
59
+ const name = utilityVariable(utility, value.slice(0, slash), program);
60
+ const variable = name === void 0 ? void 0 : program.variables.get(name);
61
+ if (!variable?.namespace.startsWith("color")) return;
62
+ const percentage = alphaPercentage(value.slice(slash + 1));
63
+ if (percentage === void 0) return;
64
+ return [`color-mix(in oklab,${variableReference(variable.name)} ${percentage}%,transparent)`, [variable.name]];
65
+ }
66
+ const negative = value[0] === "-";
67
+ const name = utilityVariable(utility, negative ? value.slice(1) : value, program);
68
+ const variable = name === void 0 ? void 0 : program.variables.get(name);
69
+ if (!variable || negative && variable.variableType !== "number") return;
70
+ const reference = variableReference(variable.name);
71
+ return [negative ? `calc(${reference} * -1)` : reference, [variable.name]];
72
+ }
73
+ function resolveUtilityAliasValue(value, utility, program) {
74
+ const slash = value.indexOf("/");
75
+ const key = slash < 0 ? value : value.slice(0, slash);
76
+ if (utilityVariable(utility, key[0] === "-" ? key.slice(1) : key, program) === void 0) return;
77
+ return resolveUtilityValue(value, utility, program);
78
+ }
79
+ /** The recipe arguments of a token key: the variable, or the key as a CSS string for string parameters. */
80
+ function namedArguments(key, utility, program) {
81
+ const keyArgument = utility.emit.type === "recipe" && utility.emit.key;
82
+ if (keyArgument && key.includes("--")) return;
83
+ const variable = utilityVariable(utility, key, program);
84
+ if (variable === void 0) return;
85
+ if (!keyArgument) return [[`var(--${variable})`], [variable]];
86
+ return [[`"${key.replaceAll("\\", "\\\\").replaceAll("\"", "\\\"")}"`], [variable]];
87
+ }
88
+ function matchUtility(className, utility, program, type) {
89
+ for (const matcher of utility.matchers) {
90
+ if (matcher.type !== type) continue;
91
+ if (matcher.type === "static") {
92
+ const rest = className.slice(matcher.name.length);
93
+ if (className.startsWith(matcher.name) && isMatchStateBoundary(rest)) return {
94
+ arguments: [],
95
+ stateToken: rest,
96
+ variableNames: [],
97
+ matcherType: "static"
98
+ };
99
+ } else if (matcher.type === "token") {
100
+ const { prefix } = matcher;
101
+ let negative = false;
102
+ let raw;
103
+ if (className.startsWith(prefix)) raw = className.slice(prefix.length);
104
+ else if (className[0] === "-" && className.startsWith(prefix, 1)) {
105
+ negative = true;
106
+ raw = className.slice(prefix.length + 1);
107
+ } else continue;
108
+ const [value, stateToken] = splitDynamicValueState(raw);
109
+ if (!value || hasTopLevelValueSeparator(value) || value[0] === "-") continue;
110
+ if (negative && !allowsNegativeToken(utility)) continue;
111
+ const token = negative ? `-${value}` : value;
112
+ if (utility.emit.type === "recipe") {
113
+ const named = namedArguments(token, utility, program);
114
+ if (named) return {
115
+ arguments: named[0],
116
+ stateToken,
117
+ variableNames: named[1],
118
+ matcherType: "token"
119
+ };
120
+ } else {
121
+ const resolved = resolveUtilityAliasValue(token, utility, program);
122
+ if (resolved) return {
123
+ value: resolved[0],
124
+ arguments: [],
125
+ stateToken,
126
+ variableNames: resolved[1],
127
+ matcherType: "token"
128
+ };
129
+ }
130
+ }
131
+ }
132
+ }
133
+ /** Master `|` separators outside strings become spaces; nothing else changes. */
134
+ function normalizeUnmanagedValue(value) {
135
+ let output = "";
136
+ let copied = 0;
137
+ let quote = 0;
138
+ let escaped = false;
139
+ for (let index = 0; index < value.length; index++) {
140
+ const unit = value.charCodeAt(index);
141
+ if (escaped) escaped = false;
142
+ else if (unit === 92) escaped = true;
143
+ else if (quote) {
144
+ if (unit === quote) quote = 0;
145
+ } else if (isQuote(unit)) quote = unit;
146
+ else if (unit === 124) {
147
+ output += `${value.slice(copied, index)} `;
148
+ copied = index + 1;
149
+ }
150
+ }
151
+ return output + value.slice(copied);
152
+ }
153
+ /**
154
+ * The registered recipe, arguments and state token a function class calls; null when
155
+ * the class starts with a function no registered recipe takes, undefined otherwise.
156
+ */
157
+ function functionInvocation(source, program) {
158
+ if (leadingFunctionName(source) === void 0) return;
159
+ const head = parseFunctionalClass(source);
160
+ if (typeof head !== "object") return null;
161
+ const index = program.functionUtilities.get(head.name);
162
+ const emit = index === void 0 ? void 0 : program.utilities[index].emit;
163
+ if (emit?.type !== "recipe") return null;
164
+ return [
165
+ index,
166
+ program.utilityDefinitions[emit.definition],
167
+ head.arguments.map((argument) => normalizeUnmanagedValue(trim(argument))),
168
+ head.suffix
169
+ ];
170
+ }
171
+ /** The longest registered token prefix of a class, with or without its negative sign. */
172
+ function tokenPrefix(source, program) {
173
+ if (source[0] === "(") return;
174
+ let longest;
175
+ for (const candidate of source[0] === "-" ? [source, source.slice(1)] : [source]) for (const prefix of program.tokenPrefixes.get(candidate[0]) ?? []) {
176
+ if (prefix[prefix.length - 1] !== "-" || !candidate.startsWith(prefix)) continue;
177
+ if (!longest || prefix.length >= longest.length) longest = prefix;
178
+ break;
179
+ }
180
+ return longest;
181
+ }
182
+ /** Utilities whose namespace owns the token key, before any sign or opacity applies. */
183
+ function tokenOwners(source, prefix, program) {
184
+ const indexes = program.tokenUtilities.get(prefix);
185
+ if (!indexes) return [];
186
+ let raw;
187
+ if (source.startsWith(prefix)) raw = source.slice(prefix.length);
188
+ else if (source[0] === "-" && source.startsWith(prefix, 1)) raw = source.slice(prefix.length + 1);
189
+ else return [];
190
+ const [value] = splitDynamicValueState(raw);
191
+ if (!value || value[0] === "-" || hasTopLevelValueSeparator(value)) return [];
192
+ const slash = value.indexOf("/");
193
+ const key = slash < 0 ? value : value.slice(0, slash);
194
+ return indexes.filter((index) => utilityVariable(program.utilities[index], key, program) !== void 0);
195
+ }
196
+ /** The match of a token class whose key exactly one utility owns. */
197
+ function tokenCandidates(source, prefix, program) {
198
+ const owners = tokenOwners(source, prefix, program);
199
+ if (owners.length !== 1) return [];
200
+ const matched = matchUtility(source, program.utilities[owners[0]], program, "token");
201
+ return matched ? [[owners[0], matched]] : [];
202
+ }
203
+ /**
204
+ * The utilities a class (without `!`) matches, in priority order. A family is selected
205
+ * before its token is looked up, so a missing qualified token never falls back to a
206
+ * shorter prefix, and static names reserve their spelling. Native declaration heads
207
+ * are never utilities.
208
+ */
209
+ function matchingUtilities(source, program) {
210
+ const matches = [];
211
+ if (source[0] === "(") return matches;
212
+ const invocation = functionInvocation(source, program);
213
+ if (invocation !== void 0) {
214
+ if (!invocation) return matches;
215
+ const [index, recipe, args, stateToken] = invocation;
216
+ const expansion = expandUtility(program, recipe, args);
217
+ if (expansion) matches.push([index, {
218
+ arguments: args,
219
+ expansion,
220
+ stateToken,
221
+ variableNames: [],
222
+ matcherType: "function"
223
+ }]);
224
+ return matches;
225
+ }
226
+ let end = 0;
227
+ while (end < source.length && !isClassSuffixStart(source[end])) end++;
228
+ for (const index of program.staticUtilities.get(source.slice(0, end)) ?? []) {
229
+ const matched = matchUtility(source, program.utilities[index], program, "static");
230
+ if (matched) matches.push([index, matched]);
231
+ }
232
+ if (matches.length) return matches;
233
+ const prefix = tokenPrefix(source, program);
234
+ return prefix === void 0 ? matches : tokenCandidates(source, prefix, program);
235
+ }
236
+ export { functionInvocation, isVariableKey, matchingUtilities, tokenCandidates, tokenPrefix, utilityVariable };
@@ -0,0 +1,254 @@
1
+ import { isAsciiCase, isAsciiDigit, isAsciiWhitespace, trimEnd } from "./text.js";
2
+ import { tokenize } from "./css-syntax.js";
3
+ // ../engine-js/src/value.ts
4
+ const MATH_FUNCTIONS = [
5
+ "calc",
6
+ "min",
7
+ "max",
8
+ "clamp"
9
+ ];
10
+ const isNumeric = (token) => token !== void 0 && (token.kind === 4 || token.kind === 5 || token.kind === 6);
11
+ /** Normalizes the math functions of a value, leaving strings, comments and URLs opaque. */
12
+ function normalizeCssMathFunctions(source) {
13
+ if (!source.includes("(")) return source;
14
+ const tokens = tokenize(source);
15
+ let output = "";
16
+ let copied = 0;
17
+ let index = 0;
18
+ while (index < tokens.length) {
19
+ const token = tokens[index];
20
+ if (token.kind !== 3 || token.close < 0) {
21
+ index++;
22
+ continue;
23
+ }
24
+ const close = token.close;
25
+ index = close + 1;
26
+ if (isAsciiCase(token.value, "url")) continue;
27
+ const start = token.end;
28
+ const end = tokens[close].start;
29
+ let inner = normalizeCssMathFunctions(source.slice(start, end));
30
+ if (MATH_FUNCTIONS.some((name) => isAsciiCase(token.value, name))) inner = normalizeMathExpression(inner);
31
+ output += source.slice(copied, start) + inner;
32
+ copied = end;
33
+ }
34
+ return output + source.slice(copied);
35
+ }
36
+ /**
37
+ * Spaces binary operators and commas. Token boundaries protect exponent signs and
38
+ * escaped or quoted identifiers; signed adjacent numbers and numeric subtraction
39
+ * inside compact dimensions are Master's two extensions to CSS tokenization.
40
+ */
41
+ function normalizeMathExpression(source) {
42
+ const tokens = tokenize(source);
43
+ const edits = [];
44
+ let operand = false;
45
+ let index = 0;
46
+ while (index < tokens.length) {
47
+ const token = tokens[index];
48
+ const raw = source.slice(token.start, token.end);
49
+ if (token.close >= 0) {
50
+ if (token.kind === 8 && token.value === "(") {
51
+ const start = token.end;
52
+ const end = tokens[token.close].start;
53
+ edits.push([
54
+ start,
55
+ end,
56
+ normalizeMathExpression(source.slice(start, end))
57
+ ]);
58
+ }
59
+ operand = true;
60
+ index = token.close + 1;
61
+ continue;
62
+ }
63
+ if (isNumeric(token)) {
64
+ if (operand && (raw[0] === "+" || raw[0] === "-")) edits.push([
65
+ token.start,
66
+ token.start + 1,
67
+ ` ${raw[0]} `
68
+ ]);
69
+ if (token.kind === 5 && !raw.includes("\\")) for (let minus = raw.indexOf("-", token.value.length); minus >= 0; minus = raw.indexOf("-", minus + 1)) {
70
+ const next = raw.charCodeAt(minus + 1);
71
+ if (minus + 1 === raw.length && tokens[index + 1]?.start === token.end && isNumeric(tokens[index + 1]) || isAsciiDigit(next) || next === 46 && isAsciiDigit(raw.charCodeAt(minus + 2))) {
72
+ edits.push([
73
+ token.start + minus,
74
+ token.end,
75
+ ` - ${normalizeMathExpression(raw.slice(minus + 1))}`
76
+ ]);
77
+ break;
78
+ }
79
+ }
80
+ operand = true;
81
+ } else if (token.kind === 8 && operand && "+-*/".includes(token.value)) {
82
+ edits.push([
83
+ token.start,
84
+ token.end,
85
+ ` ${token.value} `
86
+ ]);
87
+ operand = false;
88
+ } else if (token.kind === 8 && token.value === ",") {
89
+ edits.push([
90
+ token.start,
91
+ token.end,
92
+ ", "
93
+ ]);
94
+ operand = false;
95
+ } else operand = token.kind === 0;
96
+ index++;
97
+ }
98
+ for (const edit of edits) {
99
+ const replacement = edit[2];
100
+ if (replacement[0] !== " " && replacement[0] !== ",") continue;
101
+ if (replacement[0] === " ") while (edit[0] > 0 && isAsciiWhitespace(source.charCodeAt(edit[0] - 1))) edit[0]--;
102
+ while (edit[1] < source.length && isAsciiWhitespace(source.charCodeAt(edit[1]))) edit[1]++;
103
+ }
104
+ let output = "";
105
+ let copied = 0;
106
+ for (const [start, end, replacement] of edits) {
107
+ if (start < copied) continue;
108
+ output += source.slice(copied, start) + replacement;
109
+ copied = end;
110
+ }
111
+ return output + source.slice(copied);
112
+ }
113
+ const isVarReference = (tokens, index, end) => {
114
+ const name = tokens[index + 1];
115
+ return name?.kind === 0 && name.value.length > 2 && name.value.startsWith("--") && (index + 2 === end || tokens[index + 2]?.kind === 8 && tokens[index + 2].value === ",");
116
+ };
117
+ /** The custom properties a value references with `var()`, in source order, outside strings, comments and URLs. */
118
+ function collectCssVariableReferences(source) {
119
+ const names = [];
120
+ if (!source.includes("(")) return names;
121
+ const tokens = tokenize(source);
122
+ for (let index = 0; index < tokens.length; index++) {
123
+ const token = tokens[index];
124
+ if (token.kind !== 3) continue;
125
+ const end = token.close < 0 ? tokens.length : token.close;
126
+ if (isAsciiCase(token.value, "url")) {
127
+ index = Math.min(end + 1, tokens.length) - 1;
128
+ continue;
129
+ }
130
+ if (isAsciiCase(token.value, "var") && isVarReference(tokens, index, end)) {
131
+ const name = tokens[index + 1].value.slice(2);
132
+ if (!names.includes(name)) names.push(name);
133
+ }
134
+ }
135
+ return names;
136
+ }
137
+ /** Replaces `var()` references to inline theme tokens with their values. */
138
+ function substituteInlineTokens(source, program) {
139
+ if (!program.hasInlineTokens || !source.includes("(")) return source;
140
+ const tokens = tokenize(source);
141
+ let result = "";
142
+ let copied = 0;
143
+ let index = 0;
144
+ while (index < tokens.length) {
145
+ const token = tokens[index];
146
+ if (token.kind === 3 && token.close >= 0) {
147
+ const close = token.close;
148
+ if (isAsciiCase(token.value, "url")) {
149
+ index = close + 1;
150
+ continue;
151
+ }
152
+ const name = tokens[index + 1];
153
+ const value = isAsciiCase(token.value, "var") && name?.kind === 0 && name.value.startsWith("--") && (index + 2 === close || tokens[index + 2].kind === 8 && tokens[index + 2].value === ",") ? program.variables.get(name.value.slice(2))?.inlineValue : void 0;
154
+ if (value !== void 0) {
155
+ result += source.slice(copied, token.start) + value;
156
+ copied = tokens[close].end;
157
+ index = close + 1;
158
+ continue;
159
+ }
160
+ }
161
+ index++;
162
+ }
163
+ return result + source.slice(copied);
164
+ }
165
+ /** A value without its trailing `!important`, and whether it had one. */
166
+ function valueWithoutImportance(value) {
167
+ const tokens = tokenize(value);
168
+ const bang = tokens[tokens.length - 2];
169
+ const keyword = tokens[tokens.length - 1];
170
+ if (bang?.kind === 8 && bang.value === "!" && keyword.kind === 0 && isAsciiCase(keyword.value, "important")) return [trimEnd(value.slice(0, bang.start)), true];
171
+ return [value, false];
172
+ }
173
+ /**
174
+ * The value an inlined variable reference becomes: the last declared value, unless an
175
+ * earlier `!important` one outranks it; only when that value is an inline one.
176
+ */
177
+ function selectedInlineValue(values) {
178
+ if (!values.some((entry) => entry.inline)) return;
179
+ let selected;
180
+ let selectedImportant = false;
181
+ for (const entry of values) {
182
+ const [value, important] = valueWithoutImportance(entry.value);
183
+ if (selectedImportant && !important) continue;
184
+ selected = [entry.inline, value];
185
+ selectedImportant = important;
186
+ }
187
+ return selected?.[0] ? selected[1] : void 0;
188
+ }
189
+ const DIGITS = /^\d*$/;
190
+ function parseDecimal(text) {
191
+ const negative = text[0] === "-";
192
+ const unsigned = negative || text[0] === "+" ? text.slice(1) : text;
193
+ let mantissa = unsigned;
194
+ let exponent = 0;
195
+ const e = unsigned.search(/[eE]/);
196
+ if (e >= 0) {
197
+ const raw = unsigned.slice(e + 1);
198
+ const digits = raw[0] === "+" || raw[0] === "-" ? raw.slice(1) : raw;
199
+ if (!digits || !DIGITS.test(digits)) return;
200
+ const magnitude = Math.min(digits.replace(/^0+/, "").length > 7 ? Infinity : Number(digits), 1 << 20);
201
+ exponent = raw[0] === "-" ? -magnitude : magnitude;
202
+ mantissa = unsigned.slice(0, e);
203
+ }
204
+ const dot = mantissa.indexOf(".");
205
+ const integer = dot < 0 ? mantissa : mantissa.slice(0, dot);
206
+ const fraction = dot < 0 ? "" : mantissa.slice(dot + 1);
207
+ if (!integer && !fraction || !DIGITS.test(integer) || !DIGITS.test(fraction)) return;
208
+ const all = integer + fraction;
209
+ const leading = all.length - all.replace(/^0+/, "").length;
210
+ return {
211
+ negative,
212
+ digits: all.slice(leading).replace(/0+$/, ""),
213
+ point: integer.length - leading + exponent
214
+ };
215
+ }
216
+ /** `2^1024 − 2^970`, the least magnitude that `f64::from_str` rounds to infinity. */
217
+ const F64_OVERFLOW = "179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497792";
218
+ /** Whether `f64::from_str` parses the number to a finite value. */
219
+ function decimalIsFinite({ digits, point }) {
220
+ if (!digits || point !== 309) return !digits || point < 309;
221
+ for (let index = 0; index < 309; index++) {
222
+ const digit = digits[index] ?? "0";
223
+ if (digit !== F64_OVERFLOW[index]) return digit < F64_OVERFLOW[index];
224
+ }
225
+ return false;
226
+ }
227
+ /** Whether a digit string without leading zeros is below 2^53. */
228
+ const belowTwo53 = (digits) => digits.length < 16 || digits.length === 16 && digits < "9007199254740992";
229
+ /**
230
+ * The number as Rust's `Decimal::to_f64` computes it: exact for at most 15 significant
231
+ * digits within the exactly representable powers of ten, close to it otherwise.
232
+ */
233
+ function decimalToNumber({ negative, digits, point }) {
234
+ const significant = digits.slice(0, 19);
235
+ const exponent = point - significant.length;
236
+ let value = Number(significant || "0");
237
+ if (belowTwo53(significant) && exponent >= -22 && exponent <= 22) value = exponent < 0 ? value / Number(`1e${-exponent}`) : value * Number(`1e${exponent}`);
238
+ else if (exponent > 22 && exponent - 22 <= 19 && belowTwo53(significant + "0".repeat(exponent - 22))) value = Number(significant + "0".repeat(exponent - 22)) * 1e22;
239
+ else for (let step = Math.min(Math.abs(exponent), 400); step > 0; step--) value = exponent < 0 ? value / 10 : value * 10;
240
+ return negative ? -value : value;
241
+ }
242
+ /** An opacity from 0 to 1 as a percentage, computed on its digits so `.07` is `7`, not `7.000000000000001`. */
243
+ function alphaPercentage(alpha) {
244
+ const decimal = parseDecimal(alpha);
245
+ if (!decimal) return;
246
+ const { negative, digits } = decimal;
247
+ if (!digits) return "0";
248
+ if (negative || decimal.point > 1 || decimal.point === 1 && digits !== "1") return;
249
+ const point = decimal.point + 2;
250
+ if (point <= 0) return `0.${"0".repeat(-point)}${digits}`;
251
+ if (point >= digits.length) return digits + "0".repeat(point - digits.length);
252
+ return `${digits.slice(0, point)}.${digits.slice(point)}`;
253
+ }
254
+ export { alphaPercentage, collectCssVariableReferences, decimalIsFinite, decimalToNumber, normalizeCssMathFunctions, parseDecimal, selectedInlineValue, substituteInlineTokens, valueWithoutImportance };
package/dist/engine.js ADDED
@@ -0,0 +1,86 @@
1
+ import { MASTER_CSS_ENGINE_TRANSITION_VERSION } from "./protocol.js";
2
+ import { NativeBindingError } from "./errors.js";
3
+ import { loadNativeBinding } from "./native-loader.js";
4
+ import { MasterCSSError } from "@master/css-schema";
5
+ import { serializeMasterCSSManifest } from "@master/css-schema/manifest";
6
+ // src/engine.ts
7
+ function parse(value) {
8
+ return JSON.parse(value);
9
+ }
10
+ function globalsJSON(emittedGlobals) {
11
+ return emittedGlobals ? JSON.stringify(emittedGlobals) : void 0;
12
+ }
13
+ function bindingError(cause) {
14
+ if (cause instanceof MasterCSSError) return cause;
15
+ if (!(cause instanceof NativeBindingError)) throw cause;
16
+ return new MasterCSSError({
17
+ code: cause.code,
18
+ domain: "binding",
19
+ message: cause.message
20
+ }, { cause });
21
+ }
22
+ function createNativeEngineSession(options, moduleOptions = {}) {
23
+ try {
24
+ const loaded = loadNativeBinding(moduleOptions);
25
+ if (!loaded) return;
26
+ const { EngineSession } = loaded.binding;
27
+ const session = options.program ? EngineSession.fromProgram(options.program, globalsJSON(options.emittedGlobals)) : new EngineSession(serializeMasterCSSManifest(options.manifest), globalsJSON(options.emittedGlobals));
28
+ let disposed = false;
29
+ const dispose = () => {
30
+ if (disposed) return;
31
+ disposed = true;
32
+ session.dispose();
33
+ };
34
+ return {
35
+ ensureClassRules: (classNames) => parse(session.ensureClassRules([...classNames])),
36
+ deleteClassRules: (classNames) => parse(session.deleteClassRules([...classNames])),
37
+ registerEmittedGlobals: (emittedGlobals) => parse(session.registerEmittedGlobals(JSON.stringify(emittedGlobals))),
38
+ replaceEmittedGlobals: (emittedGlobals) => parse(session.replaceEmittedGlobals(JSON.stringify(emittedGlobals))),
39
+ refresh: (source, emittedGlobals) => parse(ArrayBuffer.isView(source) ? session.refreshProgram(source, globalsJSON(emittedGlobals)) : session.refresh(serializeMasterCSSManifest(source), globalsJSON(emittedGlobals))),
40
+ keyframeDefinitions: () => parse(session.keyframeDefinitions()),
41
+ executionState: (classNames) => parse(session.executionState([...classNames])),
42
+ inspect: (className) => parse(session.inspect(className)),
43
+ snapshot: () => parse(session.snapshot()),
44
+ dispose,
45
+ [Symbol.dispose]: dispose
46
+ };
47
+ } catch (cause) {
48
+ throw bindingError(cause);
49
+ }
50
+ }
51
+ function createNativeRenderSession(options, moduleOptions = {}) {
52
+ try {
53
+ const loaded = loadNativeBinding(moduleOptions);
54
+ if (!loaded) return;
55
+ const session = new loaded.binding.RenderSession(serializeMasterCSSManifest(options.manifest), globalsJSON(options.emittedGlobals));
56
+ let disposed = false;
57
+ const dispose = () => {
58
+ if (disposed) return;
59
+ disposed = true;
60
+ session.dispose();
61
+ };
62
+ return {
63
+ nativeDeclarationCandidates: (classNames) => parse(session.nativeDeclarationCandidates([...classNames])),
64
+ ensureClassRules: (classNames) => session.ensureClasses([...classNames]),
65
+ ensureStylesheetResources: (nativeCSS) => session.ensureStylesheetResources(nativeCSS),
66
+ emittedGlobals: () => parse(session.emittedGlobals()),
67
+ snapshot: () => parse(session.snapshot()),
68
+ snapshotForClassNames: (classNames) => parse(session.snapshotForClasses([...classNames])),
69
+ dispose,
70
+ [Symbol.dispose]: dispose
71
+ };
72
+ } catch (cause) {
73
+ throw bindingError(cause);
74
+ }
75
+ }
76
+ /** Compiles a manifest into the runtime program that browsers execute. */
77
+ function compileNativeRuntimeProgram(manifest, moduleOptions = {}) {
78
+ try {
79
+ const loaded = loadNativeBinding(moduleOptions);
80
+ if (!loaded) return;
81
+ return new Uint8Array(loaded.binding.compileRuntimeProgram(serializeMasterCSSManifest(manifest)));
82
+ } catch (cause) {
83
+ throw bindingError(cause);
84
+ }
85
+ }
86
+ export { MASTER_CSS_ENGINE_TRANSITION_VERSION, compileNativeRuntimeProgram, createNativeEngineSession, createNativeRenderSession };
package/dist/errors.js ADDED
@@ -0,0 +1,10 @@
1
+ // src/errors.ts
2
+ var NativeBindingError = class extends Error {
3
+ code;
4
+ constructor(code, message, options) {
5
+ super(message, options);
6
+ this.code = code;
7
+ this.name = "NativeBindingError";
8
+ }
9
+ };
10
+ export { NativeBindingError };
@@ -0,0 +1,4 @@
1
+ import { MASTER_CSS_BINDING_ABI_VERSION, MASTER_CSS_HYDRATION_MANIFEST_VERSION, MASTER_CSS_MANIFEST_VERSION, MASTER_CSS_PROGRAM_VERSION, MasterCSSBinding, MasterCSSBindingFeature, MasterCSSBindingInfo, MasterCSSBindingSurface, MasterCSSEngineResolvedBinding, MasterCSSResolvedBinding } from "./protocol.js";
2
+ import { MasterCSSBindingContractError, MasterCSSBindingRequirements, assertMasterCSSBindingInfo } from "./binding.js";
3
+ import { MasterCSSBindingLoadOptions, MasterCSSNativeBindingLoadOptions, MasterCSSWasmBindingLoadOptions } from "./binding-options.js";
4
+ export { MASTER_CSS_BINDING_ABI_VERSION, MASTER_CSS_HYDRATION_MANIFEST_VERSION, MASTER_CSS_MANIFEST_VERSION, MASTER_CSS_PROGRAM_VERSION, type MasterCSSBinding, MasterCSSBindingContractError, type MasterCSSBindingFeature, type MasterCSSBindingInfo, type MasterCSSBindingLoadOptions, type MasterCSSBindingRequirements, type MasterCSSBindingSurface, type MasterCSSEngineResolvedBinding, type MasterCSSNativeBindingLoadOptions, type MasterCSSResolvedBinding, type MasterCSSWasmBindingLoadOptions, assertMasterCSSBindingInfo };
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ import { MASTER_CSS_BINDING_ABI_VERSION, MASTER_CSS_HYDRATION_MANIFEST_VERSION, MASTER_CSS_MANIFEST_VERSION, MASTER_CSS_PROGRAM_VERSION } from "./protocol.js";
2
+ import { MasterCSSBindingContractError, assertMasterCSSBindingInfo } from "./binding.js";
3
+ export { MASTER_CSS_BINDING_ABI_VERSION, MASTER_CSS_HYDRATION_MANIFEST_VERSION, MASTER_CSS_MANIFEST_VERSION, MASTER_CSS_PROGRAM_VERSION, MasterCSSBindingContractError, assertMasterCSSBindingInfo };