cssints 0.0.0-stage → 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/LICENSE +21 -0
- package/README.md +188 -2
- package/dist/author-types-C1AhsnrT.d.mts +80 -0
- package/dist/check.d.mts +22 -0
- package/dist/check.mjs +37 -0
- package/dist/color-BYIxVLlS.mjs +29 -0
- package/dist/color-C8OzjAeg.mjs +2 -0
- package/dist/contrast-DhK69Xak.mjs +83 -0
- package/dist/derived.d.mts +14 -0
- package/dist/derived.mjs +391 -0
- package/dist/errors-D4ZbcwRo.d.mts +32 -0
- package/dist/frame-BoBKjgBB.mjs +92 -0
- package/dist/frame.d.mts +72 -0
- package/dist/frame.mjs +2 -0
- package/dist/group-common-9zpBxfUF.d.mts +1 -0
- package/dist/group-types-9ttphdku.d.mts +55 -0
- package/dist/groups/compositing-2.d.mts +20 -0
- package/dist/groups/css-align-3.d.mts +29 -0
- package/dist/groups/css-anchor-position-1.d.mts +49 -0
- package/dist/groups/css-anchor-position-2.d.mts +50 -0
- package/dist/groups/css-animations-1.d.mts +28 -0
- package/dist/groups/css-animations-2.d.mts +29 -0
- package/dist/groups/css-backgrounds-3.d.mts +27 -0
- package/dist/groups/css-backgrounds-4.d.mts +29 -0
- package/dist/groups/css-borders-4.d.mts +95 -0
- package/dist/groups/css-box-4.d.mts +38 -0
- package/dist/groups/css-break-4.d.mts +23 -0
- package/dist/groups/css-cascade-5.d.mts +18 -0
- package/dist/groups/css-cascade-6.d.mts +18 -0
- package/dist/groups/css-color-4.d.mts +29 -0
- package/dist/groups/css-color-5.d.mts +32 -0
- package/dist/groups/css-color-6.d.mts +32 -0
- package/dist/groups/css-color-adjust-1.d.mts +20 -0
- package/dist/groups/css-color-hdr-1.d.mts +19 -0
- package/dist/groups/css-conditional-3.d.mts +17 -0
- package/dist/groups/css-conditional-4.d.mts +17 -0
- package/dist/groups/css-conditional-5.d.mts +22 -0
- package/dist/groups/css-contain-2.d.mts +19 -0
- package/dist/groups/css-content-3.d.mts +23 -0
- package/dist/groups/css-counter-styles-3.d.mts +16 -0
- package/dist/groups/css-display-4.d.mts +22 -0
- package/dist/groups/css-easing-2.d.mts +18 -0
- package/dist/groups/css-env-1.d.mts +16 -0
- package/dist/groups/css-flexbox-1.d.mts +24 -0
- package/dist/groups/css-fonts-4.d.mts +46 -0
- package/dist/groups/css-fonts-5.d.mts +44 -0
- package/dist/groups/css-forms-1.d.mts +19 -0
- package/dist/groups/css-gaps-1.d.mts +21 -0
- package/dist/groups/css-gcpm-3.d.mts +20 -0
- package/dist/groups/css-gcpm-4.d.mts +20 -0
- package/dist/groups/css-grid-2.d.mts +34 -0
- package/dist/groups/css-grid-3.d.mts +34 -0
- package/dist/groups/css-images-3.d.mts +25 -0
- package/dist/groups/css-images-4.d.mts +32 -0
- package/dist/groups/css-images-5.d.mts +33 -0
- package/dist/groups/css-inline-3.d.mts +28 -0
- package/dist/groups/css-lists-3.d.mts +26 -0
- package/dist/groups/css-logical-1.d.mts +35 -0
- package/dist/groups/css-masking-1.d.mts +37 -0
- package/dist/groups/css-multicol-2.d.mts +24 -0
- package/dist/groups/css-overflow-3.d.mts +28 -0
- package/dist/groups/css-overflow-4.d.mts +29 -0
- package/dist/groups/css-overflow-5.d.mts +31 -0
- package/dist/groups/css-overscroll-1.d.mts +22 -0
- package/dist/groups/css-page-3.d.mts +18 -0
- package/dist/groups/css-page-floats-3.d.mts +19 -0
- package/dist/groups/css-position-3.d.mts +29 -0
- package/dist/groups/css-position-4.d.mts +30 -0
- package/dist/groups/css-rhythm-1.d.mts +18 -0
- package/dist/groups/css-round-display-1.d.mts +16 -0
- package/dist/groups/css-ruby-1.d.mts +21 -0
- package/dist/groups/css-scroll-anchoring-1.d.mts +18 -0
- package/dist/groups/css-scroll-snap-1.d.mts +42 -0
- package/dist/groups/css-scroll-snap-2.d.mts +43 -0
- package/dist/groups/css-scrollbars-1.d.mts +19 -0
- package/dist/groups/css-shapes-1.d.mts +27 -0
- package/dist/groups/css-shapes-2.d.mts +27 -0
- package/dist/groups/css-size-adjust-1.d.mts +18 -0
- package/dist/groups/css-sizing-3.d.mts +34 -0
- package/dist/groups/css-sizing-4.d.mts +33 -0
- package/dist/groups/css-speech-1.d.mts +18 -0
- package/dist/groups/css-tables-3.d.mts +22 -0
- package/dist/groups/css-text-3.d.mts +36 -0
- package/dist/groups/css-text-4.d.mts +40 -0
- package/dist/groups/css-text-decor-3.d.mts +30 -0
- package/dist/groups/css-text-decor-4.d.mts +31 -0
- package/dist/groups/css-transforms-1.d.mts +31 -0
- package/dist/groups/css-transforms-2.d.mts +48 -0
- package/dist/groups/css-transitions-1.d.mts +22 -0
- package/dist/groups/css-transitions-2.d.mts +23 -0
- package/dist/groups/css-ui-4.d.mts +35 -0
- package/dist/groups/css-values-4.d.mts +38 -0
- package/dist/groups/css-values-5.d.mts +43 -0
- package/dist/groups/css-variables-2.d.mts +6 -0
- package/dist/groups/css-view-transitions-2.d.mts +20 -0
- package/dist/groups/css-viewport.d.mts +18 -0
- package/dist/groups/css-will-change-1.d.mts +18 -0
- package/dist/groups/css-writing-modes-4.d.mts +22 -0
- package/dist/groups/css2.d.mts +19 -0
- package/dist/groups/fill-stroke-3.d.mts +27 -0
- package/dist/groups/filter-effects-1.d.mts +32 -0
- package/dist/groups/filter-effects-2.d.mts +33 -0
- package/dist/groups/limited-availability.d.mts +2 -0
- package/dist/groups/mediaqueries-4.d.mts +16 -0
- package/dist/groups/mediaqueries-5.d.mts +16 -0
- package/dist/groups/motion-1.d.mts +24 -0
- package/dist/groups/newly-available.d.mts +631 -0
- package/dist/groups/not-discouraged.d.mts +727 -0
- package/dist/groups/scroll-animations-1.d.mts +30 -0
- package/dist/groups/selectors-4.d.mts +54 -0
- package/dist/groups/selectors-5.d.mts +54 -0
- package/dist/groups/widely-available.d.mts +616 -0
- package/dist/index.d.mts +48 -0
- package/dist/index.mjs +1269 -0
- package/dist/instrument-gCazujmb.mjs +1624 -0
- package/dist/lowered-D2KusPLp.mjs +28 -0
- package/dist/node-OJ_w_Usj.d.mts +233 -0
- package/dist/parent-vars.d.mts +13 -0
- package/dist/parent-vars.mjs +65 -0
- package/dist/plugin-types.d.mts +377 -0
- package/dist/plugin.d.mts +3 -0
- package/dist/plugin.mjs +30 -0
- package/dist/registry-CTumHB8p.mjs +73 -0
- package/dist/runtime-Dt4Tm0Q7.d.mts +19 -0
- package/dist/runtime.d.mts +18 -0
- package/dist/runtime.mjs +25 -0
- package/dist/scope-ZVhUxQH1.d.mts +2101 -0
- package/dist/sheet-BKsMTa0c.mjs +757 -0
- package/dist/surface.d.mts +228 -0
- package/dist/surface.mjs +101 -0
- package/dist/theme-BsP2E4LB.mjs +929 -0
- package/dist/theme-types-Bqv0Ggz_.d.mts +1808 -0
- package/dist/trace-otlp-CbKFDsn9.mjs +14 -0
- package/dist/tui-types.d.mts +181 -0
- package/dist/tui.d.mts +23 -0
- package/dist/tui.mjs +427 -0
- package/dist/types.d.mts +2 -0
- package/dist/vite.d.mts +134 -0
- package/dist/vite.mjs +977 -0
- package/docs/API.md +1193 -0
- package/package.json +85 -4
- package/skills/cssints/SKILL.md +203 -0
- package/skills/cssints/references/errors.md +86 -0
- package/skills/cssints/references/plugins.md +91 -0
- package/skills/cssints/references/tokens.md +91 -0
- package/skills/cssints-plugin/SKILL.md +177 -0
- package/skills/cssints-plugin/references/table.md +124 -0
- package/skills/cssints-plugin/references/testing.md +122 -0
|
@@ -0,0 +1,757 @@
|
|
|
1
|
+
import { d as MacroError, f as MemberError, o as warn, t as Registry } from "./registry-CTumHB8p.mjs";
|
|
2
|
+
import { browsers, lacking, messageOf, supportOf } from "@cssints/css-grammar/support";
|
|
3
|
+
import { Effect, Formatter, Result, Schema } from "effect";
|
|
4
|
+
import { longhands } from "@cssints/css-grammar/longhands";
|
|
5
|
+
//#region src/leaves.ts
|
|
6
|
+
const leaves = (p) => longhands[p] ?? [p];
|
|
7
|
+
const width = (p) => leaves(p).length;
|
|
8
|
+
const SIDE = [
|
|
9
|
+
[/^border-(top|bottom)-(left|right)-radius$/, (m) => ["border-*-radius", `${m[1]}-${m[2]}`]],
|
|
10
|
+
[/^border-(start|end)-(start|end)-radius$/, (m) => ["border-*-radius", `${m[1]}-${m[2]}`]],
|
|
11
|
+
[/^(top|right|bottom|left)$/, (m) => ["inset-*", m[1]]],
|
|
12
|
+
[/^inset-((?:block|inline)-(?:start|end))$/, (m) => ["inset-*", m[1]]],
|
|
13
|
+
[/^(.+)-((?:block|inline)-(?:start|end))(-.+)?$/, (m) => [`${m[1]}-*${m[3] ?? ""}`, m[2]]],
|
|
14
|
+
[/^(.+)-(top|right|bottom|left)(-.+)?$/, (m) => [`${m[1]}-*${m[3] ?? ""}`, m[2]]],
|
|
15
|
+
[/^((?:min-|max-|contain-intrinsic-)?)(width|height)$/, (m) => [`${m[1]}size`, m[2]]],
|
|
16
|
+
[/^((?:min-|max-|contain-intrinsic-)?)(inline|block)-size$/, (m) => [`${m[1]}size`, m[2]]],
|
|
17
|
+
[/^(overflow|overscroll-behavior)-(x|y|inline|block)$/, (m) => [m[1], m[2]]]
|
|
18
|
+
];
|
|
19
|
+
const FAMILIES = [
|
|
20
|
+
[
|
|
21
|
+
"top",
|
|
22
|
+
"right",
|
|
23
|
+
"bottom",
|
|
24
|
+
"left"
|
|
25
|
+
],
|
|
26
|
+
[
|
|
27
|
+
"block-start",
|
|
28
|
+
"block-end",
|
|
29
|
+
"inline-start",
|
|
30
|
+
"inline-end"
|
|
31
|
+
],
|
|
32
|
+
[
|
|
33
|
+
"top-left",
|
|
34
|
+
"top-right",
|
|
35
|
+
"bottom-left",
|
|
36
|
+
"bottom-right"
|
|
37
|
+
],
|
|
38
|
+
[
|
|
39
|
+
"start-start",
|
|
40
|
+
"start-end",
|
|
41
|
+
"end-start",
|
|
42
|
+
"end-end"
|
|
43
|
+
],
|
|
44
|
+
["width", "height"],
|
|
45
|
+
["inline", "block"],
|
|
46
|
+
["x", "y"]
|
|
47
|
+
];
|
|
48
|
+
const LOGICAL = new Set(FAMILIES.filter((_, i) => i % 2).flat());
|
|
49
|
+
const sideOf = (l) => {
|
|
50
|
+
for (const [re, f] of SIDE) {
|
|
51
|
+
const m = l.match(re);
|
|
52
|
+
if (m) return f(m);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const groups = (p) => {
|
|
56
|
+
const out = /* @__PURE__ */ new Map();
|
|
57
|
+
for (const l of leaves(p)) {
|
|
58
|
+
const s = sideOf(l);
|
|
59
|
+
if (s) (out.get(s[0]) ?? out.set(s[0], /* @__PURE__ */ new Set()).get(s[0])).add(s[1]);
|
|
60
|
+
}
|
|
61
|
+
return out;
|
|
62
|
+
};
|
|
63
|
+
const full = (sides) => !!sides && FAMILIES.some((f) => f.every((x) => sides.has(x)));
|
|
64
|
+
const covers = (a, b) => {
|
|
65
|
+
const la = leaves(a);
|
|
66
|
+
const ga = groups(a);
|
|
67
|
+
return leaves(b).every((l) => la.includes(l) || full(ga.get(sideOf(l)?.[0] ?? "")));
|
|
68
|
+
};
|
|
69
|
+
const meet = (a, b) => {
|
|
70
|
+
const lb = leaves(b);
|
|
71
|
+
if (leaves(a).some((l) => lb.includes(l))) return true;
|
|
72
|
+
const gb = groups(b);
|
|
73
|
+
return [...groups(a)].some(([g, sa]) => gb.has(g) && [...sa].some((x) => LOGICAL.has(x)) !== [...gb.get(g)].some((x) => LOGICAL.has(x)));
|
|
74
|
+
};
|
|
75
|
+
function relation(a, b) {
|
|
76
|
+
if (a === b) return "same";
|
|
77
|
+
const ab = covers(a, b);
|
|
78
|
+
const ba = covers(b, a);
|
|
79
|
+
if (ab && ba) return "same";
|
|
80
|
+
if (ab || ba) return "contains";
|
|
81
|
+
return meet(a, b) ? "overlap" : "apart";
|
|
82
|
+
}
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region src/delivery.ts
|
|
85
|
+
/** The name of the runtime of derived tokens (derived.ts): not a plugin's, the engine registers it (derived-data.ts). */
|
|
86
|
+
const DERIVED = "derived";
|
|
87
|
+
const RUNTIME_ID = "virtual:cssints/runtime/";
|
|
88
|
+
const FALLBACK = "@fallback ";
|
|
89
|
+
/** Registers the runtime of a member by plugin name, with the file that uses it. The same name with another runtime is an error. */
|
|
90
|
+
const addRuntime = Effect.fnUntraced(function* ({ name, runtime }, at) {
|
|
91
|
+
const { runtimes } = yield* Registry;
|
|
92
|
+
const entry = runtimes.get(name);
|
|
93
|
+
if (entry && entry.runtime !== runtime && Formatter.formatJson(entry.runtime) !== Formatter.formatJson(runtime)) return yield* new MemberError({
|
|
94
|
+
message: `cssints: ${name}: its runtime is registered twice with a different definition`,
|
|
95
|
+
pluginName: name,
|
|
96
|
+
...at
|
|
97
|
+
});
|
|
98
|
+
const e = entry ?? {
|
|
99
|
+
runtime,
|
|
100
|
+
users: /* @__PURE__ */ new Set()
|
|
101
|
+
};
|
|
102
|
+
runtimes.set(name, e);
|
|
103
|
+
if (at) e.users.add(at.file);
|
|
104
|
+
});
|
|
105
|
+
/** Registers the runtime of derived tokens for the file that declares them; the features its literals need add up across calls. */
|
|
106
|
+
const addDerived = Effect.fnUntraced(function* (file, keys) {
|
|
107
|
+
const { runtimes } = yield* Registry;
|
|
108
|
+
const e = runtimes.get("derived") ?? {
|
|
109
|
+
runtime: { polyfills: [] },
|
|
110
|
+
users: /* @__PURE__ */ new Set()
|
|
111
|
+
};
|
|
112
|
+
e.runtime = { polyfills: [.../* @__PURE__ */ new Set([...e.runtime.polyfills, ...keys])] };
|
|
113
|
+
e.users.add(file);
|
|
114
|
+
runtimes.set(DERIVED, e);
|
|
115
|
+
});
|
|
116
|
+
/**
|
|
117
|
+
* The targets a runtime cannot reach: `parentVars` and the derived tokens' runtime (no `css`, no `script`) stand on
|
|
118
|
+
* `@property`, so those without it; fallback CSS and a plugin's own `script` reach every target.
|
|
119
|
+
*/
|
|
120
|
+
const unreached = Effect.fnUntraced(function* ({ parentVars, css, script }, ts) {
|
|
121
|
+
if ((css || script) && !parentVars?.length) return /* @__PURE__ */ new Set();
|
|
122
|
+
return new Set((yield* lacking("css.at-rules.property", ts)).map((t) => t.join(" ")));
|
|
123
|
+
});
|
|
124
|
+
/**
|
|
125
|
+
* Of `off`, the targets that lack `feature`, those no runtime of a style covers: one covers them when it polyfills the
|
|
126
|
+
* feature and reaches them (`unreached`). The one rule for a kernel's `requires` and the support warnings of its declarations.
|
|
127
|
+
*/
|
|
128
|
+
const uncovered = Effect.fnUntraced(function* (feature, off, runtimes) {
|
|
129
|
+
const fallback = runtimes.find((r) => r.polyfills.includes(feature));
|
|
130
|
+
if (!fallback) return off;
|
|
131
|
+
const beyond = yield* unreached(fallback);
|
|
132
|
+
return off.filter((t) => beyond.has(t));
|
|
133
|
+
});
|
|
134
|
+
/** Whether a target needs the runtime: it lacks a feature in `polyfills` and the runtime reaches it (`unreached`). */
|
|
135
|
+
const needed = Effect.fnUntraced(function* (runtime, ts) {
|
|
136
|
+
const off = yield* unreached(runtime, ts);
|
|
137
|
+
for (const key of runtime.polyfills) for (const t of yield* lacking(key, ts)) if (!off.has(t.join(" "))) return true;
|
|
138
|
+
return false;
|
|
139
|
+
});
|
|
140
|
+
const runtimeNames = ({ runtimes }, file) => [...runtimes].flatMap(([name, e]) => e.users.has(file) ? [name] : []);
|
|
141
|
+
/** What a module records of fallback CSS: that of the runtimes it uses, when the targets need them. */
|
|
142
|
+
const fallbackEntries = Effect.fnUntraced(function* ({ runtimes }, file) {
|
|
143
|
+
const out = [];
|
|
144
|
+
for (const e of runtimes.values()) {
|
|
145
|
+
const { css } = e.runtime;
|
|
146
|
+
if (css && e.users.has(file) && (yield* needed(e.runtime))) out.push(`${FALLBACK}${Formatter.formatJson(css)}`);
|
|
147
|
+
}
|
|
148
|
+
return out;
|
|
149
|
+
});
|
|
150
|
+
/**
|
|
151
|
+
* The text of `virtual:cssints/runtime/<name>`: nothing, or the plugin's `script` (an import, which the browser runs
|
|
152
|
+
* once however many modules import it) and the shared engine configured with the runtime's families (derived tokens:
|
|
153
|
+
* their runtime).
|
|
154
|
+
*/
|
|
155
|
+
const runtimeModule = Effect.fnUntraced(function* (name) {
|
|
156
|
+
const { runtimes } = yield* Registry;
|
|
157
|
+
const runtime = runtimes.get(name)?.runtime;
|
|
158
|
+
if (!runtime) return "export {};";
|
|
159
|
+
if (name === "derived") return (yield* needed(runtime)) ? `import derived from "cssints/derived";\nderived();\n` : "export {};";
|
|
160
|
+
const { polyfills, script, parentVars } = runtime;
|
|
161
|
+
let out = "";
|
|
162
|
+
if (script && (yield* needed({
|
|
163
|
+
polyfills,
|
|
164
|
+
script
|
|
165
|
+
}))) out += `import ${Formatter.formatJson(script)};\n`;
|
|
166
|
+
if (parentVars?.length && (yield* needed(runtime))) out += `import parentVars from "cssints/parent-vars";\nparentVars(${Formatter.formatJson(parentVars)});\n`;
|
|
167
|
+
return out || "export {};";
|
|
168
|
+
});
|
|
169
|
+
//#endregion
|
|
170
|
+
//#region src/kernel.ts
|
|
171
|
+
const KERNEL = "@kernel ";
|
|
172
|
+
/** The support warnings of the declarations of a kernel written as styles (scope-engine.ts), weighed by `addKernel`. */
|
|
173
|
+
const kernelWarnings = /* @__PURE__ */ new WeakMap();
|
|
174
|
+
const VARS = /(--[\w-]+)\s*:|@property\s+(--[\w-]+)/g;
|
|
175
|
+
/**
|
|
176
|
+
* Registers a kernel by key, on first use (a global rule with atProperty: its css in _.k, its atProperty at the top
|
|
177
|
+
* of the sheet, both once however many styles use it). The same key with other css, another key that declares one of
|
|
178
|
+
* its custom properties, and another key for a marker it prints are build errors at `at`; a `requires` that a target
|
|
179
|
+
* lacks is a support warning, unless one of `runtimes` (those of the style) polyfills it and reaches that target
|
|
180
|
+
* (`uncovered`); so is a declaration of a kernel written as styles that a target lacks (`kernelWarnings`), by the same rule.
|
|
181
|
+
*/
|
|
182
|
+
const addKernel = Effect.fnUntraced(function* (kernel, markers, at, runtimes = []) {
|
|
183
|
+
const registry = yield* Registry;
|
|
184
|
+
const { kernels } = registry;
|
|
185
|
+
const fail = (message) => new MacroError({
|
|
186
|
+
message: `cssints: ${message}`,
|
|
187
|
+
...at
|
|
188
|
+
});
|
|
189
|
+
const { key } = kernel;
|
|
190
|
+
let entry = kernels.get(key);
|
|
191
|
+
if (entry) {
|
|
192
|
+
const k = entry.kernel;
|
|
193
|
+
if (k.css !== kernel.css || k.atProperty !== kernel.atProperty) return yield* fail(`kernel ${key} is registered twice with different CSS: a kernel that changes needs a new key (name@version)`);
|
|
194
|
+
} else {
|
|
195
|
+
const vars = key.startsWith("@") ? [] : [...`${kernel.css}\n${kernel.atProperty ?? ""}`.matchAll(VARS)].map((m) => m[1] ?? m[2]);
|
|
196
|
+
for (const [other, e] of kernels) {
|
|
197
|
+
const v = vars.find((x) => e.vars.includes(x));
|
|
198
|
+
if (v) return yield* fail(`kernels ${other} and ${key} both declare ${v}: a plugin picks its own short custom-property names`);
|
|
199
|
+
}
|
|
200
|
+
kernels.set(key, entry = {
|
|
201
|
+
kernel,
|
|
202
|
+
vars,
|
|
203
|
+
markers: /* @__PURE__ */ new Set(),
|
|
204
|
+
users: /* @__PURE__ */ new Set()
|
|
205
|
+
});
|
|
206
|
+
for (const r of kernel.requires ?? []) {
|
|
207
|
+
const { key: feature, exact } = typeof r === "string" ? {
|
|
208
|
+
key: r,
|
|
209
|
+
exact: false
|
|
210
|
+
} : r;
|
|
211
|
+
const all = (yield* lacking(feature, void 0, exact)).map((t) => t.join(" "));
|
|
212
|
+
const off = yield* uncovered(feature, all, runtimes);
|
|
213
|
+
if (off.length) warn(registry, `${key} ${feature}`, `kernel ${key} needs ${feature}, not supported by ${browsers([...off])}${exact ? " (a partial implementation counts as lacking)" : ""}`, at);
|
|
214
|
+
}
|
|
215
|
+
for (const { prop, value, warning } of kernelWarnings.get(kernel) ?? []) {
|
|
216
|
+
const off = yield* uncovered(warning.key, warning.lacking, runtimes);
|
|
217
|
+
const w = `${prop} ${warning.key}${off.length < warning.lacking.length ? ` ${off.join()}` : ""}`;
|
|
218
|
+
if (off.length) warn(registry, w, messageOf(prop, value, {
|
|
219
|
+
...warning,
|
|
220
|
+
lacking: [...off]
|
|
221
|
+
}), at);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (at) entry.users.add(at.file);
|
|
225
|
+
for (const [marker, owner] of markers) {
|
|
226
|
+
if (owner !== key) continue;
|
|
227
|
+
for (const [other, e] of kernels) if (other !== key && e.markers.has(marker)) return yield* fail(`kernels ${other} and ${key} both print the marker ${marker}`);
|
|
228
|
+
entry.markers.add(marker);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
const kernelEntries = ({ kernels }, file) => [...kernels.values()].flatMap((e) => e.users.has(file) ? [`${KERNEL}${Formatter.formatJson(e.kernel)}`] : []);
|
|
232
|
+
//#endregion
|
|
233
|
+
//#region src/derived.ts
|
|
234
|
+
/** The custom property of :root that carries the data (derived-data.ts writes it). */
|
|
235
|
+
const KEY = "--_derived";
|
|
236
|
+
const mul = (m, v) => [
|
|
237
|
+
0,
|
|
238
|
+
3,
|
|
239
|
+
6
|
|
240
|
+
].map((r) => v.reduce((s, x, k) => s + m[r + k] * x, 0));
|
|
241
|
+
const lin = (c) => {
|
|
242
|
+
const a = Math.abs(c);
|
|
243
|
+
return (a <= .04045 ? a / 12.92 : ((a + .055) / 1.055) ** 2.4) * Math.sign(c);
|
|
244
|
+
};
|
|
245
|
+
const gam = (c) => {
|
|
246
|
+
const a = Math.abs(c);
|
|
247
|
+
return (a <= .0031308 ? a * 12.92 : 1.055 * a ** (1 / 2.4) - .055) * Math.sign(c);
|
|
248
|
+
};
|
|
249
|
+
const rad = Math.PI / 180;
|
|
250
|
+
const rect = ([l, c, h]) => [
|
|
251
|
+
l,
|
|
252
|
+
c * Math.cos(h * rad),
|
|
253
|
+
c * Math.sin(h * rad)
|
|
254
|
+
];
|
|
255
|
+
const polar = ([l, a, b]) => {
|
|
256
|
+
const h = Math.atan2(b, a) / rad;
|
|
257
|
+
return [
|
|
258
|
+
l,
|
|
259
|
+
Math.hypot(a, b),
|
|
260
|
+
h < 0 ? h + 360 : h
|
|
261
|
+
];
|
|
262
|
+
};
|
|
263
|
+
const LMS = [
|
|
264
|
+
.4122214708,
|
|
265
|
+
.5363325363,
|
|
266
|
+
.0514459929,
|
|
267
|
+
.2119034982,
|
|
268
|
+
.6806995451,
|
|
269
|
+
.1073969566,
|
|
270
|
+
.0883024619,
|
|
271
|
+
.2817188376,
|
|
272
|
+
.6299787005
|
|
273
|
+
];
|
|
274
|
+
const OK = [
|
|
275
|
+
.2104542553,
|
|
276
|
+
.793617785,
|
|
277
|
+
-.0040720468,
|
|
278
|
+
1.9779984951,
|
|
279
|
+
-2.428592205,
|
|
280
|
+
.4505937099,
|
|
281
|
+
.0259040371,
|
|
282
|
+
.7827717662,
|
|
283
|
+
-.808675766
|
|
284
|
+
];
|
|
285
|
+
const LMS_I = [
|
|
286
|
+
4.0767416621,
|
|
287
|
+
-3.3077115913,
|
|
288
|
+
.2309699292,
|
|
289
|
+
-1.2684380046,
|
|
290
|
+
2.6097574011,
|
|
291
|
+
-.3413193965,
|
|
292
|
+
-.0041960863,
|
|
293
|
+
-.7034186147,
|
|
294
|
+
1.707614701
|
|
295
|
+
];
|
|
296
|
+
const OK_I = [
|
|
297
|
+
1,
|
|
298
|
+
.3963377774,
|
|
299
|
+
.2158037573,
|
|
300
|
+
1,
|
|
301
|
+
-.1055613458,
|
|
302
|
+
-.0638541728,
|
|
303
|
+
1,
|
|
304
|
+
-.0894841775,
|
|
305
|
+
-1.291485548
|
|
306
|
+
];
|
|
307
|
+
const XYZ = [
|
|
308
|
+
.436065743,
|
|
309
|
+
.385151469,
|
|
310
|
+
.143078454,
|
|
311
|
+
.222493192,
|
|
312
|
+
.716887054,
|
|
313
|
+
.0606197905,
|
|
314
|
+
.0139239045,
|
|
315
|
+
.0970812857,
|
|
316
|
+
.714099358
|
|
317
|
+
];
|
|
318
|
+
const XYZ_I = [
|
|
319
|
+
3.13413576,
|
|
320
|
+
-1.61738568,
|
|
321
|
+
-.49066242,
|
|
322
|
+
-.978795456,
|
|
323
|
+
1.91625419,
|
|
324
|
+
.0334429841,
|
|
325
|
+
.071955413,
|
|
326
|
+
-.228976675,
|
|
327
|
+
1.40538601
|
|
328
|
+
];
|
|
329
|
+
const D50 = [
|
|
330
|
+
.9642956764295677,
|
|
331
|
+
1,
|
|
332
|
+
.8251046025104602
|
|
333
|
+
];
|
|
334
|
+
const E = 216 / 24389;
|
|
335
|
+
const K = 24389 / 27;
|
|
336
|
+
const to = {
|
|
337
|
+
"srgb-linear": (c) => c,
|
|
338
|
+
srgb: (c) => c.map(lin),
|
|
339
|
+
oklab: (c) => mul(LMS_I, mul(OK_I, c).map((v) => v ** 3)),
|
|
340
|
+
oklch: (c) => to.oklab(rect(c)),
|
|
341
|
+
lab: ([l, a, b]) => {
|
|
342
|
+
const y = (l + 16) / 116;
|
|
343
|
+
const f = [
|
|
344
|
+
a / 500 + y,
|
|
345
|
+
y,
|
|
346
|
+
y - b / 200
|
|
347
|
+
];
|
|
348
|
+
return mul(XYZ_I, f.map((v, i) => D50[i] * (v ** 3 > E ? v ** 3 : (116 * v - 16) / K)));
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
const from = {
|
|
352
|
+
"srgb-linear": (c) => c,
|
|
353
|
+
srgb: (c) => c.map(gam),
|
|
354
|
+
oklab: (c) => mul(OK, mul(LMS, c).map(Math.cbrt)),
|
|
355
|
+
oklch: (c) => polar(from.oklab(c)),
|
|
356
|
+
lab: (c) => {
|
|
357
|
+
const f = mul(XYZ, c).map((v, i) => {
|
|
358
|
+
const x = v / D50[i];
|
|
359
|
+
return x > E ? Math.cbrt(x) : (K * x + 16) / 116;
|
|
360
|
+
});
|
|
361
|
+
return [
|
|
362
|
+
116 * f[1] - 16,
|
|
363
|
+
500 * (f[0] - f[1]),
|
|
364
|
+
200 * (f[1] - f[2])
|
|
365
|
+
];
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
const conv = (c, s) => c.s === s ? c : {
|
|
369
|
+
s,
|
|
370
|
+
c: from[s](to[c.s](c.c)),
|
|
371
|
+
a: c.a
|
|
372
|
+
};
|
|
373
|
+
const SPEC = {
|
|
374
|
+
srgb: ["rgb", [
|
|
375
|
+
1,
|
|
376
|
+
1,
|
|
377
|
+
1
|
|
378
|
+
]],
|
|
379
|
+
"srgb-linear": ["rgb", [
|
|
380
|
+
1,
|
|
381
|
+
1,
|
|
382
|
+
1
|
|
383
|
+
]],
|
|
384
|
+
oklab: ["lab", [
|
|
385
|
+
1,
|
|
386
|
+
.4,
|
|
387
|
+
.4
|
|
388
|
+
]],
|
|
389
|
+
oklch: ["lch", [
|
|
390
|
+
1,
|
|
391
|
+
.4,
|
|
392
|
+
360
|
|
393
|
+
]],
|
|
394
|
+
lab: ["lab", [
|
|
395
|
+
100,
|
|
396
|
+
125,
|
|
397
|
+
125
|
|
398
|
+
]]
|
|
399
|
+
};
|
|
400
|
+
const NAMED = {
|
|
401
|
+
black: "#000",
|
|
402
|
+
white: "#fff",
|
|
403
|
+
transparent: "#0000"
|
|
404
|
+
};
|
|
405
|
+
const TOKEN = /[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?(?:%|deg)?|#\w+|(?:--|-?)[a-z_][\w-]*|[^\s]/gi;
|
|
406
|
+
const fail = (x) => {
|
|
407
|
+
throw new Error(x);
|
|
408
|
+
};
|
|
409
|
+
const hex = (x) => {
|
|
410
|
+
const h = x.slice(1);
|
|
411
|
+
if (![
|
|
412
|
+
3,
|
|
413
|
+
4,
|
|
414
|
+
6,
|
|
415
|
+
8
|
|
416
|
+
].includes(h.length) || /[^\da-f]/i.test(h)) return fail(x);
|
|
417
|
+
const n = h.length < 5 ? h.replace(/./g, "$&$&") : h;
|
|
418
|
+
const byte = (i) => parseInt(n.slice(i, i + 2), 16) / 255;
|
|
419
|
+
return {
|
|
420
|
+
s: "srgb",
|
|
421
|
+
c: [
|
|
422
|
+
byte(0),
|
|
423
|
+
byte(2),
|
|
424
|
+
byte(4)
|
|
425
|
+
],
|
|
426
|
+
a: n.length > 6 ? byte(6) : 1
|
|
427
|
+
};
|
|
428
|
+
};
|
|
429
|
+
const evaluate = (text, get = (n) => fail(n)) => {
|
|
430
|
+
const t = text.match(TOKEN) ?? [];
|
|
431
|
+
let i = 0;
|
|
432
|
+
let pct = 1;
|
|
433
|
+
let env = {};
|
|
434
|
+
const next = () => t[i++] ?? fail(t[i - 2]);
|
|
435
|
+
const want = (s) => {
|
|
436
|
+
if (next() !== s) fail(t[i - 1]);
|
|
437
|
+
};
|
|
438
|
+
const input = () => {
|
|
439
|
+
want("(");
|
|
440
|
+
const v = get(next());
|
|
441
|
+
want(")");
|
|
442
|
+
return v;
|
|
443
|
+
};
|
|
444
|
+
const list = () => {
|
|
445
|
+
want("(");
|
|
446
|
+
const out = [sum()];
|
|
447
|
+
while (t[i] === ",") {
|
|
448
|
+
i++;
|
|
449
|
+
out.push(sum());
|
|
450
|
+
}
|
|
451
|
+
want(")");
|
|
452
|
+
return out;
|
|
453
|
+
};
|
|
454
|
+
const atom = () => {
|
|
455
|
+
const x = next();
|
|
456
|
+
if (/^[+-]?[\d.]/.test(x)) return parseFloat(x) * (x.endsWith("%") ? pct / 100 : 1);
|
|
457
|
+
if (x === "(") {
|
|
458
|
+
const v = sum();
|
|
459
|
+
want(")");
|
|
460
|
+
return v;
|
|
461
|
+
}
|
|
462
|
+
if (x === "calc") return atom();
|
|
463
|
+
if (x === "-") return -atom();
|
|
464
|
+
if (x === "clamp") {
|
|
465
|
+
const [lo, v, hi] = list();
|
|
466
|
+
return Math.max(lo, Math.min(v, hi));
|
|
467
|
+
}
|
|
468
|
+
if (x === "min") return Math.min(...list());
|
|
469
|
+
if (x === "max") return Math.max(...list());
|
|
470
|
+
if (x === "var") {
|
|
471
|
+
const v = input();
|
|
472
|
+
return typeof v === "string" && v ? Number(v) : fail(x);
|
|
473
|
+
}
|
|
474
|
+
if (x === "none") return 0;
|
|
475
|
+
return Object.hasOwn(env, x) ? env[x] : fail(x);
|
|
476
|
+
};
|
|
477
|
+
const prod = () => {
|
|
478
|
+
let v = atom();
|
|
479
|
+
for (let o = t[i]; o === "*" || o === "/"; o = t[i]) {
|
|
480
|
+
i++;
|
|
481
|
+
v = o === "*" ? v * atom() : v / atom();
|
|
482
|
+
}
|
|
483
|
+
return v;
|
|
484
|
+
};
|
|
485
|
+
const sum = () => {
|
|
486
|
+
let v = prod();
|
|
487
|
+
for (let o = t[i]; o === "+" || o === "-"; o = t[i]) {
|
|
488
|
+
i++;
|
|
489
|
+
v += o === "+" ? prod() : -prod();
|
|
490
|
+
}
|
|
491
|
+
return v;
|
|
492
|
+
};
|
|
493
|
+
const fn = (f) => {
|
|
494
|
+
want("(");
|
|
495
|
+
const origin = t[i] === "from" ? (i++, col()) : void 0;
|
|
496
|
+
const space = f === "color" ? next() : f === "rgb" || f === "rgba" ? "srgb" : f;
|
|
497
|
+
if (!Object.hasOwn(SPEC, space)) return fail(f === "color" ? space : f);
|
|
498
|
+
const [names, base] = SPEC[space];
|
|
499
|
+
const k = f[0] === "r" ? 255 : 1;
|
|
500
|
+
const src = origin && conv(origin, space);
|
|
501
|
+
env = src ? {
|
|
502
|
+
alpha: src.a,
|
|
503
|
+
...Object.fromEntries([...names].map((n, j) => [n, src.c[j] * k]))
|
|
504
|
+
} : {};
|
|
505
|
+
const c = base.map((b, j) => {
|
|
506
|
+
if (j && t[i] === ",") i++;
|
|
507
|
+
pct = b * k;
|
|
508
|
+
return atom() / k;
|
|
509
|
+
});
|
|
510
|
+
let a = 1;
|
|
511
|
+
if (t[i] === "/" || t[i] === ",") {
|
|
512
|
+
i++;
|
|
513
|
+
pct = 1;
|
|
514
|
+
a = Math.min(1, Math.max(0, atom()));
|
|
515
|
+
}
|
|
516
|
+
want(")");
|
|
517
|
+
return {
|
|
518
|
+
s: space,
|
|
519
|
+
c,
|
|
520
|
+
a
|
|
521
|
+
};
|
|
522
|
+
};
|
|
523
|
+
const mix = () => {
|
|
524
|
+
want("(");
|
|
525
|
+
want("in");
|
|
526
|
+
const s = next();
|
|
527
|
+
if (s === "oklch" || !Object.hasOwn(SPEC, s)) return fail(s);
|
|
528
|
+
want(",");
|
|
529
|
+
const one = () => {
|
|
530
|
+
return [conv(col(), s), t[i]?.endsWith("%") ? parseFloat(next()) : void 0];
|
|
531
|
+
};
|
|
532
|
+
const [a, p] = one();
|
|
533
|
+
want(",");
|
|
534
|
+
const [b, q] = one();
|
|
535
|
+
want(")");
|
|
536
|
+
const x = p ?? 100 - (q ?? 50);
|
|
537
|
+
const y = q ?? 100 - x;
|
|
538
|
+
if (x + y !== 100) return fail("color-mix");
|
|
539
|
+
const al = (a.a * x + b.a * y) / 100;
|
|
540
|
+
return {
|
|
541
|
+
s,
|
|
542
|
+
c: a.c.map((v, j) => al ? (v * a.a * x + b.c[j] * b.a * y) / 100 / al : 0),
|
|
543
|
+
a: al
|
|
544
|
+
};
|
|
545
|
+
};
|
|
546
|
+
const col = () => {
|
|
547
|
+
const x = next();
|
|
548
|
+
if (x.startsWith("#")) return hex(x);
|
|
549
|
+
if (NAMED[x]) return hex(NAMED[x]);
|
|
550
|
+
if (x === "var") {
|
|
551
|
+
const v = input();
|
|
552
|
+
return typeof v === "string" ? evaluate(v, get) : v;
|
|
553
|
+
}
|
|
554
|
+
return x === "color-mix" ? mix() : fn(x);
|
|
555
|
+
};
|
|
556
|
+
const out = col();
|
|
557
|
+
if (i < t.length) fail(t[i]);
|
|
558
|
+
return out;
|
|
559
|
+
};
|
|
560
|
+
const css = (c) => {
|
|
561
|
+
const [r, g, b] = conv(c, "srgb").c.map((v) => Math.round(Math.min(1, Math.max(0, v)) * 255));
|
|
562
|
+
return `rgb(${r} ${g} ${b}${c.a < 1 ? ` / ${+c.a.toFixed(3)}` : ""})`;
|
|
563
|
+
};
|
|
564
|
+
//#endregion
|
|
565
|
+
//#region src/derived-data.ts
|
|
566
|
+
const refuses = (literal) => {
|
|
567
|
+
const tried = Result.try({
|
|
568
|
+
try: () => evaluate(literal),
|
|
569
|
+
catch: (e) => `does not evaluate "${e.message}"`
|
|
570
|
+
});
|
|
571
|
+
return Result.isFailure(tried) ? tried.failure : void 0;
|
|
572
|
+
};
|
|
573
|
+
const standIn = Effect.fnUntraced(function* (at, who, kind, literal, inherits, rooted) {
|
|
574
|
+
const registry = yield* Registry;
|
|
575
|
+
if (registry.defs === registry.terminal?.defs) return false;
|
|
576
|
+
let why;
|
|
577
|
+
if (kind !== "color") why = "computes colours only";
|
|
578
|
+
else if (!inherits) why = "does not write tokens that do not inherit";
|
|
579
|
+
else if (!rooted) why = "does not read container themes";
|
|
580
|
+
else why = refuses(literal);
|
|
581
|
+
const ws = kind === "color" ? supportOf("color", literal).filter((w) => w.feature !== "color") : [];
|
|
582
|
+
if (why === void 0) {
|
|
583
|
+
yield* addDerived(at.file, [...new Set(ws.map((w) => w.key))]);
|
|
584
|
+
return true;
|
|
585
|
+
}
|
|
586
|
+
const lacking = browsers([...new Set(ws.flatMap((w) => w.lacking))]);
|
|
587
|
+
warn(registry, `derived ${who} ${why}`, `${who}: "${literal}" stays at its static default${lacking ? ` in ${lacking}` : " in the older targets"}: the runtime for derived tokens ${why}`, at);
|
|
588
|
+
return false;
|
|
589
|
+
});
|
|
590
|
+
const usesDerived = ({ defs, themed }, names) => [...names].some((n) => defs.get(n)?.poly !== void 0 || [...themed.values()].some((t) => t.theme?.poly?.has(n)));
|
|
591
|
+
const derivedRule = Effect.fnUntraced(function* (properties, keys) {
|
|
592
|
+
const { runtimes, defs, themed } = yield* Registry;
|
|
593
|
+
const entry = runtimes.get(DERIVED);
|
|
594
|
+
if (!entry || !(yield* needed(entry.runtime))) return;
|
|
595
|
+
const used = new Set(properties.map((p) => /^@property (--[\w-]+)/.exec(p)?.[1]));
|
|
596
|
+
const byKey = new Map([...themed.values()].map((t) => [t.key, t.theme]));
|
|
597
|
+
const themes = keys.flatMap((k) => byKey.get(k) ?? []);
|
|
598
|
+
const probes = /* @__PURE__ */ new Set();
|
|
599
|
+
const base = {};
|
|
600
|
+
const names = /* @__PURE__ */ new Set();
|
|
601
|
+
for (const [n, d] of defs) if (used.has(n) && d.poly) {
|
|
602
|
+
base[n] = d.template;
|
|
603
|
+
probes.add(d.poly);
|
|
604
|
+
names.add(n);
|
|
605
|
+
}
|
|
606
|
+
for (const { poly } of themes) for (const [n, literal] of poly ?? []) if (used.has(n)) {
|
|
607
|
+
probes.add(literal);
|
|
608
|
+
names.add(n);
|
|
609
|
+
}
|
|
610
|
+
if (!names.size) return;
|
|
611
|
+
const t = themes.flatMap(({ label, values, poly }) => {
|
|
612
|
+
const set = Object.fromEntries([...values].flatMap(([n, css]) => names.has(n) ? [[n, poly?.has(n) ? css : 0]] : []));
|
|
613
|
+
return Object.keys(set).length ? [[label, set]] : [];
|
|
614
|
+
});
|
|
615
|
+
const json = Formatter.formatJson({
|
|
616
|
+
p: [...probes],
|
|
617
|
+
b: base,
|
|
618
|
+
t
|
|
619
|
+
});
|
|
620
|
+
return `:root{${KEY}:'${json.replace(/[\\']/g, "\\$&")}'}`;
|
|
621
|
+
});
|
|
622
|
+
//#endregion
|
|
623
|
+
//#region src/sheet.ts
|
|
624
|
+
const fromJson = Schema.decodeSync(Schema.fromJsonString(Schema.Unknown));
|
|
625
|
+
const THEME = "@theme ";
|
|
626
|
+
const LAYERS = "@layer _.k, _.a, _.b, _.c, _.d, _.e;";
|
|
627
|
+
const cmp = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
628
|
+
const cmpCond = (a, b) => a.reduce((d, x, i) => d || (i < b.length ? x - b[i] : 0), 0) || a.length - b.length;
|
|
629
|
+
const wrapKey = (r) => r.wrap.join("{");
|
|
630
|
+
const byOrder = (a, b) => cmp(a.layer, b.layer) || cmpCond(a.cond, b.cond) || cmp(wrapKey(a), wrapKey(b)) || width(b.prop) - width(a.prop) || cmp(a.cls, b.cls);
|
|
631
|
+
const GLOBAL_RULE = "@global ";
|
|
632
|
+
const LAYER_LIST = "@layers ";
|
|
633
|
+
const LAYER_BEFORE = "@layers< ";
|
|
634
|
+
const LAYER_NAME = /^[A-Za-z_][\w-]*$/;
|
|
635
|
+
/** Adds a global rule (`*{box-sizing:border-box}`) of a plugin member, by its content, to the sheet of the module at `at`. `layer` names a declared top-level layer to wrap it in, no layer puts it in `_.k`. */
|
|
636
|
+
const addGlobal = Effect.fnUntraced(function* (g, at) {
|
|
637
|
+
const { globals } = yield* Registry;
|
|
638
|
+
if (g.layer !== void 0) yield* requireLayer(g.layer, at);
|
|
639
|
+
const key = `${g.layer ?? ""}\t${g.css}`;
|
|
640
|
+
const entry = globals.get(key) ?? globals.set(key, {
|
|
641
|
+
global: g,
|
|
642
|
+
users: /* @__PURE__ */ new Set()
|
|
643
|
+
}).get(key);
|
|
644
|
+
if (at) entry.users.add(at.file);
|
|
645
|
+
});
|
|
646
|
+
const globalEntries = ({ globals }, file) => [...globals.values()].flatMap((e) => e.users.has(file) ? [`${GLOBAL_RULE}${Formatter.formatJson([e.global.layer ?? "", e.global.css])}`] : []);
|
|
647
|
+
/**
|
|
648
|
+
* Declares top-level layers, in order: the statement `@layer a, b, c;`, printed after the engine's own layers, once
|
|
649
|
+
* whoever declares it, so what is in them beats the engine's `:root` fallbacks; with `before`, printed before them, so
|
|
650
|
+
* the engine's classes beat what is in them (a reset). Another statement may name the same layers in the same order, or
|
|
651
|
+
* hold or be held by this one; layers in another order, shared without one holding the other, or declared both before
|
|
652
|
+
* and after the engine's, are build errors at `at`, since the sheet could not say which comes first.
|
|
653
|
+
*/
|
|
654
|
+
const addLayers = Effect.fnUntraced(function* ({ names, before = false }, at) {
|
|
655
|
+
const { layers } = yield* Registry;
|
|
656
|
+
const fail = (message) => new MacroError({
|
|
657
|
+
message: `cssints: ${message}`,
|
|
658
|
+
...at
|
|
659
|
+
});
|
|
660
|
+
const list = names.join(", ");
|
|
661
|
+
if (!names.length || new Set(names).size !== names.length || !names.every((n) => LAYER_NAME.test(n))) return yield* fail(`layers(${list}) takes names of layers, each once: letters, digits, _ and -`);
|
|
662
|
+
for (const l of layers.values()) {
|
|
663
|
+
const mine = names.filter((n) => l.names.includes(n));
|
|
664
|
+
if (mine.length && l.before !== before) return yield* fail(`layers(${list}) declares ${mine.join(", ")} ${before ? "before" : "after"} the engine's layers, and layers(${l.names.join(", ")}) ${l.before ? "before" : "after"}`);
|
|
665
|
+
if (mine.length && mine.join() !== l.names.filter((n) => names.includes(n)).join()) return yield* fail(`layers(${list}) names layers in another order than layers(${l.names.join(", ")})`);
|
|
666
|
+
if (mine.length && mine.length < Math.min(names.length, l.names.length)) return yield* fail(`layers(${list}) and layers(${l.names.join(", ")}) share layers, and neither holds the other: declare them in one call`);
|
|
667
|
+
}
|
|
668
|
+
const key = names.join();
|
|
669
|
+
const entry = layers.get(key) ?? layers.set(key, {
|
|
670
|
+
names: [...names],
|
|
671
|
+
before,
|
|
672
|
+
users: /* @__PURE__ */ new Set()
|
|
673
|
+
}).get(key);
|
|
674
|
+
if (at) entry.users.add(at.file);
|
|
675
|
+
});
|
|
676
|
+
/** A build error at `at` unless `layer` is declared by a `layers()` that has run (this module, or one it imports). */
|
|
677
|
+
const requireLayer = Effect.fnUntraced(function* (layer, at) {
|
|
678
|
+
const { layers } = yield* Registry;
|
|
679
|
+
if (![...layers.values()].some((l) => l.names.includes(layer))) return yield* new MacroError({
|
|
680
|
+
message: `cssints: the layer "${layer}" is not declared: call layers("${layer}", ...) in this module or in one it imports`,
|
|
681
|
+
...at
|
|
682
|
+
});
|
|
683
|
+
});
|
|
684
|
+
const layerEntries = ({ layers }, file) => [...layers.values()].flatMap((l) => l.users.has(file) ? [`${l.before ? LAYER_BEFORE : LAYER_LIST}${l.names.join()}`] : []);
|
|
685
|
+
const layerStatements = (lists) => [...new Map([...lists].map((l) => [l.join(), [...l]])).values()].sort((a, b) => b.length - a.length || cmp(a.join(), b.join()));
|
|
686
|
+
const themedEntries = (themed, file, names) => [...themed.values()].flatMap((t) => t.file === file || t.names.some((n) => names.has(n)) ? [`${THEME}${t.key}\t${t.layer ?? ""}\t${t.css}`] : []);
|
|
687
|
+
const globalNames = (themed, file) => [...themed.values()].filter((t) => t.file === file && t.key.startsWith("-:")).flatMap((t) => t.css.match(/--[\w-]+/g) ?? []);
|
|
688
|
+
const DECL = /(--[\w-]+):([^;{}]*)/g;
|
|
689
|
+
const closeNames = (names, defs, themed) => {
|
|
690
|
+
for (let size = -1; size !== names.size;) {
|
|
691
|
+
size = names.size;
|
|
692
|
+
for (const n of [...names]) defs.get(n)?.refs?.forEach((r) => names.add(r));
|
|
693
|
+
for (const t of themed.values()) if (t.names.some((n) => names.has(n))) {
|
|
694
|
+
for (const [, n, value] of t.css.matchAll(DECL)) if (names.has(n)) value.match(/--[\w-]+/g)?.forEach((r) => names.add(r));
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
};
|
|
698
|
+
/** The rules of `entries`: class names, and the text of `@property` rules (once each, whichever module has them). */
|
|
699
|
+
const renderSheet = Effect.fn("cssints.renderSheet")(function* (entries) {
|
|
700
|
+
const { rules, layers } = yield* Registry;
|
|
701
|
+
const all = [...new Set(entries)];
|
|
702
|
+
const properties = all.filter((e) => e.startsWith("@property")).sort();
|
|
703
|
+
const themes = all.flatMap((e) => e.startsWith(THEME) ? [e.split(" ")] : []).sort((a, b) => cmp(a[1], b[1]));
|
|
704
|
+
const kThemes = themes.filter((t) => t[2] === "");
|
|
705
|
+
const topThemes = themes.filter((t) => t[2] !== "");
|
|
706
|
+
const used = all.flatMap((e) => e.startsWith("@kernel ") ? [fromJson(e.slice(8))] : []).sort((a, b) => cmp(a.key, b.key));
|
|
707
|
+
const fallbacks = all.flatMap((e) => e.startsWith("@fallback ") ? [fromJson(e.slice(10))] : []).sort();
|
|
708
|
+
const derived = yield* derivedRule(properties, themes.map((t) => t[1]));
|
|
709
|
+
const sorted = all.flatMap((cls) => {
|
|
710
|
+
const rule = rules.get(cls);
|
|
711
|
+
return rule ? [{
|
|
712
|
+
cls,
|
|
713
|
+
...rule
|
|
714
|
+
}] : [];
|
|
715
|
+
}).sort(byOrder);
|
|
716
|
+
const globals = all.filter((e) => e.startsWith(GLOBAL_RULE)).sort(cmp).map((e) => fromJson(e.slice(8)));
|
|
717
|
+
const kGlobals = globals.flatMap(([layer, css]) => layer === "" ? [css] : []);
|
|
718
|
+
const layered = globals.filter(([layer]) => layer !== "");
|
|
719
|
+
const inUse = /* @__PURE__ */ new Set([...layered.map(([layer]) => layer), ...topThemes.map((t) => t[2])]);
|
|
720
|
+
const statementsOf = (prefix, before) => layerStatements([...all.flatMap((e) => e.startsWith(prefix) ? [e.slice(prefix.length).split(",")] : []), ...[...layers.values()].flatMap((l) => l.before === before && l.names.some((n) => inUse.has(n)) ? [l.names] : [])]).map((s) => `@layer ${s.join(", ")};\n`);
|
|
721
|
+
let out = `${LAYERS}\n${[...properties, ...used.flatMap((k) => k.atProperty ?? [])].map((p) => `${p}\n`).join("")}`;
|
|
722
|
+
out = `${statementsOf(LAYER_BEFORE, true).join("")}${out.replace("\n", `\n${statementsOf(LAYER_LIST, false).join("")}`)}`;
|
|
723
|
+
if (kGlobals.length || used.length || fallbacks.length || kThemes.length) out += `@layer _.k {\n${[
|
|
724
|
+
...kGlobals,
|
|
725
|
+
...used.map((k) => k.css),
|
|
726
|
+
...fallbacks,
|
|
727
|
+
...kThemes.map((t) => t[3]),
|
|
728
|
+
...derived ? [derived] : []
|
|
729
|
+
].map((g) => ` ${g}\n`).join("")}}\n`;
|
|
730
|
+
for (const [layer, css] of layered) out += `@layer ${layer} {\n ${css}\n}\n`;
|
|
731
|
+
for (const t of topThemes) out += `@layer ${t[2]} {\n ${t[3]}\n}\n`;
|
|
732
|
+
let layer = "";
|
|
733
|
+
let wrap = "";
|
|
734
|
+
let depth = 0;
|
|
735
|
+
const closeWrap = () => out += depth ? ` ${"}".repeat(depth)}\n` : "";
|
|
736
|
+
for (const r of sorted) {
|
|
737
|
+
const key = wrapKey(r);
|
|
738
|
+
if (r.layer !== layer) {
|
|
739
|
+
closeWrap();
|
|
740
|
+
out += `${layer ? "}\n" : ""}@layer ${r.layer} {\n`;
|
|
741
|
+
layer = r.layer;
|
|
742
|
+
wrap = "";
|
|
743
|
+
depth = 0;
|
|
744
|
+
}
|
|
745
|
+
if (key !== wrap) {
|
|
746
|
+
closeWrap();
|
|
747
|
+
wrap = key;
|
|
748
|
+
depth = r.wrap.length;
|
|
749
|
+
if (depth) out += ` ${r.wrap.map((w) => `${w} {`).join(" ")}\n`;
|
|
750
|
+
}
|
|
751
|
+
out += `${depth ? " " : " "}${r.css}\n`;
|
|
752
|
+
}
|
|
753
|
+
closeWrap();
|
|
754
|
+
return layer ? `${out}}\n` : out;
|
|
755
|
+
});
|
|
756
|
+
//#endregion
|
|
757
|
+
export { fallbackEntries as C, relation as D, covers as E, addRuntime as S, runtimeNames as T, addKernel as _, closeNames as a, DERIVED as b, layerEntries as c, requireLayer as d, themedEntries as f, evaluate as g, css as h, byOrder as i, layerStatements as l, usesDerived as m, addGlobal as n, globalEntries as o, standIn as p, addLayers as r, globalNames as s, LAYERS as t, renderSheet as u, kernelEntries as v, runtimeModule as w, RUNTIME_ID as x, kernelWarnings as y };
|