@tenphi/tasty 0.0.0-snapshot.fdb16ea → 0.0.0-snapshot.fde6cf3

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 (87) hide show
  1. package/dist/astro-Dj8YpRd7.js +301 -0
  2. package/dist/astro-Dj8YpRd7.js.map +1 -0
  3. package/dist/{babel-CMYf4JZ2.d.ts → babel-Cbp2C2bj.d.ts} +2 -2
  4. package/dist/{collector-Ctn5s74s.d.ts → collector-DBY6liC2.d.ts} +94 -11
  5. package/dist/collector-NjmUiB8f.js +529 -0
  6. package/dist/collector-NjmUiB8f.js.map +1 -0
  7. package/dist/{config-B23gZrfP.js → config-Bd2vOF0Z.js} +454 -105
  8. package/dist/config-Bd2vOF0Z.js.map +1 -0
  9. package/dist/{config-CZx8_DCu.d.ts → config-CA7iAlEI.d.ts} +112 -22
  10. package/dist/core/index.d.ts +5 -5
  11. package/dist/core/index.js +6 -6
  12. package/dist/{core-B1tyn69d.js → core-ClInK6YG.js} +386 -107
  13. package/dist/core-ClInK6YG.js.map +1 -0
  14. package/dist/css-resources-Cyl_axbI.js +149 -0
  15. package/dist/css-resources-Cyl_axbI.js.map +1 -0
  16. package/dist/{css-writer-CvAxkR6S.js → css-writer-BDQXG9Jo.js} +3 -3
  17. package/dist/{css-writer-CvAxkR6S.js.map → css-writer-BDQXG9Jo.js.map} +1 -1
  18. package/dist/{format-rules-BCTWVvcS.js → format-rules-CGhgoVLR.js} +22 -32
  19. package/dist/format-rules-CGhgoVLR.js.map +1 -0
  20. package/dist/{hydrate-BCPvkJj3.js → hydrate-CqbxwVh_.js} +2 -2
  21. package/dist/{hydrate-BCPvkJj3.js.map → hydrate-CqbxwVh_.js.map} +1 -1
  22. package/dist/{index-B3o0aCYV.d.ts → index-C8RFYeFW.d.ts} +61 -12
  23. package/dist/{index-CsvB0EXZ.d.ts → index-FpYK0H5g.d.ts} +49 -8
  24. package/dist/index.d.ts +5 -5
  25. package/dist/index.js +43 -27
  26. package/dist/index.js.map +1 -1
  27. package/dist/{keyframes-Dxdx3KOo.js → keyframes-BjfNVhaB.js} +45 -3
  28. package/dist/keyframes-BjfNVhaB.js.map +1 -0
  29. package/dist/{merge-styles-DJTSfz_M.d.ts → merge-styles-BQv7d3fx.d.ts} +2 -2
  30. package/dist/{merge-styles-C-uwpoNW.js → merge-styles-BbJhjesV.js} +2 -2
  31. package/dist/{merge-styles-C-uwpoNW.js.map → merge-styles-BbJhjesV.js.map} +1 -1
  32. package/dist/precompile/index.d.ts +11 -0
  33. package/dist/precompile/index.js +72 -0
  34. package/dist/precompile/index.js.map +1 -0
  35. package/dist/precompile/register.d.ts +13 -0
  36. package/dist/precompile/register.js +2 -0
  37. package/dist/register-BkC-8Zuy.js +333 -0
  38. package/dist/register-BkC-8Zuy.js.map +1 -0
  39. package/dist/{resolve-recipes-BuOvSEa2.js → resolve-recipes-B2Sf36AH.js} +3 -3
  40. package/dist/{resolve-recipes-BuOvSEa2.js.map → resolve-recipes-B2Sf36AH.js.map} +1 -1
  41. package/dist/ssr/astro-client.js +1 -1
  42. package/dist/ssr/astro-middleware-extract-static.d.ts +11 -0
  43. package/dist/ssr/astro-middleware-extract-static.js +9 -0
  44. package/dist/ssr/astro-middleware-extract-static.js.map +1 -0
  45. package/dist/ssr/astro-middleware-extract.d.ts +11 -0
  46. package/dist/ssr/astro-middleware-extract.js +9 -0
  47. package/dist/ssr/astro-middleware-extract.js.map +1 -0
  48. package/dist/ssr/astro-middleware-static.d.ts +3 -1
  49. package/dist/ssr/astro-middleware-static.js +1 -1
  50. package/dist/ssr/astro-middleware.d.ts +3 -1
  51. package/dist/ssr/astro-middleware.js +1 -1
  52. package/dist/ssr/astro.d.ts +45 -3
  53. package/dist/ssr/astro.js +1 -156
  54. package/dist/ssr/index.d.ts +2 -2
  55. package/dist/ssr/index.js +3 -3
  56. package/dist/ssr/index.js.map +1 -1
  57. package/dist/ssr/next-config.d.ts +66 -0
  58. package/dist/ssr/next-config.js +115 -0
  59. package/dist/ssr/next-config.js.map +1 -0
  60. package/dist/ssr/next.d.ts +9 -2
  61. package/dist/ssr/next.js +26 -9
  62. package/dist/ssr/next.js.map +1 -1
  63. package/dist/ssr-collector-ref-COs_ioWl.js +29 -0
  64. package/dist/ssr-collector-ref-COs_ioWl.js.map +1 -0
  65. package/dist/static/index.d.ts +2 -2
  66. package/dist/static/index.js +1 -1
  67. package/dist/types-Bo5ePLZh.d.ts +111 -0
  68. package/dist/zero/babel.d.ts +1 -1
  69. package/dist/zero/babel.js +4 -4
  70. package/dist/zero/babel.js.map +1 -1
  71. package/dist/zero/index.d.ts +1 -1
  72. package/dist/zero/index.js +1 -1
  73. package/dist/zero/next.d.ts +1 -1
  74. package/docs/README.md +3 -1
  75. package/docs/debug.md +17 -6
  76. package/docs/injector.md +23 -3
  77. package/docs/precompile.md +202 -0
  78. package/docs/runtime-benchmarks.md +143 -72
  79. package/docs/ssr.md +179 -20
  80. package/package.json +44 -10
  81. package/dist/collector-DMSR6ANK.js +0 -304
  82. package/dist/collector-DMSR6ANK.js.map +0 -1
  83. package/dist/config-B23gZrfP.js.map +0 -1
  84. package/dist/core-B1tyn69d.js.map +0 -1
  85. package/dist/format-rules-BCTWVvcS.js.map +0 -1
  86. package/dist/keyframes-Dxdx3KOo.js.map +0 -1
  87. package/dist/ssr/astro.js.map +0 -1
@@ -0,0 +1,333 @@
1
+ import { $t as getGlobalParseFunctions, W as getGlobalPredefinedStates, Z as getPrecompileStore, _ as isConfigLocked, d as getGlobalRecipes, en as getGlobalParser, kt as hashString, n as getConfig, nt as warnPrecompileOnce, r as getConfiguredOverrides, tn as getGlobalPredefinedTokens, v as isFunctionsPolyfillEnabled } from "./config-Bd2vOF0Z.js";
2
+ //#region src/version.ts
3
+ /** Package version injected by builds; the fallback supports direct source consumers. */
4
+ const TASTY_VERSION = "0.0.0-snapshot.fde6cf3";
5
+ //#endregion
6
+ //#region src/precompile/fingerprint.ts
7
+ /**
8
+ * A stable token for an arbitrary configuration value.
9
+ *
10
+ * Function-valued entries (unit handlers, parse functions) cannot be compared
11
+ * by body: a catalog is compiled from an unminified build while the runtime may
12
+ * be reading a minified one, so `toString()` differs for identical behaviour and
13
+ * would reject every production bundle. Their presence and arity are recorded
14
+ * instead, which catches an entry being added, removed or swapped for one of a
15
+ * different shape — not a rewritten body. That gap is documented on
16
+ * `TastyCompilationConfig`.
17
+ */
18
+ function token(value) {
19
+ if (typeof value === "function") return `fn/${value.length}`;
20
+ if (value === void 0) return "undefined";
21
+ if (typeof value === "string") return `s/${hashString(value)}`;
22
+ return `j/${hashString(stableStringify(value))}`;
23
+ }
24
+ /** JSON with object keys sorted, so key order cannot change the token. */
25
+ function stableStringify(value) {
26
+ if (value === null || typeof value !== "object") return JSON.stringify(value) ?? "undefined";
27
+ if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
28
+ return `{${Object.entries(value).filter(([, item]) => item !== void 0).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, item]) => `${JSON.stringify(key)}:${stableStringify(item)}`).join(",")}}`;
29
+ }
30
+ /**
31
+ * Entries recorded in `configure()` order, deduped into a comparable map.
32
+ * Later calls win, matching how `configure()` merges them.
33
+ */
34
+ function named(entries) {
35
+ const out = {};
36
+ for (const [name, definition] of entries) out[name] = definition;
37
+ return out;
38
+ }
39
+ function tokenize(source, prefix) {
40
+ const out = {};
41
+ if (!source) return out;
42
+ for (const key of Object.keys(source).sort()) out[`${prefix}:${key}`] = token(source[key]);
43
+ return out;
44
+ }
45
+ /**
46
+ * Snapshot the configuration a precompiled catalog was compiled under.
47
+ *
48
+ * Read at build time into the manifest, and again at runtime once the config
49
+ * locks, so the two can be compared before any lookup trusts the catalog.
50
+ */
51
+ function captureCompilationConfig() {
52
+ const config = getConfig();
53
+ const parser = getGlobalParser();
54
+ const overrides = getConfiguredOverrides();
55
+ return {
56
+ scoped: {
57
+ ...tokenize(getGlobalPredefinedStates(), "state"),
58
+ ...tokenize(parser.getUnits(), "unit"),
59
+ ...tokenize(getGlobalRecipes(), "recipe"),
60
+ ...tokenize(named(overrides.functions), "fn"),
61
+ ...tokenize(getGlobalParseFunctions(), "parseFn"),
62
+ ...tokenize(getGlobalPredefinedTokens(), "replaceToken")
63
+ },
64
+ exclusive: {
65
+ ...tokenize(named(overrides.handlers), "handler"),
66
+ ...tokenize(named(overrides.propHandlers), "propHandler")
67
+ },
68
+ scalars: {
69
+ autoPropertyTypes: String(config.autoPropertyTypes !== false),
70
+ functionsPolyfill: String(isFunctionsPolyfillEnabled())
71
+ }
72
+ };
73
+ }
74
+ /**
75
+ * Describe every way `runtime` would compile differently from `compiled`.
76
+ *
77
+ * An empty result means the catalog's CSS is still what this configuration
78
+ * would produce. Names are reported rather than counted so the warning tells
79
+ * the consumer which setting to look at.
80
+ */
81
+ function diffCompilationConfig(compiled, runtime) {
82
+ const reasons = [];
83
+ for (const [key, value] of Object.entries(compiled.scalars)) if (runtime.scalars[key] !== value) reasons.push(`${key} changed`);
84
+ for (const [key, value] of Object.entries(compiled.scoped)) {
85
+ const current = runtime.scoped[key];
86
+ if (current === void 0) reasons.push(`${key} removed`);
87
+ else if (current !== value) reasons.push(`${key} changed`);
88
+ }
89
+ const exclusiveKeys = new Set([...Object.keys(compiled.exclusive), ...Object.keys(runtime.exclusive)]);
90
+ for (const key of exclusiveKeys) {
91
+ const before = compiled.exclusive[key];
92
+ const after = runtime.exclusive[key];
93
+ if (before === after) continue;
94
+ reasons.push(before === void 0 ? `${key} added` : after === void 0 ? `${key} removed` : `${key} changed`);
95
+ }
96
+ return reasons.sort();
97
+ }
98
+ function isCompilationConfigShapeValid(value) {
99
+ const isTokenMap = (map) => !!map && typeof map === "object" && !Array.isArray(map) && Object.values(map).every((item) => typeof item === "string");
100
+ return !!value && isTokenMap(value.scoped) && isTokenMap(value.exclusive) && isTokenMap(value.scalars);
101
+ }
102
+ //#endregion
103
+ //#region src/precompile/registry.ts
104
+ const isStringArray = (value) => Array.isArray(value) && value.every((item) => typeof item === "string");
105
+ const isRecord = (value) => !!value && typeof value === "object" && !Array.isArray(value);
106
+ /**
107
+ * The documented workflow imports a manifest from JSON and casts it, so the
108
+ * shape is only as good as the file — and the input is `unknown` here for that
109
+ * reason. Checking that a dependency field is an array is not enough:
110
+ * `keyframes: [{}]` would pass and then throw while iterating `item.rscKeys`
111
+ * in `mergeDependencies`, and `chunks: [null]` would throw inside the
112
+ * validator itself. Nor is optional chaining enough at the top level: `null`
113
+ * survives `manifest?.dependencies` and then throws on `manifest.schemaVersion`
114
+ * before registration can warn. A malformed manifest should be warned about
115
+ * and ignored, never crash registration.
116
+ */
117
+ function isManifestShapeValid(manifest) {
118
+ if (!isRecord(manifest)) return false;
119
+ const dependencies = manifest.dependencies;
120
+ const stats = manifest.stats;
121
+ return manifest.schemaVersion === 2 && isCompilationConfigShapeValid(manifest.compilationConfig) && typeof manifest.id === "string" && manifest.id.length > 0 && typeof manifest.tastyVersion === "string" && typeof manifest.namePrefix === "string" && typeof manifest.cssHash === "string" && manifest.cssHash.length > 0 && isRecord(stats) && Number.isSafeInteger(stats.cssSize) && stats.cssSize >= 0 && Number.isSafeInteger(stats.ruleCount) && stats.ruleCount >= 0 && Array.isArray(manifest.chunks) && manifest.chunks.every((chunk) => isRecord(chunk) && typeof chunk.lookupKey === "string" && typeof chunk.className === "string" && isStringArray(chunk.animations)) && isRecord(dependencies) && Array.isArray(dependencies.properties) && dependencies.properties.every((item) => isRecord(item) && typeof item.name === "string" && typeof item.definition === "string") && Array.isArray(dependencies.keyframes) && dependencies.keyframes.every((item) => isRecord(item) && typeof item.name === "string" && typeof item.contentKey === "string" && isStringArray(item.rscKeys)) && isStringArray(dependencies.fontFaces) && Array.isArray(dependencies.counterStyles) && dependencies.counterStyles.every((item) => isRecord(item) && typeof item.name === "string" && isStringArray(item.rscKeys)) && isStringArray(dependencies.functions) && isStringArray(dependencies.rscKeys);
122
+ }
123
+ function sameStrings(a, b) {
124
+ return a.length === b.length && a.every((value, index) => value === b[index]);
125
+ }
126
+ function mergeDependencies(current, next) {
127
+ const properties = new Map(current?.properties.map((item) => [item.name, item.definition]));
128
+ const keyframes = /* @__PURE__ */ new Map();
129
+ const counterStyles = /* @__PURE__ */ new Map();
130
+ for (const item of current?.keyframes ?? []) keyframes.set(item.contentKey, {
131
+ ...item,
132
+ rscKeys: new Set(item.rscKeys)
133
+ });
134
+ for (const item of current?.counterStyles ?? []) counterStyles.set(item.name, new Set(item.rscKeys));
135
+ for (const item of next.properties) if (!properties.has(item.name)) properties.set(item.name, item.definition);
136
+ for (const item of next.keyframes) {
137
+ let entry = keyframes.get(item.contentKey);
138
+ if (!entry) {
139
+ entry = {
140
+ ...item,
141
+ rscKeys: /* @__PURE__ */ new Set()
142
+ };
143
+ keyframes.set(item.contentKey, entry);
144
+ }
145
+ for (const key of item.rscKeys) entry.rscKeys.add(key);
146
+ }
147
+ for (const item of next.counterStyles) {
148
+ let keys = counterStyles.get(item.name);
149
+ if (!keys) {
150
+ keys = /* @__PURE__ */ new Set();
151
+ counterStyles.set(item.name, keys);
152
+ }
153
+ for (const key of item.rscKeys) keys.add(key);
154
+ }
155
+ return {
156
+ properties: [...properties].map(([name, definition]) => ({
157
+ name,
158
+ definition
159
+ })),
160
+ keyframes: [...keyframes.values()].map((item) => ({
161
+ ...item,
162
+ rscKeys: [...item.rscKeys]
163
+ })),
164
+ fontFaces: [...new Set([...current?.fontFaces ?? [], ...next.fontFaces])],
165
+ counterStyles: [...counterStyles].map(([name, rscKeys]) => ({
166
+ name,
167
+ rscKeys: [...rscKeys]
168
+ })),
169
+ functions: [...new Set([...current?.functions ?? [], ...next.functions])],
170
+ rscKeys: [...new Set([...current?.rscKeys ?? [], ...next.rscKeys])]
171
+ };
172
+ }
173
+ /** Register one immutable stylesheet manifest. Returns whether it is usable. */
174
+ function registerPrecompiledManifest(manifest) {
175
+ if (!isManifestShapeValid(manifest)) {
176
+ warnPrecompileOnce(`invalid:${manifest?.id ?? "unknown"}`, "[Tasty] Ignoring an invalid precompiled style manifest.");
177
+ return false;
178
+ }
179
+ if (manifest.tastyVersion !== "0.0.0-snapshot.fde6cf3") {
180
+ warnPrecompileOnce(`version:${manifest.id}:${manifest.tastyVersion}`, `[Tasty] Ignoring precompiled styles "${manifest.id}": generated by Tasty ${manifest.tastyVersion}, but the runtime is ${TASTY_VERSION}.`);
181
+ return false;
182
+ }
183
+ const store = getPrecompileStore();
184
+ const existingManifest = store.manifests?.get(manifest.id);
185
+ if (existingManifest) {
186
+ if (existingManifest.cssHash === manifest.cssHash) return true;
187
+ warnPrecompileOnce(`manifest-conflict:${manifest.id}`, `[Tasty] Ignoring conflicting precompiled styles "${manifest.id}": the id is already registered with a different CSS hash.`);
188
+ return false;
189
+ }
190
+ const manifestChunks = /* @__PURE__ */ new Map();
191
+ for (const chunk of manifest.chunks) {
192
+ const duplicate = manifestChunks.get(chunk.lookupKey);
193
+ if (duplicate && (duplicate.className !== chunk.className || !sameStrings(duplicate.animations, chunk.animations))) {
194
+ warnPrecompileOnce(`internal-chunk-conflict:${manifest.id}:${chunk.lookupKey}`, `[Tasty] Ignoring precompiled styles "${manifest.id}": the manifest maps one chunk lookup key more than once with different metadata.`);
195
+ return false;
196
+ }
197
+ manifestChunks.set(chunk.lookupKey, chunk);
198
+ const existing = store.chunks?.get(chunk.lookupKey);
199
+ if (existing && (existing.className !== chunk.className || !sameStrings(existing.animations, chunk.animations))) {
200
+ warnPrecompileOnce(`chunk-conflict:${chunk.lookupKey}`, `[Tasty] Ignoring precompiled styles "${manifest.id}": a chunk lookup key is already mapped to different metadata by "${existing.manifestId}".`);
201
+ return false;
202
+ }
203
+ }
204
+ if (store.manifests) {
205
+ const propertyDefinitions = /* @__PURE__ */ new Map();
206
+ const keyframeNames = /* @__PURE__ */ new Map();
207
+ const keyframeContents = /* @__PURE__ */ new Map();
208
+ for (const registered of store.manifests.values()) {
209
+ for (const item of registered.dependencies.properties) propertyDefinitions.set(item.name, item.definition);
210
+ for (const item of registered.dependencies.keyframes) {
211
+ keyframeNames.set(item.name, item.contentKey);
212
+ keyframeContents.set(item.contentKey, item.name);
213
+ }
214
+ }
215
+ for (const item of manifest.dependencies.properties) {
216
+ const existing = propertyDefinitions.get(item.name);
217
+ if (existing !== void 0 && existing !== item.definition) {
218
+ warnPrecompileOnce(`property-conflict:${item.name}`, `[Tasty] Ignoring precompiled styles "${manifest.id}": @property ${item.name} conflicts with an already registered manifest.`);
219
+ return false;
220
+ }
221
+ }
222
+ for (const item of manifest.dependencies.keyframes) {
223
+ const contentForName = keyframeNames.get(item.name);
224
+ const nameForContent = keyframeContents.get(item.contentKey);
225
+ if (contentForName !== void 0 && contentForName !== item.contentKey || nameForContent !== void 0 && nameForContent !== item.name) {
226
+ warnPrecompileOnce(`keyframes-conflict:${item.name}:${item.contentKey}`, `[Tasty] Ignoring precompiled styles "${manifest.id}": its keyframe cache metadata conflicts with an already registered manifest.`);
227
+ return false;
228
+ }
229
+ }
230
+ }
231
+ const manifests = store.manifests ??= /* @__PURE__ */ new Map();
232
+ const chunks = store.chunks ??= /* @__PURE__ */ new Map();
233
+ const dependencies = store.dependencies ??= /* @__PURE__ */ new Map();
234
+ manifests.set(manifest.id, manifest);
235
+ dependencies.set(manifest.namePrefix, mergeDependencies(dependencies.get(manifest.namePrefix), manifest.dependencies));
236
+ for (const chunk of manifest.chunks) if (!chunks.has(chunk.lookupKey)) chunks.set(chunk.lookupKey, {
237
+ ...chunk,
238
+ manifestId: manifest.id,
239
+ namePrefix: manifest.namePrefix
240
+ });
241
+ store.active = true;
242
+ store.revision++;
243
+ store.validate = ensurePrecompiledConfigValidated;
244
+ return true;
245
+ }
246
+ /**
247
+ * Drop every catalog whose recorded configuration no longer matches this host's.
248
+ *
249
+ * Deferred to the moment the config locks rather than run at registration: the
250
+ * registration module is a side-effect import, so it routinely executes before
251
+ * the host's own `configure()` call and there is nothing final to compare yet.
252
+ *
253
+ * A lookup key is a hash of the style *source*, not of the CSS it produced, so
254
+ * a host that redefines a unit, handler, recipe or chunk assignment the catalog
255
+ * compiled against still hits — and would be served CSS its own configuration
256
+ * would never generate. Disabling the catalog costs the lookup and falls back
257
+ * to runtime generation, which is always correct.
258
+ *
259
+ * @internal
260
+ */
261
+ function validatePrecompiledCompilationConfig() {
262
+ const store = getPrecompileStore();
263
+ if (!store.manifests?.size) return;
264
+ const runtime = captureCompilationConfig();
265
+ const rejected = [];
266
+ for (const manifest of store.manifests.values()) {
267
+ const reasons = diffCompilationConfig(manifest.compilationConfig, runtime);
268
+ if (reasons.length === 0) continue;
269
+ rejected.push(manifest.id);
270
+ warnPrecompileOnce(`config-mismatch:${manifest.id}`, `[Tasty] Ignoring precompiled styles "${manifest.id}": this application's configuration differs from the one the catalog was compiled under, so its CSS is not what these settings would produce. Falling back to runtime generation. Differences: ${reasons.join(", ")}.`);
271
+ }
272
+ if (rejected.length === 0) return;
273
+ for (const id of rejected) store.manifests.delete(id);
274
+ const chunks = store.chunks ??= /* @__PURE__ */ new Map();
275
+ const dependencies = store.dependencies ??= /* @__PURE__ */ new Map();
276
+ chunks.clear();
277
+ dependencies.clear();
278
+ for (const manifest of store.manifests.values()) {
279
+ dependencies.set(manifest.namePrefix, mergeDependencies(dependencies.get(manifest.namePrefix), manifest.dependencies));
280
+ for (const chunk of manifest.chunks) if (!chunks.has(chunk.lookupKey)) chunks.set(chunk.lookupKey, {
281
+ ...chunk,
282
+ manifestId: manifest.id,
283
+ namePrefix: manifest.namePrefix
284
+ });
285
+ }
286
+ store.active = store.manifests.size > 0;
287
+ store.revision++;
288
+ }
289
+ /**
290
+ * Validate the registered catalogs once per registration, on first use.
291
+ *
292
+ * Called from the lookup path rather than from `configure()`: registration is a
293
+ * side-effect import that normally runs before the host configures anything, so
294
+ * there is no final configuration to compare until a render asks for a class.
295
+ */
296
+ function ensurePrecompiledConfigValidated() {
297
+ const store = getPrecompileStore();
298
+ if (store.validatedRevision === store.revision) return;
299
+ validatePrecompiledCompilationConfig();
300
+ store.validatedRevision = store.revision;
301
+ }
302
+ function isPrecompiledManifestRegistered(id, cssHash) {
303
+ const manifest = getPrecompileStore().manifests?.get(id);
304
+ return !!manifest && (cssHash === void 0 || manifest.cssHash === cssHash);
305
+ }
306
+ //#endregion
307
+ //#region src/precompile/register.ts
308
+ function registerTastyPrecompiled(manifest) {
309
+ registerPrecompiledManifest(manifest);
310
+ }
311
+ function installTastyPrecompiled(artifact, options) {
312
+ if (typeof document === "undefined") throw new Error("[Tasty] installTastyPrecompiled() is browser-only. Register the manifest and load its stylesheet separately during SSR.");
313
+ const installed = Array.from(document.querySelectorAll("style[data-tasty-precompiled]")).find((element) => element.dataset.tastyPrecompiled === artifact.manifest.id);
314
+ if (installed) {
315
+ if (installed.dataset.tastyPrecompiledHash !== artifact.manifest.cssHash) throw new Error(`[Tasty] A different precompiled stylesheet is already installed for "${artifact.manifest.id}".`);
316
+ registerPrecompiledManifest(artifact.manifest);
317
+ if (!isPrecompiledManifestRegistered(artifact.manifest.id, artifact.manifest.cssHash)) throw new Error(`[Tasty] The installed precompiled stylesheet "${artifact.manifest.id}" is incompatible with this runtime.`);
318
+ return;
319
+ }
320
+ if (isConfigLocked()) throw new Error("[Tasty] installTastyPrecompiled() must run before the first Tasty render.");
321
+ if (!registerPrecompiledManifest(artifact.manifest)) return;
322
+ const style = document.createElement("style");
323
+ style.dataset.tastyPrecompiled = artifact.manifest.id;
324
+ style.dataset.tastyPrecompiledHash = artifact.manifest.cssHash;
325
+ const nonce = options?.nonce ?? getConfig().nonce;
326
+ if (nonce) style.nonce = nonce;
327
+ style.textContent = artifact.css;
328
+ document.head.appendChild(style);
329
+ }
330
+ //#endregion
331
+ export { TASTY_VERSION as i, registerTastyPrecompiled as n, captureCompilationConfig as r, installTastyPrecompiled as t };
332
+
333
+ //# sourceMappingURL=register-BkC-8Zuy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-BkC-8Zuy.js","names":[],"sources":["../src/version.ts","../src/precompile/fingerprint.ts","../src/precompile/registry.ts","../src/precompile/register.ts"],"sourcesContent":["/** Package version injected by builds; the fallback supports direct source consumers. */\nexport const TASTY_VERSION =\n typeof __TASTY_VERSION__ === 'string' ? __TASTY_VERSION__ : '3.6.0';\n","import {\n getConfig,\n getConfiguredOverrides,\n getGlobalRecipes,\n isFunctionsPolyfillEnabled,\n} from '../config';\nimport { getGlobalPredefinedStates } from '../states';\nimport { hashString } from '../utils/hash';\nimport {\n getGlobalParseFunctions,\n getGlobalParser,\n getGlobalPredefinedTokens,\n} from '../utils/styles';\n\nimport type { TastyCompilationConfig } from './types';\n\n/**\n * A stable token for an arbitrary configuration value.\n *\n * Function-valued entries (unit handlers, parse functions) cannot be compared\n * by body: a catalog is compiled from an unminified build while the runtime may\n * be reading a minified one, so `toString()` differs for identical behaviour and\n * would reject every production bundle. Their presence and arity are recorded\n * instead, which catches an entry being added, removed or swapped for one of a\n * different shape — not a rewritten body. That gap is documented on\n * `TastyCompilationConfig`.\n */\nfunction token(value: unknown): string {\n if (typeof value === 'function') return `fn/${value.length}`;\n if (value === undefined) return 'undefined';\n if (typeof value === 'string') return `s/${hashString(value)}`;\n\n return `j/${hashString(stableStringify(value))}`;\n}\n\n/** JSON with object keys sorted, so key order cannot change the token. */\nfunction stableStringify(value: unknown): string {\n if (value === null || typeof value !== 'object')\n return JSON.stringify(value) ?? 'undefined';\n if (Array.isArray(value)) {\n return `[${value.map(stableStringify).join(',')}]`;\n }\n\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([, item]) => item !== undefined)\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));\n\n return `{${entries.map(([key, item]) => `${JSON.stringify(key)}:${stableStringify(item)}`).join(',')}}`;\n}\n\n/**\n * Entries recorded in `configure()` order, deduped into a comparable map.\n * Later calls win, matching how `configure()` merges them.\n */\nfunction named(\n entries: readonly (readonly [string, unknown])[],\n): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [name, definition] of entries) out[name] = definition;\n\n return out;\n}\n\nfunction tokenize(\n source: Record<string, unknown> | null | undefined,\n prefix: string,\n) {\n const out: Record<string, string> = {};\n if (!source) return out;\n\n for (const key of Object.keys(source).sort()) {\n out[`${prefix}:${key}`] = token(source[key]);\n }\n\n return out;\n}\n\n/**\n * Snapshot the configuration a precompiled catalog was compiled under.\n *\n * Read at build time into the manifest, and again at runtime once the config\n * locks, so the two can be compared before any lookup trusts the catalog.\n */\nexport function captureCompilationConfig(): TastyCompilationConfig {\n const config = getConfig();\n const parser = getGlobalParser();\n const overrides = getConfiguredOverrides();\n\n return {\n scoped: {\n ...tokenize(getGlobalPredefinedStates(), 'state'),\n ...tokenize(parser.getUnits() as Record<string, unknown>, 'unit'),\n ...tokenize(getGlobalRecipes(), 'recipe'),\n // Declarative `$$` CSS functions, read from what the host passed to\n // `configure()` rather than from `getGlobalFunctions()`. With\n // `polyfills.functions` enabled that registry stays empty and only a\n // synthesized closure remains, so rewriting `$$scale` from\n // `2 * $value` to `3 * $value` would keep the same name and arity and\n // compare equal while the expanded CSS changed.\n ...tokenize(named(overrides.functions), 'fn'),\n // Bare-key parse functions, which live in their own registry. Recorded\n // by presence and arity only — see `token()`.\n ...tokenize(getGlobalParseFunctions(), 'parseFn'),\n // `replaceTokens` only. Its values are substituted at parse time and\n // baked into the declaration (`padding: 8px`), so a changed value makes\n // a compiled chunk wrong while its lookup key — a hash of the style\n // source — stays the same.\n //\n // `configure({ tokens })` deliberately does NOT belong here. Those emit\n // `:root` custom properties, which the catalog excludes, and a chunk\n // using `#brand` compiles to `var(--brand-color)` whatever the current\n // value is. The runtime `:root` rule supplies the new value, so the\n // chunk stays correct across a palette change — and fingerprinting them\n // would disable the whole catalog on every theme, which is exactly the\n // dynamic behaviour `docs/precompile.md` promises.\n ...tokenize(getGlobalPredefinedTokens(), 'replaceToken'),\n },\n // Names the host passed to `configure()`, not the live handler registry:\n // that registry is populated lazily as styles are encountered, so it\n // describes which styles have rendered so far rather than configuration.\n exclusive: {\n ...tokenize(named(overrides.handlers), 'handler'),\n ...tokenize(named(overrides.propHandlers), 'propHandler'),\n },\n scalars: {\n // Compare effective behaviour, not the literal setting: the default is\n // enabled, so an omitted value and an explicit `true` are the same thing\n // and must not read as a divergence.\n autoPropertyTypes: String(config.autoPropertyTypes !== false),\n functionsPolyfill: String(isFunctionsPolyfillEnabled()),\n },\n };\n}\n\n/**\n * Describe every way `runtime` would compile differently from `compiled`.\n *\n * An empty result means the catalog's CSS is still what this configuration\n * would produce. Names are reported rather than counted so the warning tells\n * the consumer which setting to look at.\n */\nexport function diffCompilationConfig(\n compiled: TastyCompilationConfig,\n runtime: TastyCompilationConfig,\n): string[] {\n const reasons: string[] = [];\n\n for (const [key, value] of Object.entries(compiled.scalars)) {\n const current = runtime.scalars[key];\n if (current !== value) {\n reasons.push(`${key} changed`);\n }\n }\n\n // A name the catalog never saw cannot change a chunk it already compiled, so\n // additions are accepted here; a changed or dropped one is not.\n for (const [key, value] of Object.entries(compiled.scoped)) {\n const current = runtime.scoped[key];\n if (current === undefined) {\n reasons.push(`${key} removed`);\n } else if (current !== value) {\n reasons.push(`${key} changed`);\n }\n }\n\n // These record deviations from Tasty's built-in tables, which `tastyVersion`\n // already pins. A runtime-only entry is therefore an override of a built-in\n // the catalog may have compiled against, so extra keys count too.\n const exclusiveKeys = new Set([\n ...Object.keys(compiled.exclusive),\n ...Object.keys(runtime.exclusive),\n ]);\n for (const key of exclusiveKeys) {\n const before = compiled.exclusive[key];\n const after = runtime.exclusive[key];\n if (before === after) continue;\n reasons.push(\n before === undefined\n ? `${key} added`\n : after === undefined\n ? `${key} removed`\n : `${key} changed`,\n );\n }\n\n return reasons.sort();\n}\n\nexport function isCompilationConfigShapeValid(\n value: TastyCompilationConfig | undefined,\n): boolean {\n const isTokenMap = (map: unknown) =>\n !!map &&\n typeof map === 'object' &&\n !Array.isArray(map) &&\n Object.values(map as Record<string, unknown>).every(\n (item) => typeof item === 'string',\n );\n\n return (\n !!value &&\n isTokenMap(value.scoped) &&\n isTokenMap(value.exclusive) &&\n isTokenMap(value.scalars)\n );\n}\n","import { TASTY_VERSION } from '../version';\n\nimport {\n captureCompilationConfig,\n diffCompilationConfig,\n isCompilationConfigShapeValid,\n} from './fingerprint';\nimport { getPrecompileStore, warnPrecompileOnce } from './runtime';\nimport type {\n TastyCompilationConfig,\n TastyPrecompiledChunk,\n TastyPrecompiledDependencies,\n TastyPrecompiledManifest,\n} from './types';\n\nconst isStringArray = (value: unknown): boolean =>\n Array.isArray(value) && value.every((item) => typeof item === 'string');\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n !!value && typeof value === 'object' && !Array.isArray(value);\n\n/**\n * The documented workflow imports a manifest from JSON and casts it, so the\n * shape is only as good as the file — and the input is `unknown` here for that\n * reason. Checking that a dependency field is an array is not enough:\n * `keyframes: [{}]` would pass and then throw while iterating `item.rscKeys`\n * in `mergeDependencies`, and `chunks: [null]` would throw inside the\n * validator itself. Nor is optional chaining enough at the top level: `null`\n * survives `manifest?.dependencies` and then throws on `manifest.schemaVersion`\n * before registration can warn. A malformed manifest should be warned about\n * and ignored, never crash registration.\n */\nfunction isManifestShapeValid(\n manifest: unknown,\n): manifest is TastyPrecompiledManifest {\n if (!isRecord(manifest)) return false;\n const dependencies = manifest.dependencies;\n const stats = manifest.stats;\n return (\n manifest.schemaVersion === 2 &&\n isCompilationConfigShapeValid(\n manifest.compilationConfig as TastyCompilationConfig | undefined,\n ) &&\n typeof manifest.id === 'string' &&\n manifest.id.length > 0 &&\n typeof manifest.tastyVersion === 'string' &&\n typeof manifest.namePrefix === 'string' &&\n typeof manifest.cssHash === 'string' &&\n manifest.cssHash.length > 0 &&\n isRecord(stats) &&\n Number.isSafeInteger(stats.cssSize) &&\n (stats.cssSize as number) >= 0 &&\n Number.isSafeInteger(stats.ruleCount) &&\n (stats.ruleCount as number) >= 0 &&\n Array.isArray(manifest.chunks) &&\n manifest.chunks.every(\n (chunk) =>\n isRecord(chunk) &&\n typeof chunk.lookupKey === 'string' &&\n typeof chunk.className === 'string' &&\n isStringArray(chunk.animations),\n ) &&\n isRecord(dependencies) &&\n Array.isArray(dependencies.properties) &&\n dependencies.properties.every(\n (item) =>\n isRecord(item) &&\n typeof item.name === 'string' &&\n typeof item.definition === 'string',\n ) &&\n Array.isArray(dependencies.keyframes) &&\n dependencies.keyframes.every(\n (item) =>\n isRecord(item) &&\n typeof item.name === 'string' &&\n typeof item.contentKey === 'string' &&\n isStringArray(item.rscKeys),\n ) &&\n isStringArray(dependencies.fontFaces) &&\n Array.isArray(dependencies.counterStyles) &&\n dependencies.counterStyles.every(\n (item) =>\n isRecord(item) &&\n typeof item.name === 'string' &&\n isStringArray(item.rscKeys),\n ) &&\n isStringArray(dependencies.functions) &&\n isStringArray(dependencies.rscKeys)\n );\n}\n\nfunction sameStrings(a: readonly string[], b: readonly string[]): boolean {\n return a.length === b.length && a.every((value, index) => value === b[index]);\n}\n\nfunction mergeDependencies(\n current: TastyPrecompiledDependencies | undefined,\n next: TastyPrecompiledDependencies,\n): TastyPrecompiledDependencies {\n const properties = new Map(\n current?.properties.map((item) => [item.name, item.definition]),\n );\n const keyframes = new Map<\n string,\n { name: string; contentKey: string; rscKeys: Set<string> }\n >();\n const counterStyles = new Map<string, Set<string>>();\n\n for (const item of current?.keyframes ?? []) {\n keyframes.set(item.contentKey, {\n ...item,\n rscKeys: new Set(item.rscKeys),\n });\n }\n for (const item of current?.counterStyles ?? []) {\n counterStyles.set(item.name, new Set(item.rscKeys));\n }\n\n for (const item of next.properties) {\n if (!properties.has(item.name)) properties.set(item.name, item.definition);\n }\n for (const item of next.keyframes) {\n let entry = keyframes.get(item.contentKey);\n if (!entry) {\n entry = { ...item, rscKeys: new Set() };\n keyframes.set(item.contentKey, entry);\n }\n for (const key of item.rscKeys) entry.rscKeys.add(key);\n }\n for (const item of next.counterStyles) {\n let keys = counterStyles.get(item.name);\n if (!keys) {\n keys = new Set();\n counterStyles.set(item.name, keys);\n }\n for (const key of item.rscKeys) keys.add(key);\n }\n\n return {\n properties: [...properties].map(([name, definition]) => ({\n name,\n definition,\n })),\n keyframes: [...keyframes.values()].map((item) => ({\n ...item,\n rscKeys: [...item.rscKeys],\n })),\n fontFaces: [...new Set([...(current?.fontFaces ?? []), ...next.fontFaces])],\n counterStyles: [...counterStyles].map(([name, rscKeys]) => ({\n name,\n rscKeys: [...rscKeys],\n })),\n functions: [...new Set([...(current?.functions ?? []), ...next.functions])],\n rscKeys: [...new Set([...(current?.rscKeys ?? []), ...next.rscKeys])],\n };\n}\n\n/** Register one immutable stylesheet manifest. Returns whether it is usable. */\nexport function registerPrecompiledManifest(\n manifest: TastyPrecompiledManifest,\n): boolean {\n if (!isManifestShapeValid(manifest)) {\n warnPrecompileOnce(\n `invalid:${(manifest as TastyPrecompiledManifest | null)?.id ?? 'unknown'}`,\n '[Tasty] Ignoring an invalid precompiled style manifest.',\n );\n return false;\n }\n\n if (manifest.tastyVersion !== TASTY_VERSION) {\n warnPrecompileOnce(\n `version:${manifest.id}:${manifest.tastyVersion}`,\n `[Tasty] Ignoring precompiled styles \"${manifest.id}\": generated by Tasty ${manifest.tastyVersion}, but the runtime is ${TASTY_VERSION}.`,\n );\n return false;\n }\n\n const store = getPrecompileStore();\n const existingManifest = store.manifests?.get(manifest.id);\n if (existingManifest) {\n if (existingManifest.cssHash === manifest.cssHash) return true;\n warnPrecompileOnce(\n `manifest-conflict:${manifest.id}`,\n `[Tasty] Ignoring conflicting precompiled styles \"${manifest.id}\": the id is already registered with a different CSS hash.`,\n );\n return false;\n }\n\n const manifestChunks = new Map<string, TastyPrecompiledChunk>();\n for (const chunk of manifest.chunks) {\n const duplicate = manifestChunks.get(chunk.lookupKey);\n if (\n duplicate &&\n (duplicate.className !== chunk.className ||\n !sameStrings(duplicate.animations, chunk.animations))\n ) {\n warnPrecompileOnce(\n `internal-chunk-conflict:${manifest.id}:${chunk.lookupKey}`,\n `[Tasty] Ignoring precompiled styles \"${manifest.id}\": the manifest maps one chunk lookup key more than once with different metadata.`,\n );\n return false;\n }\n manifestChunks.set(chunk.lookupKey, chunk);\n\n const existing = store.chunks?.get(chunk.lookupKey);\n if (\n existing &&\n (existing.className !== chunk.className ||\n !sameStrings(existing.animations, chunk.animations))\n ) {\n warnPrecompileOnce(\n `chunk-conflict:${chunk.lookupKey}`,\n `[Tasty] Ignoring precompiled styles \"${manifest.id}\": a chunk lookup key is already mapped to different metadata by \"${existing.manifestId}\".`,\n );\n return false;\n }\n }\n\n if (store.manifests) {\n const propertyDefinitions = new Map<string, string>();\n const keyframeNames = new Map<string, string>();\n const keyframeContents = new Map<string, string>();\n for (const registered of store.manifests.values()) {\n for (const item of registered.dependencies.properties) {\n propertyDefinitions.set(item.name, item.definition);\n }\n for (const item of registered.dependencies.keyframes) {\n keyframeNames.set(item.name, item.contentKey);\n keyframeContents.set(item.contentKey, item.name);\n }\n }\n for (const item of manifest.dependencies.properties) {\n const existing = propertyDefinitions.get(item.name);\n if (existing !== undefined && existing !== item.definition) {\n warnPrecompileOnce(\n `property-conflict:${item.name}`,\n `[Tasty] Ignoring precompiled styles \"${manifest.id}\": @property ${item.name} conflicts with an already registered manifest.`,\n );\n return false;\n }\n }\n for (const item of manifest.dependencies.keyframes) {\n const contentForName = keyframeNames.get(item.name);\n const nameForContent = keyframeContents.get(item.contentKey);\n if (\n (contentForName !== undefined && contentForName !== item.contentKey) ||\n (nameForContent !== undefined && nameForContent !== item.name)\n ) {\n warnPrecompileOnce(\n `keyframes-conflict:${item.name}:${item.contentKey}`,\n `[Tasty] Ignoring precompiled styles \"${manifest.id}\": its keyframe cache metadata conflicts with an already registered manifest.`,\n );\n return false;\n }\n }\n }\n\n const manifests = (store.manifests ??= new Map());\n const chunks = (store.chunks ??= new Map());\n const dependencies = (store.dependencies ??= new Map());\n manifests.set(manifest.id, manifest);\n dependencies.set(\n manifest.namePrefix,\n mergeDependencies(\n dependencies.get(manifest.namePrefix),\n manifest.dependencies,\n ),\n );\n for (const chunk of manifest.chunks) {\n if (!chunks.has(chunk.lookupKey)) {\n chunks.set(chunk.lookupKey, {\n ...chunk,\n manifestId: manifest.id,\n namePrefix: manifest.namePrefix,\n });\n }\n }\n store.active = true;\n store.revision++;\n store.validate = ensurePrecompiledConfigValidated;\n return true;\n}\n\n/**\n * Drop every catalog whose recorded configuration no longer matches this host's.\n *\n * Deferred to the moment the config locks rather than run at registration: the\n * registration module is a side-effect import, so it routinely executes before\n * the host's own `configure()` call and there is nothing final to compare yet.\n *\n * A lookup key is a hash of the style *source*, not of the CSS it produced, so\n * a host that redefines a unit, handler, recipe or chunk assignment the catalog\n * compiled against still hits — and would be served CSS its own configuration\n * would never generate. Disabling the catalog costs the lookup and falls back\n * to runtime generation, which is always correct.\n *\n * @internal\n */\nexport function validatePrecompiledCompilationConfig(): void {\n const store = getPrecompileStore();\n if (!store.manifests?.size) return;\n\n const runtime = captureCompilationConfig();\n const rejected: string[] = [];\n\n for (const manifest of store.manifests.values()) {\n const reasons = diffCompilationConfig(manifest.compilationConfig, runtime);\n if (reasons.length === 0) continue;\n\n rejected.push(manifest.id);\n warnPrecompileOnce(\n `config-mismatch:${manifest.id}`,\n `[Tasty] Ignoring precompiled styles \"${manifest.id}\": this application's configuration differs from the one the catalog was compiled under, so its CSS is not what these settings would produce. Falling back to runtime generation. Differences: ${reasons.join(', ')}.`,\n );\n }\n\n if (rejected.length === 0) return;\n\n for (const id of rejected) store.manifests.delete(id);\n\n // Rebuild rather than subtract: a lookup key dropped by one catalog may still\n // be provided by another that is still valid.\n const chunks = (store.chunks ??= new Map());\n const dependencies = (store.dependencies ??= new Map());\n chunks.clear();\n dependencies.clear();\n\n for (const manifest of store.manifests.values()) {\n dependencies.set(\n manifest.namePrefix,\n mergeDependencies(\n dependencies.get(manifest.namePrefix),\n manifest.dependencies,\n ),\n );\n for (const chunk of manifest.chunks) {\n if (!chunks.has(chunk.lookupKey)) {\n chunks.set(chunk.lookupKey, {\n ...chunk,\n manifestId: manifest.id,\n namePrefix: manifest.namePrefix,\n });\n }\n }\n }\n\n store.active = store.manifests.size > 0;\n store.revision++;\n}\n\n/**\n * Validate the registered catalogs once per registration, on first use.\n *\n * Called from the lookup path rather than from `configure()`: registration is a\n * side-effect import that normally runs before the host configures anything, so\n * there is no final configuration to compare until a render asks for a class.\n */\nexport function ensurePrecompiledConfigValidated(): void {\n const store = getPrecompileStore();\n if (store.validatedRevision === store.revision) return;\n\n // Set first: validation rebuilds the store and bumps `revision`, and the\n // result of that rebuild is what we just checked.\n validatePrecompiledCompilationConfig();\n store.validatedRevision = store.revision;\n}\n\nexport function isPrecompiledManifestRegistered(\n id: string,\n cssHash?: string,\n): boolean {\n const manifest = getPrecompileStore().manifests?.get(id);\n return !!manifest && (cssHash === undefined || manifest.cssHash === cssHash);\n}\n","import { getConfig, isConfigLocked } from '../config';\n\nimport {\n isPrecompiledManifestRegistered,\n registerPrecompiledManifest,\n} from './registry';\nimport type { TastyPrecompiledManifest } from './types';\n\nexport type {\n PrecompiledCounterStyleCacheEntry,\n PrecompiledKeyframeCacheEntry,\n PrecompiledPropertyCacheEntry,\n TastyPrecompiledChunk,\n TastyPrecompiledDependencies,\n TastyPrecompiledManifest,\n TastyPrecompiledStats,\n} from './types';\n\nexport function registerTastyPrecompiled(\n manifest: TastyPrecompiledManifest,\n): void {\n registerPrecompiledManifest(manifest);\n}\n\nexport function installTastyPrecompiled(\n artifact: { css: string; manifest: TastyPrecompiledManifest },\n options?: { nonce?: string },\n): void {\n if (typeof document === 'undefined') {\n throw new Error(\n '[Tasty] installTastyPrecompiled() is browser-only. Register the manifest and load its stylesheet separately during SSR.',\n );\n }\n\n const installed = Array.from(\n document.querySelectorAll<HTMLStyleElement>(\n 'style[data-tasty-precompiled]',\n ),\n ).find(\n (element) => element.dataset.tastyPrecompiled === artifact.manifest.id,\n );\n if (installed) {\n if (installed.dataset.tastyPrecompiledHash !== artifact.manifest.cssHash) {\n throw new Error(\n `[Tasty] A different precompiled stylesheet is already installed for \"${artifact.manifest.id}\".`,\n );\n }\n registerPrecompiledManifest(artifact.manifest);\n if (\n !isPrecompiledManifestRegistered(\n artifact.manifest.id,\n artifact.manifest.cssHash,\n )\n ) {\n throw new Error(\n `[Tasty] The installed precompiled stylesheet \"${artifact.manifest.id}\" is incompatible with this runtime.`,\n );\n }\n return;\n }\n\n if (isConfigLocked()) {\n throw new Error(\n '[Tasty] installTastyPrecompiled() must run before the first Tasty render.',\n );\n }\n\n if (!registerPrecompiledManifest(artifact.manifest)) return;\n\n const style = document.createElement('style');\n style.dataset.tastyPrecompiled = artifact.manifest.id;\n style.dataset.tastyPrecompiledHash = artifact.manifest.cssHash;\n const nonce = options?.nonce ?? getConfig().nonce;\n if (nonce) style.nonce = nonce;\n style.textContent = artifact.css;\n document.head.appendChild(style);\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { I as isSelector, Qt as isDevEnv, u as getGlobalRecipes } from "./config-B23gZrfP.js";
2
- import { t as mergeStyles } from "./merge-styles-C-uwpoNW.js";
1
+ import { L as isSelector, d as getGlobalRecipes, dn as isDevEnv } from "./config-Bd2vOF0Z.js";
2
+ import { t as mergeStyles } from "./merge-styles-BbJhjesV.js";
3
3
  //#region src/utils/resolve-recipes.ts
4
4
  /**
5
5
  * Recipe resolution utility.
@@ -141,4 +141,4 @@ function resolveRecipes(styles) {
141
141
  //#endregion
142
142
  export { resolveRecipes as t };
143
143
 
144
- //# sourceMappingURL=resolve-recipes-BuOvSEa2.js.map
144
+ //# sourceMappingURL=resolve-recipes-B2Sf36AH.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-recipes-BuOvSEa2.js","names":[],"sources":["../src/utils/resolve-recipes.ts"],"sourcesContent":["/**\n * Recipe resolution utility.\n *\n * Resolves `recipe` style properties by looking up predefined recipe styles\n * from global configuration and merging them with the component's own styles.\n *\n * Resolution order per level (top-level and each sub-element independently):\n * base_recipe_1 base_recipe_2 → component styles → post_recipe_1 post_recipe_2\n *\n * The `/` separator splits base recipes (before component styles)\n * from post recipes (after component styles). All merges use mergeStyles\n * semantics: primitives and state maps with '' key fully replace;\n * state maps without '' key extend the existing value.\n *\n * Returns the same object reference if no recipes are present (zero overhead).\n */\n\nimport { getGlobalRecipes } from '../config';\nimport { isSelector } from '../pipeline';\nimport type { RecipeStyles, Styles } from '../styles/types';\n\nimport { isDevEnv } from './is-dev-env';\nimport { mergeStyles } from './merge-styles';\n\nconst devMode = isDevEnv();\n\ninterface ParsedRecipeGroups {\n base: string[] | null;\n post: string[] | null;\n}\n\n/**\n * Parse a recipe string into base and post recipe name groups.\n *\n * Syntax: `'base1 base2 / post1 post2'`\n * - Names are space-separated within each group\n * - `/` separates base (before component) from post (after component) groups\n * - `/` is optional; if absent, all names are base\n * - `none` as the sole base value means \"no base recipes\"\n *\n * Returns `{ base: null, post: null }` if the string is empty or invalid.\n */\nfunction parseRecipeNames(value: unknown): ParsedRecipeGroups {\n const empty: ParsedRecipeGroups = { base: null, post: null };\n\n if (typeof value !== 'string') return empty;\n const trimmed = value.trim();\n if (trimmed === '') return empty;\n\n const slashIndex = trimmed.indexOf('/');\n\n if (slashIndex === -1) {\n if (trimmed === 'none') return empty;\n const names = splitNames(trimmed);\n return { base: names, post: null };\n }\n\n const basePart = trimmed.slice(0, slashIndex);\n const postPart = trimmed.slice(slashIndex + 1);\n\n return {\n base: basePart.trim() === 'none' ? null : splitNames(basePart),\n post: splitNames(postPart),\n };\n}\n\nfunction splitNames(s: string): string[] | null {\n const names = s.split(/\\s+/).filter(Boolean);\n return names.length > 0 ? names : null;\n}\n\n/**\n * Collect merged styles for a list of recipe names.\n * Each recipe is flat-spread on top of the previous.\n */\nfunction collectRecipeStyles(\n names: string[],\n recipes: Record<string, RecipeStyles>,\n): Record<string, unknown> {\n let merged: Record<string, unknown> = {};\n\n for (const name of names) {\n const recipeStyles = recipes[name];\n\n if (!recipeStyles) {\n if (devMode) {\n console.warn(\n `[Tasty] Recipe \"${name}\" not found. ` +\n `Make sure it is defined in configure({ recipes: { ... } }).`,\n );\n }\n continue;\n }\n\n merged = { ...merged, ...(recipeStyles as Record<string, unknown>) };\n }\n\n return merged;\n}\n\n/**\n * Resolve recipe references in a flat styles object (no sub-elements).\n * Returns null if no `recipe` key is present.\n *\n * Resolution: base recipes → component styles → post recipes (all via mergeStyles)\n */\nfunction resolveRecipesForLevel(\n styles: Record<string, unknown>,\n recipes: Record<string, RecipeStyles>,\n): Record<string, unknown> | null {\n if (!('recipe' in styles)) return null;\n\n const { base, post } = parseRecipeNames(styles.recipe);\n\n // Separate selector keys (sub-elements) from flat style properties.\n // mergeStyles handles selectors with its own semantics (e.g. false = delete),\n // but at this level we only want recipe merging on flat properties.\n\n const { recipe: _recipe, ...allRest } = styles;\n const flatStyles: Record<string, unknown> = {};\n const selectorStyles: Record<string, unknown> = {};\n\n for (const key of Object.keys(allRest)) {\n if (isSelector(key)) {\n selectorStyles[key] = allRest[key];\n } else {\n flatStyles[key] = allRest[key];\n }\n }\n\n if (!base && !post) {\n return allRest;\n }\n\n // 1. Merge base recipes, then component styles on top (via mergeStyles)\n let result: Record<string, unknown>;\n\n if (base) {\n const baseStyles = collectRecipeStyles(base, recipes);\n result = mergeStyles(baseStyles as Styles, flatStyles as Styles) as Record<\n string,\n unknown\n >;\n } else {\n result = { ...flatStyles };\n }\n\n // 2. Apply post recipes via mergeStyles (state map extend semantics)\n if (post) {\n const postStyles = collectRecipeStyles(post, recipes);\n result = mergeStyles(result as Styles, postStyles as Styles) as Record<\n string,\n unknown\n >;\n }\n\n // Re-attach selector keys unchanged\n for (const key of Object.keys(selectorStyles)) {\n result[key] = selectorStyles[key];\n }\n\n return result;\n}\n\n/**\n * Resolve all `recipe` style properties in a styles object.\n *\n * Handles both top-level and sub-element recipe references.\n * Returns the same object reference if no recipes are present anywhere\n * (zero overhead for the common case).\n *\n * @param styles - The styles object potentially containing `recipe` keys\n * @returns Resolved styles with recipe values merged in, or the original object if unchanged\n */\nexport function resolveRecipes(styles: Styles): Styles {\n const recipes = getGlobalRecipes();\n\n // Fast path: no recipes configured globally\n if (!recipes) return styles;\n\n let changed = false;\n\n // Resolve top-level recipe\n const topResolved = resolveRecipesForLevel(\n styles as Record<string, unknown>,\n recipes,\n );\n\n let result: Record<string, unknown>;\n\n if (topResolved) {\n changed = true;\n result = topResolved;\n } else {\n // Keep reference; a shallow copy is deferred until a sub-element actually changes\n result = styles as Record<string, unknown>;\n }\n\n // Resolve sub-element recipes\n const keys = Object.keys(result);\n\n for (const key of keys) {\n if (!isSelector(key)) continue;\n\n const subStyles = result[key];\n\n if (\n !subStyles ||\n typeof subStyles !== 'object' ||\n Array.isArray(subStyles)\n ) {\n continue;\n }\n\n const subRecord = subStyles as Record<string, unknown>;\n\n if (!('recipe' in subRecord)) continue;\n\n const subResolved = resolveRecipesForLevel(subRecord, recipes);\n\n if (subResolved) {\n if (!changed) {\n // First change in sub-elements -- need to shallow-copy the top level\n changed = true;\n result = { ...(styles as Record<string, unknown>) };\n }\n result[key] = subResolved;\n }\n }\n\n return changed ? (result as Styles) : styles;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAwBA,MAAM,UAAU,SAAS;;;;;;;;;;;;AAkBzB,SAAS,iBAAiB,OAAoC;CAC5D,MAAM,QAA4B;EAAE,MAAM;EAAM,MAAM;CAAK;CAE3D,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,MAAM,UAAU,MAAM,KAAK;CAC3B,IAAI,YAAY,IAAI,OAAO;CAE3B,MAAM,aAAa,QAAQ,QAAQ,GAAG;CAEtC,IAAI,eAAe,IAAI;EACrB,IAAI,YAAY,QAAQ,OAAO;EAE/B,OAAO;GAAE,MADK,WAAW,OACN;GAAG,MAAM;EAAK;CACnC;CAEA,MAAM,WAAW,QAAQ,MAAM,GAAG,UAAU;CAC5C,MAAM,WAAW,QAAQ,MAAM,aAAa,CAAC;CAE7C,OAAO;EACL,MAAM,SAAS,KAAK,MAAM,SAAS,OAAO,WAAW,QAAQ;EAC7D,MAAM,WAAW,QAAQ;CAC3B;AACF;AAEA,SAAS,WAAW,GAA4B;CAC9C,MAAM,QAAQ,EAAE,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO;CAC3C,OAAO,MAAM,SAAS,IAAI,QAAQ;AACpC;;;;;AAMA,SAAS,oBACP,OACA,SACyB;CACzB,IAAI,SAAkC,CAAC;CAEvC,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,eAAe,QAAQ;EAE7B,IAAI,CAAC,cAAc;GACjB,IAAI,SACF,QAAQ,KACN,mBAAmB,KAAK,yEAE1B;GAEF;EACF;EAEA,SAAS;GAAE,GAAG;GAAQ,GAAI;EAAyC;CACrE;CAEA,OAAO;AACT;;;;;;;AAQA,SAAS,uBACP,QACA,SACgC;CAChC,IAAI,EAAE,YAAY,SAAS,OAAO;CAElC,MAAM,EAAE,MAAM,SAAS,iBAAiB,OAAO,MAAM;CAMrD,MAAM,EAAE,QAAQ,SAAS,GAAG,YAAY;CACxC,MAAM,aAAsC,CAAC;CAC7C,MAAM,iBAA0C,CAAC;CAEjD,KAAK,MAAM,OAAO,OAAO,KAAK,OAAO,GACnC,IAAI,WAAW,GAAG,GAChB,eAAe,OAAO,QAAQ;MAE9B,WAAW,OAAO,QAAQ;CAI9B,IAAI,CAAC,QAAQ,CAAC,MACZ,OAAO;CAIT,IAAI;CAEJ,IAAI,MAEF,SAAS,YADU,oBAAoB,MAAM,OACf,GAAa,UAAoB;MAK/D,SAAS,EAAE,GAAG,WAAW;CAI3B,IAAI,MAAM;EACR,MAAM,aAAa,oBAAoB,MAAM,OAAO;EACpD,SAAS,YAAY,QAAkB,UAAoB;CAI7D;CAGA,KAAK,MAAM,OAAO,OAAO,KAAK,cAAc,GAC1C,OAAO,OAAO,eAAe;CAG/B,OAAO;AACT;;;;;;;;;;;AAYA,SAAgB,eAAe,QAAwB;CACrD,MAAM,UAAU,iBAAiB;CAGjC,IAAI,CAAC,SAAS,OAAO;CAErB,IAAI,UAAU;CAGd,MAAM,cAAc,uBAClB,QACA,OACF;CAEA,IAAI;CAEJ,IAAI,aAAa;EACf,UAAU;EACV,SAAS;CACX,OAEE,SAAS;CAIX,MAAM,OAAO,OAAO,KAAK,MAAM;CAE/B,KAAK,MAAM,OAAO,MAAM;EACtB,IAAI,CAAC,WAAW,GAAG,GAAG;EAEtB,MAAM,YAAY,OAAO;EAEzB,IACE,CAAC,aACD,OAAO,cAAc,YACrB,MAAM,QAAQ,SAAS,GAEvB;EAGF,MAAM,YAAY;EAElB,IAAI,EAAE,YAAY,YAAY;EAE9B,MAAM,cAAc,uBAAuB,WAAW,OAAO;EAE7D,IAAI,aAAa;GACf,IAAI,CAAC,SAAS;IAEZ,UAAU;IACV,SAAS,EAAE,GAAI,OAAmC;GACpD;GACA,OAAO,OAAO;EAChB;CACF;CAEA,OAAO,UAAW,SAAoB;AACxC"}
1
+ {"version":3,"file":"resolve-recipes-B2Sf36AH.js","names":[],"sources":["../src/utils/resolve-recipes.ts"],"sourcesContent":["/**\n * Recipe resolution utility.\n *\n * Resolves `recipe` style properties by looking up predefined recipe styles\n * from global configuration and merging them with the component's own styles.\n *\n * Resolution order per level (top-level and each sub-element independently):\n * base_recipe_1 base_recipe_2 → component styles → post_recipe_1 post_recipe_2\n *\n * The `/` separator splits base recipes (before component styles)\n * from post recipes (after component styles). All merges use mergeStyles\n * semantics: primitives and state maps with '' key fully replace;\n * state maps without '' key extend the existing value.\n *\n * Returns the same object reference if no recipes are present (zero overhead).\n */\n\nimport { getGlobalRecipes } from '../config';\nimport { isSelector } from '../pipeline';\nimport type { RecipeStyles, Styles } from '../styles/types';\n\nimport { isDevEnv } from './is-dev-env';\nimport { mergeStyles } from './merge-styles';\n\nconst devMode = isDevEnv();\n\ninterface ParsedRecipeGroups {\n base: string[] | null;\n post: string[] | null;\n}\n\n/**\n * Parse a recipe string into base and post recipe name groups.\n *\n * Syntax: `'base1 base2 / post1 post2'`\n * - Names are space-separated within each group\n * - `/` separates base (before component) from post (after component) groups\n * - `/` is optional; if absent, all names are base\n * - `none` as the sole base value means \"no base recipes\"\n *\n * Returns `{ base: null, post: null }` if the string is empty or invalid.\n */\nfunction parseRecipeNames(value: unknown): ParsedRecipeGroups {\n const empty: ParsedRecipeGroups = { base: null, post: null };\n\n if (typeof value !== 'string') return empty;\n const trimmed = value.trim();\n if (trimmed === '') return empty;\n\n const slashIndex = trimmed.indexOf('/');\n\n if (slashIndex === -1) {\n if (trimmed === 'none') return empty;\n const names = splitNames(trimmed);\n return { base: names, post: null };\n }\n\n const basePart = trimmed.slice(0, slashIndex);\n const postPart = trimmed.slice(slashIndex + 1);\n\n return {\n base: basePart.trim() === 'none' ? null : splitNames(basePart),\n post: splitNames(postPart),\n };\n}\n\nfunction splitNames(s: string): string[] | null {\n const names = s.split(/\\s+/).filter(Boolean);\n return names.length > 0 ? names : null;\n}\n\n/**\n * Collect merged styles for a list of recipe names.\n * Each recipe is flat-spread on top of the previous.\n */\nfunction collectRecipeStyles(\n names: string[],\n recipes: Record<string, RecipeStyles>,\n): Record<string, unknown> {\n let merged: Record<string, unknown> = {};\n\n for (const name of names) {\n const recipeStyles = recipes[name];\n\n if (!recipeStyles) {\n if (devMode) {\n console.warn(\n `[Tasty] Recipe \"${name}\" not found. ` +\n `Make sure it is defined in configure({ recipes: { ... } }).`,\n );\n }\n continue;\n }\n\n merged = { ...merged, ...(recipeStyles as Record<string, unknown>) };\n }\n\n return merged;\n}\n\n/**\n * Resolve recipe references in a flat styles object (no sub-elements).\n * Returns null if no `recipe` key is present.\n *\n * Resolution: base recipes → component styles → post recipes (all via mergeStyles)\n */\nfunction resolveRecipesForLevel(\n styles: Record<string, unknown>,\n recipes: Record<string, RecipeStyles>,\n): Record<string, unknown> | null {\n if (!('recipe' in styles)) return null;\n\n const { base, post } = parseRecipeNames(styles.recipe);\n\n // Separate selector keys (sub-elements) from flat style properties.\n // mergeStyles handles selectors with its own semantics (e.g. false = delete),\n // but at this level we only want recipe merging on flat properties.\n\n const { recipe: _recipe, ...allRest } = styles;\n const flatStyles: Record<string, unknown> = {};\n const selectorStyles: Record<string, unknown> = {};\n\n for (const key of Object.keys(allRest)) {\n if (isSelector(key)) {\n selectorStyles[key] = allRest[key];\n } else {\n flatStyles[key] = allRest[key];\n }\n }\n\n if (!base && !post) {\n return allRest;\n }\n\n // 1. Merge base recipes, then component styles on top (via mergeStyles)\n let result: Record<string, unknown>;\n\n if (base) {\n const baseStyles = collectRecipeStyles(base, recipes);\n result = mergeStyles(baseStyles as Styles, flatStyles as Styles) as Record<\n string,\n unknown\n >;\n } else {\n result = { ...flatStyles };\n }\n\n // 2. Apply post recipes via mergeStyles (state map extend semantics)\n if (post) {\n const postStyles = collectRecipeStyles(post, recipes);\n result = mergeStyles(result as Styles, postStyles as Styles) as Record<\n string,\n unknown\n >;\n }\n\n // Re-attach selector keys unchanged\n for (const key of Object.keys(selectorStyles)) {\n result[key] = selectorStyles[key];\n }\n\n return result;\n}\n\n/**\n * Resolve all `recipe` style properties in a styles object.\n *\n * Handles both top-level and sub-element recipe references.\n * Returns the same object reference if no recipes are present anywhere\n * (zero overhead for the common case).\n *\n * @param styles - The styles object potentially containing `recipe` keys\n * @returns Resolved styles with recipe values merged in, or the original object if unchanged\n */\nexport function resolveRecipes(styles: Styles): Styles {\n const recipes = getGlobalRecipes();\n\n // Fast path: no recipes configured globally\n if (!recipes) return styles;\n\n let changed = false;\n\n // Resolve top-level recipe\n const topResolved = resolveRecipesForLevel(\n styles as Record<string, unknown>,\n recipes,\n );\n\n let result: Record<string, unknown>;\n\n if (topResolved) {\n changed = true;\n result = topResolved;\n } else {\n // Keep reference; a shallow copy is deferred until a sub-element actually changes\n result = styles as Record<string, unknown>;\n }\n\n // Resolve sub-element recipes\n const keys = Object.keys(result);\n\n for (const key of keys) {\n if (!isSelector(key)) continue;\n\n const subStyles = result[key];\n\n if (\n !subStyles ||\n typeof subStyles !== 'object' ||\n Array.isArray(subStyles)\n ) {\n continue;\n }\n\n const subRecord = subStyles as Record<string, unknown>;\n\n if (!('recipe' in subRecord)) continue;\n\n const subResolved = resolveRecipesForLevel(subRecord, recipes);\n\n if (subResolved) {\n if (!changed) {\n // First change in sub-elements -- need to shallow-copy the top level\n changed = true;\n result = { ...(styles as Record<string, unknown>) };\n }\n result[key] = subResolved;\n }\n }\n\n return changed ? (result as Styles) : styles;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAwBA,MAAM,UAAU,SAAS;;;;;;;;;;;;AAkBzB,SAAS,iBAAiB,OAAoC;CAC5D,MAAM,QAA4B;EAAE,MAAM;EAAM,MAAM;CAAK;CAE3D,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,MAAM,UAAU,MAAM,KAAK;CAC3B,IAAI,YAAY,IAAI,OAAO;CAE3B,MAAM,aAAa,QAAQ,QAAQ,GAAG;CAEtC,IAAI,eAAe,IAAI;EACrB,IAAI,YAAY,QAAQ,OAAO;EAE/B,OAAO;GAAE,MADK,WAAW,OACN;GAAG,MAAM;EAAK;CACnC;CAEA,MAAM,WAAW,QAAQ,MAAM,GAAG,UAAU;CAC5C,MAAM,WAAW,QAAQ,MAAM,aAAa,CAAC;CAE7C,OAAO;EACL,MAAM,SAAS,KAAK,MAAM,SAAS,OAAO,WAAW,QAAQ;EAC7D,MAAM,WAAW,QAAQ;CAC3B;AACF;AAEA,SAAS,WAAW,GAA4B;CAC9C,MAAM,QAAQ,EAAE,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO;CAC3C,OAAO,MAAM,SAAS,IAAI,QAAQ;AACpC;;;;;AAMA,SAAS,oBACP,OACA,SACyB;CACzB,IAAI,SAAkC,CAAC;CAEvC,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,eAAe,QAAQ;EAE7B,IAAI,CAAC,cAAc;GACjB,IAAI,SACF,QAAQ,KACN,mBAAmB,KAAK,yEAE1B;GAEF;EACF;EAEA,SAAS;GAAE,GAAG;GAAQ,GAAI;EAAyC;CACrE;CAEA,OAAO;AACT;;;;;;;AAQA,SAAS,uBACP,QACA,SACgC;CAChC,IAAI,EAAE,YAAY,SAAS,OAAO;CAElC,MAAM,EAAE,MAAM,SAAS,iBAAiB,OAAO,MAAM;CAMrD,MAAM,EAAE,QAAQ,SAAS,GAAG,YAAY;CACxC,MAAM,aAAsC,CAAC;CAC7C,MAAM,iBAA0C,CAAC;CAEjD,KAAK,MAAM,OAAO,OAAO,KAAK,OAAO,GACnC,IAAI,WAAW,GAAG,GAChB,eAAe,OAAO,QAAQ;MAE9B,WAAW,OAAO,QAAQ;CAI9B,IAAI,CAAC,QAAQ,CAAC,MACZ,OAAO;CAIT,IAAI;CAEJ,IAAI,MAEF,SAAS,YADU,oBAAoB,MAAM,OACf,GAAa,UAAoB;MAK/D,SAAS,EAAE,GAAG,WAAW;CAI3B,IAAI,MAAM;EACR,MAAM,aAAa,oBAAoB,MAAM,OAAO;EACpD,SAAS,YAAY,QAAkB,UAAoB;CAI7D;CAGA,KAAK,MAAM,OAAO,OAAO,KAAK,cAAc,GAC1C,OAAO,OAAO,eAAe;CAG/B,OAAO;AACT;;;;;;;;;;;AAYA,SAAgB,eAAe,QAAwB;CACrD,MAAM,UAAU,iBAAiB;CAGjC,IAAI,CAAC,SAAS,OAAO;CAErB,IAAI,UAAU;CAGd,MAAM,cAAc,uBAClB,QACA,OACF;CAEA,IAAI;CAEJ,IAAI,aAAa;EACf,UAAU;EACV,SAAS;CACX,OAEE,SAAS;CAIX,MAAM,OAAO,OAAO,KAAK,MAAM;CAE/B,KAAK,MAAM,OAAO,MAAM;EACtB,IAAI,CAAC,WAAW,GAAG,GAAG;EAEtB,MAAM,YAAY,OAAO;EAEzB,IACE,CAAC,aACD,OAAO,cAAc,YACrB,MAAM,QAAQ,SAAS,GAEvB;EAGF,MAAM,YAAY;EAElB,IAAI,EAAE,YAAY,YAAY;EAE9B,MAAM,cAAc,uBAAuB,WAAW,OAAO;EAE7D,IAAI,aAAa;GACf,IAAI,CAAC,SAAS;IAEZ,UAAU;IACV,SAAS,EAAE,GAAI,OAAmC;GACpD;GACA,OAAO,OAAO;EAChB;CACF;CAEA,OAAO,UAAW,SAAoB;AACxC"}
@@ -1,4 +1,4 @@
1
- import { t as hydrateTastyClasses } from "../hydrate-BCPvkJj3.js";
1
+ import { t as hydrateTastyClasses } from "../hydrate-CqbxwVh_.js";
2
2
  //#region src/ssr/astro-client.ts
3
3
  /**
4
4
  * Client-side cache hydration for Astro islands.
@@ -0,0 +1,11 @@
1
+ //#region src/ssr/astro-middleware-extract-static.d.ts
2
+ /**
3
+ * Prerender-extraction middleware entrypoint for sites without islands.
4
+ * Exported only so Astro can resolve it through the package exports map.
5
+ */
6
+ declare const onRequest: (context: {
7
+ isPrerendered?: boolean;
8
+ }, next: () => Promise<Response>) => Promise<Response>;
9
+ //#endregion
10
+ export { onRequest };
11
+ //# sourceMappingURL=astro-middleware-extract-static.d.ts.map
@@ -0,0 +1,9 @@
1
+ import { n as tastyMiddleware } from "../astro-Dj8YpRd7.js";
2
+ const onRequest = tastyMiddleware({
3
+ transferCache: false,
4
+ extractionMetadata: true
5
+ });
6
+ //#endregion
7
+ export { onRequest };
8
+
9
+ //# sourceMappingURL=astro-middleware-extract-static.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"astro-middleware-extract-static.js","names":[],"sources":["../../src/ssr/astro-middleware-extract-static.ts"],"sourcesContent":["/**\n * Prerender-extraction middleware entrypoint for sites without islands.\n * Exported only so Astro can resolve it through the package exports map.\n */\n\nimport { tastyMiddleware } from './astro';\n\nconst options = {\n transferCache: false,\n extractionMetadata: true,\n};\n\nexport const onRequest = tastyMiddleware(options);\n"],"mappings":";AAYA,MAAa,YAAY,gBAAgB;CAJvC,eAAe;CACf,oBAAoB;AAGmB,CAAO"}
@@ -0,0 +1,11 @@
1
+ //#region src/ssr/astro-middleware-extract.d.ts
2
+ /**
3
+ * Prerender-extraction middleware entrypoint with island cache transfer.
4
+ * Exported only so Astro can resolve it through the package exports map.
5
+ */
6
+ declare const onRequest: (context: {
7
+ isPrerendered?: boolean;
8
+ }, next: () => Promise<Response>) => Promise<Response>;
9
+ //#endregion
10
+ export { onRequest };
11
+ //# sourceMappingURL=astro-middleware-extract.d.ts.map
@@ -0,0 +1,9 @@
1
+ import { n as tastyMiddleware } from "../astro-Dj8YpRd7.js";
2
+ const onRequest = tastyMiddleware({
3
+ transferCache: true,
4
+ extractionMetadata: true
5
+ });
6
+ //#endregion
7
+ export { onRequest };
8
+
9
+ //# sourceMappingURL=astro-middleware-extract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"astro-middleware-extract.js","names":[],"sources":["../../src/ssr/astro-middleware-extract.ts"],"sourcesContent":["/**\n * Prerender-extraction middleware entrypoint with island cache transfer.\n * Exported only so Astro can resolve it through the package exports map.\n */\n\nimport { tastyMiddleware } from './astro';\n\nconst options = {\n transferCache: true,\n extractionMetadata: true,\n};\n\nexport const onRequest = tastyMiddleware(options);\n"],"mappings":";AAYA,MAAa,YAAY,gBAAgB;CAJvC,eAAe;CACf,oBAAoB;AAGmB,CAAO"}
@@ -10,7 +10,9 @@
10
10
  * Identical to `./astro-middleware` except that no class-list `<script>` is
11
11
  * emitted, so a site without `client:*` islands ships zero client JavaScript.
12
12
  */
13
- declare const onRequest: (_context: unknown, next: () => Promise<Response>) => Promise<Response>;
13
+ declare const onRequest: (context: {
14
+ isPrerendered?: boolean;
15
+ }, next: () => Promise<Response>) => Promise<Response>;
14
16
  //#endregion
15
17
  export { onRequest };
16
18
  //# sourceMappingURL=astro-middleware-static.d.ts.map
@@ -1,4 +1,4 @@
1
- import { tastyMiddleware } from "./astro.js";
1
+ import { n as tastyMiddleware } from "../astro-Dj8YpRd7.js";
2
2
  //#region src/ssr/astro-middleware-static.ts
3
3
  /**
4
4
  * Astro middleware entrypoint for `tastyIntegration({ islands: false })`.
@@ -11,7 +11,9 @@
11
11
  * `./astro-middleware-static` for the variant used by
12
12
  * `tastyIntegration({ islands: false })`.
13
13
  */
14
- declare const onRequest: (_context: unknown, next: () => Promise<Response>) => Promise<Response>;
14
+ declare const onRequest: (context: {
15
+ isPrerendered?: boolean;
16
+ }, next: () => Promise<Response>) => Promise<Response>;
15
17
  //#endregion
16
18
  export { onRequest };
17
19
  //# sourceMappingURL=astro-middleware.d.ts.map
@@ -1,4 +1,4 @@
1
- import { tastyMiddleware } from "./astro.js";
1
+ import { n as tastyMiddleware } from "../astro-Dj8YpRd7.js";
2
2
  //#region src/ssr/astro-middleware.ts
3
3
  /**
4
4
  * Astro middleware entrypoint for `tastyIntegration()`.
@@ -43,7 +43,19 @@ interface TastyMiddlewareOptions {
43
43
  * );
44
44
  * ```
45
45
  */
46
- declare function tastyMiddleware(options?: TastyMiddlewareOptions): (_context: unknown, next: () => Promise<Response>) => Promise<Response>;
46
+ declare function tastyMiddleware(options?: TastyMiddlewareOptions): (context: {
47
+ isPrerendered?: boolean;
48
+ }, next: () => Promise<Response>) => Promise<Response>;
49
+ interface TastyIntegrationCSSOptions {
50
+ /**
51
+ * CSS delivery mode. Extraction only applies to prerendered builds.
52
+ * Extracted CSS preserves resource URLs verbatim, so use absolute URLs or
53
+ * data URLs. Root-relative URLs are also supported unless `assetsPrefix`
54
+ * sends CSS to an external origin. The build rejects resource URLs whose
55
+ * targets would change after extraction.
56
+ */
57
+ mode?: 'inline' | 'extract';
58
+ }
47
59
  interface TastyIntegrationOptions {
48
60
  /**
49
61
  * Enable island hydration support.
@@ -57,6 +69,8 @@ interface TastyIntegrationOptions {
57
69
  * directives.
58
70
  */
59
71
  islands?: boolean;
72
+ /** Configure inline or build-wide extracted CSS delivery. */
73
+ css?: TastyIntegrationCSSOptions;
60
74
  }
61
75
  /**
62
76
  * Astro integration that automatically sets up Tasty SSR.
@@ -86,8 +100,36 @@ interface TastyIntegrationOptions {
86
100
  */
87
101
  declare function tastyIntegration(options?: TastyIntegrationOptions): {
88
102
  name: string;
89
- hooks: Record<string, (...args: never[]) => void>;
103
+ hooks: {
104
+ 'astro:config:setup': ({
105
+ addMiddleware,
106
+ injectScript
107
+ }: {
108
+ addMiddleware: (middleware: {
109
+ entrypoint: string | URL;
110
+ order: "pre" | "post";
111
+ }) => void;
112
+ injectScript: (stage: "head-inline" | "before-hydration" | "page" | "page-ssr", content: string) => void;
113
+ }) => void;
114
+ 'astro:config:done': ({
115
+ config
116
+ }: {
117
+ config: {
118
+ base?: string;
119
+ site?: URL;
120
+ build?: {
121
+ assets?: string;
122
+ assetsPrefix?: string | Record<string, string>;
123
+ };
124
+ };
125
+ }) => void;
126
+ 'astro:build:done': ({
127
+ dir
128
+ }: {
129
+ dir: URL;
130
+ }) => Promise<void>;
131
+ };
90
132
  };
91
133
  //#endregion
92
- export { TastyIntegrationOptions, TastyMiddlewareOptions, tastyIntegration, tastyMiddleware };
134
+ export { TastyIntegrationCSSOptions, TastyIntegrationOptions, TastyMiddlewareOptions, tastyIntegration, tastyMiddleware };
93
135
  //# sourceMappingURL=astro.d.ts.map