@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,38 @@
1
+ import { normalizeBindingError } from "./normalize-error.js";
2
+ import { bindEngineBindingSession, bindRenderBindingSession } from "./engine-binding-adapter.js";
3
+ import { compileNativeRuntimeProgram, createNativeEngineSession, createNativeRenderSession } from "./engine.js";
4
+ // src/engine-binding-node.ts
5
+ function createEngineBindingSessionSync(options, loadOptions = {}) {
6
+ try {
7
+ const session = createNativeEngineSession(options, {
8
+ ...loadOptions,
9
+ required: true
10
+ });
11
+ return bindEngineBindingSession("native", session);
12
+ } catch (cause) {
13
+ throw normalizeBindingError(cause, "engine");
14
+ }
15
+ }
16
+ function createRenderBindingSessionSync(options, loadOptions = {}) {
17
+ try {
18
+ const session = createNativeRenderSession(options, {
19
+ ...loadOptions,
20
+ required: true
21
+ });
22
+ return bindRenderBindingSession("native", session);
23
+ } catch (cause) {
24
+ throw normalizeBindingError(cause, "server");
25
+ }
26
+ }
27
+ /** Compiles a manifest into the runtime program that browsers execute. */
28
+ function compileRuntimeProgramSync(manifest, loadOptions = {}) {
29
+ try {
30
+ return compileNativeRuntimeProgram(manifest, {
31
+ ...loadOptions,
32
+ required: true
33
+ });
34
+ } catch (cause) {
35
+ throw normalizeBindingError(cause, "engine");
36
+ }
37
+ }
38
+ export { compileRuntimeProgramSync, createEngineBindingSessionSync, createRenderBindingSessionSync };
@@ -0,0 +1,64 @@
1
+ import { assertMasterCSSBindingInfo } from "./binding.js";
2
+ import { serializeMasterCSSManifest } from "@master/css-schema/manifest";
3
+ // src/engine-binding-wasm.ts
4
+ async function loadDefaultWasmProvider(options) {
5
+ const { createMasterCSSEngineWasmProvider } = await import("@master/css-binding-wasm-engine");
6
+ return await createMasterCSSEngineWasmProvider(options);
7
+ }
8
+ async function createWasmProvider(feature, options, factory = loadDefaultWasmProvider) {
9
+ const provider = await factory(options);
10
+ assertMasterCSSBindingInfo(provider.info, {
11
+ surface: "runtime",
12
+ features: [feature]
13
+ });
14
+ return provider;
15
+ }
16
+ function lifecycle(session) {
17
+ let disposed = false;
18
+ const dispose = () => {
19
+ if (disposed) return;
20
+ disposed = true;
21
+ session.dispose();
22
+ };
23
+ return {
24
+ binding: "wasm",
25
+ dispose,
26
+ [Symbol.dispose]: dispose
27
+ };
28
+ }
29
+ function wasmSource(source) {
30
+ return ArrayBuffer.isView(source) ? source : serializeMasterCSSManifest(source);
31
+ }
32
+ async function createWasmEngineBindingSession(options, loadOptions, providerFactory) {
33
+ const session = await (await createWasmProvider("engine", loadOptions, providerFactory)).createEngineSession(wasmSource(options.program ?? options.manifest), options.emittedGlobals);
34
+ const bound = {
35
+ ...lifecycle(session),
36
+ ensureClassRules: (classNames) => session.ensureClassRules([...classNames]),
37
+ deleteClassRules: (classNames) => session.deleteClassRules([...classNames]),
38
+ registerEmittedGlobals: (emittedGlobals) => session.registerEmittedGlobals(emittedGlobals),
39
+ replaceEmittedGlobals: (emittedGlobals) => session.replaceEmittedGlobals(emittedGlobals),
40
+ refresh: (source, emittedGlobals) => session.refresh(wasmSource(source), emittedGlobals),
41
+ keyframeDefinitions: () => session.keyframeDefinitions(),
42
+ executionState: (classNames) => session.executionState([...classNames]),
43
+ inspect: (className) => session.inspect(className),
44
+ snapshot: () => session.snapshot()
45
+ };
46
+ return Object.freeze(bound);
47
+ }
48
+ async function createWasmRenderBindingSession(options, loadOptions, providerFactory) {
49
+ const session = await (await createWasmProvider("render", loadOptions, providerFactory)).createRenderSession(serializeMasterCSSManifest(options.manifest), options.emittedGlobals ? JSON.stringify(options.emittedGlobals) : void 0);
50
+ const bound = {
51
+ ...lifecycle(session),
52
+ nativeDeclarationCandidates: (classNames) => session.nativeDeclarationCandidates(classNames),
53
+ ensureClassRules: (classNames) => session.ensureClassRules(classNames),
54
+ ensureStylesheetResources: (nativeCSS) => session.ensureStylesheetResources(nativeCSS),
55
+ emittedGlobals: () => session.emittedGlobals(),
56
+ snapshot: () => session.snapshot(),
57
+ snapshotForClassNames: (classNames) => session.snapshotForClassNames(classNames)
58
+ };
59
+ return Object.freeze(bound);
60
+ }
61
+ async function compileWasmRuntimeProgram(manifest, loadOptions, providerFactory) {
62
+ return await (await createWasmProvider("engine", loadOptions, providerFactory)).compileRuntimeProgram(serializeMasterCSSManifest(manifest));
63
+ }
64
+ export { compileWasmRuntimeProgram, createWasmEngineBindingSession, createWasmRenderBindingSession };
@@ -0,0 +1,40 @@
1
+ import { MasterCSSEngineExecutionState, MasterCSSEngineInspection, MasterCSSEngineResolvedBinding, MasterCSSEngineSnapshot, MasterCSSEngineTransition, MasterCSSNativeDeclarationCandidate, MasterCSSResolvedBinding, MasterCSSServerRender } from "./protocol.js";
2
+ import { MasterCSSBindingLoadOptions, MasterCSSNativeBindingLoadOptions, MasterCSSWasmBindingLoadOptions } from "./binding-options.js";
3
+ import { MasterCSSEngineSource } from "./engine-contract.js";
4
+ import { MasterCSSKeyframeDefinition, MasterCSSManifest } from "@master/css-schema/manifest";
5
+ import { MasterCSSEmittedGlobals } from "@master/css-schema/emitted-globals";
6
+ type MasterCSSEngineBindingSessionOptions = MasterCSSEngineSource & {
7
+ readonly emittedGlobals?: MasterCSSEmittedGlobals;
8
+ };
9
+ interface MasterCSSRenderBindingSessionOptions {
10
+ readonly manifest: MasterCSSManifest;
11
+ readonly emittedGlobals?: MasterCSSEmittedGlobals;
12
+ }
13
+ interface MasterCSSEngineBindingSession extends Disposable {
14
+ readonly binding: MasterCSSEngineResolvedBinding;
15
+ ensureClassRules(classNames: readonly string[]): MasterCSSEngineTransition;
16
+ deleteClassRules(classNames: readonly string[]): MasterCSSEngineTransition;
17
+ registerEmittedGlobals(emittedGlobals: MasterCSSEmittedGlobals): MasterCSSEngineTransition;
18
+ replaceEmittedGlobals(emittedGlobals: MasterCSSEmittedGlobals): MasterCSSEngineTransition;
19
+ refresh(source: MasterCSSManifest | Uint8Array, emittedGlobals?: MasterCSSEmittedGlobals): MasterCSSEngineTransition;
20
+ keyframeDefinitions(): readonly MasterCSSKeyframeDefinition[];
21
+ executionState(classNames: readonly string[]): MasterCSSEngineExecutionState;
22
+ inspect(className: string): MasterCSSEngineInspection;
23
+ snapshot(): MasterCSSEngineSnapshot;
24
+ dispose(): void;
25
+ }
26
+ interface MasterCSSRenderBindingSession extends Disposable {
27
+ readonly binding: MasterCSSResolvedBinding;
28
+ nativeDeclarationCandidates(classNames: readonly string[]): readonly MasterCSSNativeDeclarationCandidate[];
29
+ ensureClassRules(classNames: readonly string[]): void;
30
+ ensureStylesheetResources(nativeCSS: string): void;
31
+ emittedGlobals(): MasterCSSEmittedGlobals;
32
+ snapshot(): MasterCSSServerRender;
33
+ snapshotForClassNames(classNames: readonly string[]): MasterCSSServerRender;
34
+ dispose(): void;
35
+ }
36
+ declare function createEngineBindingSession(options: MasterCSSEngineBindingSessionOptions, loadOptions?: MasterCSSBindingLoadOptions): Promise<MasterCSSEngineBindingSession>;
37
+ declare function createRenderBindingSession(options: MasterCSSRenderBindingSessionOptions, loadOptions?: MasterCSSBindingLoadOptions): Promise<MasterCSSRenderBindingSession>;
38
+ /** Compiles a manifest into the runtime program that browsers execute. */
39
+ declare function compileRuntimeProgram(manifest: MasterCSSManifest, loadOptions?: MasterCSSBindingLoadOptions): Promise<Uint8Array>;
40
+ export { type MasterCSSBindingLoadOptions, MasterCSSEngineBindingSession, MasterCSSEngineBindingSessionOptions, type MasterCSSEngineSource, type MasterCSSNativeBindingLoadOptions, MasterCSSRenderBindingSession, MasterCSSRenderBindingSessionOptions, type MasterCSSWasmBindingLoadOptions, compileRuntimeProgram, createEngineBindingSession, createRenderBindingSession };
@@ -0,0 +1,57 @@
1
+ import { normalizeBindingError } from "./normalize-error.js";
2
+ import { hasMasterCSSNodeRuntime, shouldLoadMasterCSSNativeBinding } from "./binding-options.js";
3
+ import { compileWasmRuntimeProgram, createWasmEngineBindingSession, createWasmRenderBindingSession } from "./engine-binding-wasm.js";
4
+ import { bindEngineBindingSession, bindRenderBindingSession } from "./engine-binding-adapter.js";
5
+ import { createJavaScriptEngineBindingSession } from "./engine-binding-js.js";
6
+ // src/engine-binding.ts
7
+ async function loadNativeEngineFactories() {
8
+ return await (import.meta.url.endsWith(".ts") ? import("./engine.js") : import("./engine.js"));
9
+ }
10
+ async function createEngineBindingSession(options, loadOptions = {}) {
11
+ try {
12
+ if (shouldLoadMasterCSSNativeBinding(loadOptions.binding)) {
13
+ const { createNativeEngineSession } = await loadNativeEngineFactories();
14
+ const native = createNativeEngineSession(options, {
15
+ ...loadOptions.native,
16
+ required: loadOptions.binding === "native"
17
+ });
18
+ if (native) return bindEngineBindingSession("native", native);
19
+ }
20
+ if (loadOptions.binding !== "wasm" && options.program && !hasMasterCSSNodeRuntime()) return createJavaScriptEngineBindingSession(options);
21
+ return bindEngineBindingSession("wasm", await createWasmEngineBindingSession(options, loadOptions.wasm));
22
+ } catch (cause) {
23
+ throw normalizeBindingError(cause, "engine");
24
+ }
25
+ }
26
+ async function createRenderBindingSession(options, loadOptions = {}) {
27
+ try {
28
+ if (shouldLoadMasterCSSNativeBinding(loadOptions.binding)) {
29
+ const { createNativeRenderSession } = await loadNativeEngineFactories();
30
+ const native = createNativeRenderSession(options, {
31
+ ...loadOptions.native,
32
+ required: loadOptions.binding === "native"
33
+ });
34
+ if (native) return bindRenderBindingSession("native", native);
35
+ }
36
+ return bindRenderBindingSession("wasm", await createWasmRenderBindingSession(options, loadOptions.wasm));
37
+ } catch (cause) {
38
+ throw normalizeBindingError(cause, "server");
39
+ }
40
+ }
41
+ /** Compiles a manifest into the runtime program that browsers execute. */
42
+ async function compileRuntimeProgram(manifest, loadOptions = {}) {
43
+ try {
44
+ if (shouldLoadMasterCSSNativeBinding(loadOptions.binding)) {
45
+ const { compileNativeRuntimeProgram } = await loadNativeEngineFactories();
46
+ const program = compileNativeRuntimeProgram(manifest, {
47
+ ...loadOptions.native,
48
+ required: loadOptions.binding === "native"
49
+ });
50
+ if (program) return program;
51
+ }
52
+ return await compileWasmRuntimeProgram(manifest, loadOptions.wasm);
53
+ } catch (cause) {
54
+ throw normalizeBindingError(cause, "engine");
55
+ }
56
+ }
57
+ export { compileRuntimeProgram, createEngineBindingSession, createRenderBindingSession };
@@ -0,0 +1,14 @@
1
+ import { MasterCSSKeyframeDefinition, MasterCSSManifest } from "@master/css-schema/manifest";
2
+ import { MasterCSSEmittedGlobals } from "@master/css-schema/emitted-globals";
3
+ /**
4
+ * What an engine session executes: a manifest, which only Node hosts compile, or a
5
+ * runtime program that `compileRuntimeProgram()` encoded.
6
+ */
7
+ type MasterCSSEngineSource = {
8
+ readonly manifest: MasterCSSManifest;
9
+ readonly program?: never;
10
+ } | {
11
+ readonly program: Uint8Array;
12
+ readonly manifest?: never;
13
+ };
14
+ export { MasterCSSEngineSource };
@@ -0,0 +1,154 @@
1
+ import { asciiLowercase, isAsciiCase } from "./text.js";
2
+ import { collectStatements, tokenize } from "./css-syntax.js";
3
+ // ../engine-js/src/animation.ts
4
+ /** Authored declarations, without those inside keyframes, which CSS ignores. */
5
+ function stylesheetDeclarations(source) {
6
+ const tokens = tokenize(source);
7
+ const statements = collectStatements(tokens);
8
+ const declarations = [];
9
+ for (const statement of statements) {
10
+ if (!statement.declaration || statement.end - statement.start < 3) continue;
11
+ let inKeyframes = false;
12
+ for (let parent = statement.parent; parent >= 0; parent = statements[parent].parent) {
13
+ const head = tokens[statements[parent].start];
14
+ if (head.kind === 2 && (isAsciiCase(head.value, "keyframes") || isAsciiCase(head.value, "-webkit-keyframes"))) {
15
+ inKeyframes = true;
16
+ break;
17
+ }
18
+ }
19
+ const property = tokens[statement.start];
20
+ if (inKeyframes || property.kind !== 0) continue;
21
+ declarations.push([property.value, source.slice(tokens[statement.start + 2].start, tokens[statement.end - 1].end)]);
22
+ }
23
+ return declarations;
24
+ }
25
+ function analyzeAnimations(declarations, program) {
26
+ const result = {
27
+ names: [],
28
+ retainAll: false
29
+ };
30
+ if (!program.keyframes.length) return result;
31
+ const variables = /* @__PURE__ */ new Map();
32
+ for (const [name, value] of declarations) {
33
+ if (!name.startsWith("--")) continue;
34
+ const values = variables.get(name.slice(2));
35
+ if (values) values.push(value);
36
+ else variables.set(name.slice(2), [value]);
37
+ }
38
+ for (const [name, value] of declarations) {
39
+ let property = asciiLowercase(name);
40
+ if (property.startsWith("-webkit-")) property = property.slice(8);
41
+ if (property !== "animation" && property !== "animation-name") continue;
42
+ const values = resolve(value, program, variables, /* @__PURE__ */ new Set(), { remaining: 256 });
43
+ if (values) for (const option of values) parseNames(option, property === "animation-name", result);
44
+ else result.retainAll = true;
45
+ }
46
+ result.names = result.names.filter((name) => program.keyframes.some((definition) => definition.name === name));
47
+ return result;
48
+ }
49
+ /** Every value a `var()` chain may substitute, or undefined when any is unknown. */
50
+ function resolve(value, program, variables, stack, budget) {
51
+ if (!budget.remaining || stack.size > 64) return;
52
+ budget.remaining--;
53
+ const tokens = tokenize(value);
54
+ const index = tokens.findIndex((token) => token.kind === 3 && isAsciiCase(token.value, "var"));
55
+ if (index < 0) return [value];
56
+ const token = tokens[index];
57
+ if (token.close < 0) return;
58
+ const nameToken = tokens[index + 1];
59
+ if (nameToken?.kind !== 0 || !nameToken.value.startsWith("--")) return;
60
+ const name = nameToken.value.slice(2);
61
+ if (stack.has(name)) return;
62
+ stack.add(name);
63
+ const options = (program.variables.get(name)?.values ?? []).map((entry) => entry.value);
64
+ options.push(...program.animationVariables.get(name) ?? [], ...variables.get(name) ?? []);
65
+ if (!options.length) {
66
+ stack.delete(name);
67
+ return;
68
+ }
69
+ const comma = tokens[index + 2];
70
+ if (comma?.kind === 8 && comma.value === ",") options.push(value.slice(comma.end, tokens[token.close].start));
71
+ const output = [];
72
+ for (const option of options) {
73
+ const optionTokens = tokenize(option);
74
+ const bang = optionTokens[optionTokens.length - 2];
75
+ const last = optionTokens[optionTokens.length - 1];
76
+ const replacements = resolve(bang?.kind === 8 && bang.value === "!" && last.kind === 0 && isAsciiCase(last.value, "important") ? option.slice(0, bang.start) : option, program, variables, stack, budget);
77
+ if (!replacements) return;
78
+ for (const replacement of replacements) {
79
+ const expanded = value.slice(0, token.start) + replacement + value.slice(tokens[token.close].end);
80
+ stack.delete(name);
81
+ const resolved = resolve(expanded, program, variables, stack, budget);
82
+ if (!resolved) return;
83
+ output.push(...resolved);
84
+ stack.add(name);
85
+ }
86
+ }
87
+ stack.delete(name);
88
+ return output;
89
+ }
90
+ const KEYWORD_CATEGORIES = {
91
+ ease: "timing",
92
+ linear: "timing",
93
+ "ease-in": "timing",
94
+ "ease-out": "timing",
95
+ "ease-in-out": "timing",
96
+ "step-start": "timing",
97
+ "step-end": "timing",
98
+ infinite: "iteration",
99
+ normal: "direction",
100
+ reverse: "direction",
101
+ alternate: "direction",
102
+ "alternate-reverse": "direction",
103
+ none: "fill",
104
+ forwards: "fill",
105
+ backwards: "fill",
106
+ both: "fill",
107
+ running: "play",
108
+ paused: "play",
109
+ auto: "duration"
110
+ };
111
+ const MATH = /* @__PURE__ */ new Set([
112
+ "calc",
113
+ "min",
114
+ "max",
115
+ "clamp",
116
+ "round",
117
+ "mod",
118
+ "rem",
119
+ "abs",
120
+ "sign"
121
+ ]);
122
+ function parseNames(value, namesOnly, result) {
123
+ const tokens = tokenize(value);
124
+ const used = /* @__PURE__ */ new Set();
125
+ for (let cursor = 0; cursor < tokens.length; cursor++) {
126
+ const token = tokens[cursor];
127
+ let name;
128
+ if (token.kind === 8 && token.value === ",") used.clear();
129
+ else if (token.kind === 8 && token.value === "!") break;
130
+ else if (token.kind === 1) name = token.value;
131
+ else if (token.kind === 0) {
132
+ const keyword = asciiLowercase(token.value);
133
+ if (keyword === "initial" || keyword === "inherit" || keyword === "unset" || keyword === "revert" || keyword === "revert-layer") {
134
+ if (keyword === "inherit" || keyword.startsWith("revert")) result.retainAll = true;
135
+ } else if (namesOnly) {
136
+ if (keyword !== "none") name = token.value;
137
+ } else {
138
+ const category = Object.hasOwn(KEYWORD_CATEGORIES, keyword) ? KEYWORD_CATEGORIES[keyword] : void 0;
139
+ const fresh = category !== void 0 && !used.has(category);
140
+ if (category !== void 0) used.add(category);
141
+ if (!fresh && keyword !== "none") name = token.value;
142
+ }
143
+ } else if (token.kind === 3) {
144
+ const fn = asciiLowercase(token.value);
145
+ if (fn === "steps" || fn === "cubic-bezier" || fn === "linear") used.add("timing");
146
+ else if (!MATH.has(fn)) result.retainAll = true;
147
+ if (token.close >= 0) cursor = token.close;
148
+ else result.retainAll = true;
149
+ } else if (token.kind === 4) used.add("iteration");
150
+ else if (token.kind !== 5 && token.kind !== 6) result.retainAll = true;
151
+ if (name !== void 0 && !result.names.includes(name)) result.names.push(name);
152
+ }
153
+ }
154
+ export { analyzeAnimations, stylesheetDeclarations };
@@ -0,0 +1,207 @@
1
+ import { trim } from "./text.js";
2
+ import { tokenize } from "./css-syntax.js";
3
+ import { collectCssVariableReferences, substituteInlineTokens } from "./value.js";
4
+ import { cssEscape } from "./program.js";
5
+ import { decodeNativeContent, parseFunctionalClass, parseNativeDeclaration, splitStateToken } from "./class-syntax.js";
6
+ import { atomicShape } from "./order.js";
7
+ import { conditionPriority, parseCustomMediaQuery, parseNativeQuery, queryRequiresCss, renderConditionToken, resolveLayerCondition } from "./condition.js";
8
+ import { replaceNestingSelector, selectorPriority, selectorTokenToTemplate, validSelectorStructure } from "./selector.js";
9
+ import { expandBody, expandMixin, expandUtility } from "./mixin.js";
10
+ import { resolveStateBranches } from "./state.js";
11
+ import { functionInvocation, matchingUtilities, tokenPrefix } from "./utility.js";
12
+ import { addAnimationReferences, compositionRules, formatDeclaration, nativeDeclaration, rulePriority, wrapRawConditions } from "./generate.js";
13
+ // ../engine-js/src/apply.ts
14
+ /** The CSS mixin call inside an `@apply(…)` suffix: a complete dashed call or name. */
15
+ function parseMixinCall(source) {
16
+ const head = parseFunctionalClass(source);
17
+ if (head !== void 0) {
18
+ if (typeof head === "string" || !head.name.startsWith("--") || head.suffix) return;
19
+ return [head.name, head.arguments.map(trim)];
20
+ }
21
+ const tokens = tokenize(source);
22
+ if (tokens.length === 1 && tokens[0].kind === 0 && tokens[0].value.startsWith("--")) return [tokens[0].value, []];
23
+ }
24
+ /** The mixin call of an `apply(…)` condition token; null when it is malformed, undefined for other tokens. */
25
+ function applyInvocation(token) {
26
+ if (!token.startsWith("apply(")) return;
27
+ const body = token.endsWith(")") ? decodeNativeContent(token.slice(6, -1)) : void 0;
28
+ return (body === void 0 ? void 0 : parseMixinCall(body)) ?? null;
29
+ }
30
+ /** Whether a function class or a matched recipe fails to expand. */
31
+ function hasExpansionError(source, program) {
32
+ const invocation = functionInvocation(source, program);
33
+ if (invocation !== void 0) return !invocation || !expandUtility(program, invocation[1], invocation[2]);
34
+ return matchingUtilities(source, program).some(([index, matched]) => {
35
+ const { emit } = program.utilities[index];
36
+ return emit.type === "recipe" && !expandUtility(program, program.utilityDefinitions[emit.definition], matched.arguments);
37
+ });
38
+ }
39
+ /** Whether the Rust engine reports any error diagnostic for a class. */
40
+ function hasDiagnostics(className, program) {
41
+ const source = className.endsWith("!") ? className.slice(0, -1) : className;
42
+ const declaration = parseNativeDeclaration(source);
43
+ if (declaration === null) return true;
44
+ const stateSource = declaration ? source.slice(declaration.suffixStart) : source;
45
+ if (!declaration && hasExpansionError(source, program)) return true;
46
+ if (decodeNativeContent(stateSource) === void 0) return true;
47
+ const matches = declaration ? [] : matchingUtilities(source, program);
48
+ const states = declaration ? [stateSource] : matches.map(([, matched]) => matched.stateToken);
49
+ for (const state of states) {
50
+ const [selector] = splitStateToken(state[0] === "!" ? state.slice(1) : state);
51
+ if (selector && !validSelectorStructure(selectorTokenToTemplate(selector))) return true;
52
+ }
53
+ let layer;
54
+ for (const token of splitStateToken(stateSource)[1]) {
55
+ const call = applyInvocation(token);
56
+ if (call !== void 0) {
57
+ if (!call || !expandMixin(program, call[0], call[1], [])) return true;
58
+ continue;
59
+ }
60
+ const next = resolveLayerCondition(token);
61
+ if (next) {
62
+ if (layer && layer !== next) return true;
63
+ layer = next;
64
+ continue;
65
+ }
66
+ if (queryRequiresCss(token)) return true;
67
+ const query = parseNativeQuery(token);
68
+ if (query?.kind === "media" && query.prelude.includes("--") && !parseCustomMediaQuery(query.prelude, (name) => program.customMedia.get(name))) return true;
69
+ if (!program.customMedia.has(`--${token}`) && !renderConditionToken(token, program)) return true;
70
+ }
71
+ return !declaration && !matches.length && tokenPrefix(source, program) !== void 0;
72
+ }
73
+ const textValue = (value) => [{
74
+ type: "text",
75
+ value
76
+ }];
77
+ function expandApplication(className, head, suffixes, program) {
78
+ if (hasDiagnostics(className, program)) return;
79
+ const important = className.endsWith("!");
80
+ const native = !!parseNativeDeclaration(head);
81
+ const [first] = matchingUtilities(head, program);
82
+ const state = first ? first[1].stateToken : nativeDeclaration(head)?.[1].stateToken ?? "";
83
+ const base = head.endsWith(state) ? head.slice(0, head.length - state.length) : head;
84
+ if (hasDiagnostics(base, program)) return;
85
+ const originals = compositionRules(base, program);
86
+ if (!originals.length) return;
87
+ let layer;
88
+ const setLayer = (next) => {
89
+ if (layer && layer !== next) return false;
90
+ layer = next;
91
+ return true;
92
+ };
93
+ const body = [];
94
+ for (const rule of originals) {
95
+ if (rule.explicitLayer && !setLayer(rule.explicitLayer)) return;
96
+ let nodes = rule.declarations.map(([property, value]) => ({
97
+ type: "declaration",
98
+ property,
99
+ value: textValue(value)
100
+ }));
101
+ if (rule.selector !== "&") nodes = [{
102
+ type: "rule",
103
+ selector: rule.selector,
104
+ body: nodes
105
+ }];
106
+ for (let index = rule.conditions.length - 1; index >= 0; index--) nodes = [{
107
+ type: "condition",
108
+ condition: rule.conditions[index],
109
+ body: nodes
110
+ }];
111
+ body.push(...nodes);
112
+ }
113
+ const options = [];
114
+ for (const suffix of suffixes) {
115
+ const call = applyInvocation(suffix);
116
+ const next = call === void 0 ? resolveLayerCondition(suffix) : void 0;
117
+ if (call === null || next && !setLayer(next)) return;
118
+ const branches = call === void 0 && !next ? resolveStateBranches(`@${suffix}`, false, program) : void 0;
119
+ if (branches && !branches.length && !program.customMedia.has(`--${suffix}`)) return;
120
+ options.push(branches);
121
+ }
122
+ const template = state ? selectorTokenToTemplate(state) : void 0;
123
+ let combinations = [[]];
124
+ for (const branches of options) if (branches) combinations = combinations.flatMap((chosen) => branches.map((branch) => [...chosen, branch]));
125
+ const primary = originals[0];
126
+ const anchor = `.${cssEscape(className)}`;
127
+ const stored = [];
128
+ for (const [group, chosen] of combinations.entries()) {
129
+ let nodes = body;
130
+ let at = chosen.length;
131
+ for (let index = suffixes.length - 1; index >= 0; index--) {
132
+ const call = applyInvocation(suffixes[index]);
133
+ if (call) nodes = [{
134
+ type: "apply",
135
+ name: call[0],
136
+ arguments: call[1].map(textValue),
137
+ contents: nodes
138
+ }];
139
+ else if (options[index]) nodes = chosen[--at].conditionWrappers.reduceRight((contents, [, condition]) => [{
140
+ type: "condition",
141
+ condition,
142
+ body: contents
143
+ }], nodes);
144
+ }
145
+ if (template !== void 0) nodes = [{
146
+ type: "rule",
147
+ selector: template,
148
+ body: nodes
149
+ }];
150
+ const expanded = expandBody(program, nodes);
151
+ if (!expanded) return;
152
+ if (!expanded.length) continue;
153
+ const outer = chosen.flatMap((branch) => branch.conditionWrappers);
154
+ const texts = [];
155
+ const selectors = [];
156
+ const declarations = expanded.map((rule) => {
157
+ const text = rule.declarations.map(([property, raw]) => {
158
+ const value = substituteInlineTokens(raw, program);
159
+ if (!important) return `${property}:${value}`;
160
+ const declaration = formatDeclaration(property, value, true);
161
+ return `${property}:${declaration.slice(declaration.indexOf(":") + 1)}`;
162
+ }).join(";");
163
+ const selector = replaceNestingSelector(rule.selector, anchor) ?? rule.selector;
164
+ texts.push(wrapRawConditions(`${selector}{${text}}`, rule.conditions));
165
+ selectors.push(selector);
166
+ return text;
167
+ }).join(";");
168
+ const [only] = expanded;
169
+ const shape = expanded.length === 1 && only.selector === (template ?? "&") && only.conditions.length === outer.length && only.declarations.length === 1 ? native ? { category: 2 } : atomicShape(...only.declarations[0]) : { category: 0 };
170
+ const [features, conditions] = conditionPriority(outer);
171
+ const ir = {
172
+ className,
173
+ key: group ? `${className}\0${group}` : className,
174
+ layer: layer ?? primary.layer,
175
+ type: primary.type,
176
+ sortTier: outer.length ? 3 : template === void 0 ? 0 : 1,
177
+ priority: rulePriority(features, selectorPriority(template), conditions, primary.valuePriority, declarations, shape),
178
+ text: texts.join("")
179
+ };
180
+ if (texts.length > 1) ir.nodes = texts.map((text) => ({ text }));
181
+ if (selectors.length === 1) ir.selectorText = selectors[0];
182
+ const variableNames = collectCssVariableReferences(declarations).filter((name) => program.variables.has(name));
183
+ if (variableNames.length) ir.variableNames = variableNames;
184
+ addAnimationReferences(ir, declarations, program);
185
+ stored.push({
186
+ ir,
187
+ features
188
+ });
189
+ }
190
+ return stored;
191
+ }
192
+ /** The rule of an `@apply` class, or undefined when the class has no `@apply` suffix. */
193
+ function applicationRules(className, program) {
194
+ if (!className.includes("@apply(")) return;
195
+ const source = className.endsWith("!") ? className.slice(0, -1) : className;
196
+ const declaration = parseNativeDeclaration(source);
197
+ let head;
198
+ let suffixes;
199
+ if (declaration) {
200
+ const [selector, conditions] = splitStateToken(source.slice(declaration.suffixStart));
201
+ head = source.slice(0, declaration.suffixStart) + selector;
202
+ suffixes = conditions;
203
+ } else [head, suffixes] = splitStateToken(source);
204
+ if (!suffixes.some((suffix) => suffix.startsWith("apply("))) return;
205
+ return expandApplication(className, head, suffixes, program) ?? [];
206
+ }
207
+ export { applicationRules };