@tenphi/tasty 0.0.0-snapshot.27b6708 → 0.0.0-snapshot.28eb83c

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 (106) hide show
  1. package/README.md +38 -54
  2. package/dist/{babel-BUQGeOXA.d.ts → babel-D6lOuSwk.d.ts} +2 -2
  3. package/dist/chunks/async-storage-DKK-wTD4.js.map +1 -0
  4. package/dist/chunks/build-config-BBThSdlo.js +45 -0
  5. package/dist/chunks/build-config-BBThSdlo.js.map +1 -0
  6. package/dist/{collector-DTahQUiV.js → chunks/collector-DcViW2ZQ.js} +28 -14
  7. package/dist/chunks/collector-DcViW2ZQ.js.map +1 -0
  8. package/dist/chunks/config-engine-DQVQK4NU.js +403 -0
  9. package/dist/chunks/config-engine-DQVQK4NU.js.map +1 -0
  10. package/dist/chunks/css-definitions-BZ9vm0ci.js +1284 -0
  11. package/dist/chunks/css-definitions-BZ9vm0ci.js.map +1 -0
  12. package/dist/chunks/css-resources-Cyl_axbI.js +149 -0
  13. package/dist/chunks/css-resources-Cyl_axbI.js.map +1 -0
  14. package/dist/chunks/debug-Vyauml7U.js +583 -0
  15. package/dist/chunks/debug-Vyauml7U.js.map +1 -0
  16. package/dist/chunks/dsl-CXvoaLnj.js +2097 -0
  17. package/dist/chunks/dsl-CXvoaLnj.js.map +1 -0
  18. package/dist/chunks/hydration-CLdVKcH2.js +59 -0
  19. package/dist/chunks/hydration-CLdVKcH2.js.map +1 -0
  20. package/dist/chunks/react-runtime-so_X_yMo.js +1526 -0
  21. package/dist/chunks/react-runtime-so_X_yMo.js.map +1 -0
  22. package/dist/chunks/runtime-engine-DQ5laRou.js +3056 -0
  23. package/dist/chunks/runtime-engine-DQ5laRou.js.map +1 -0
  24. package/dist/{merge-styles-oklji0KB.js → chunks/shared-utils-OIg0N_dp.js} +42 -3
  25. package/dist/chunks/shared-utils-OIg0N_dp.js.map +1 -0
  26. package/dist/{config-B5kHzuNz.js → chunks/style-engine-CBuOt1e4.js} +2387 -7442
  27. package/dist/chunks/style-engine-CBuOt1e4.js.map +1 -0
  28. package/dist/{css-writer-B-J87ncv.js → chunks/zero-engine-BFh7gKbK.js} +3 -3
  29. package/dist/chunks/zero-engine-BFh7gKbK.js.map +1 -0
  30. package/dist/{collector-DUaHCcTS.d.ts → collector-CAmndLXe.d.ts} +23 -3
  31. package/dist/{config-YsxGv4tq.d.ts → config-BWYrv_Aa.d.ts} +141 -37
  32. package/dist/core/index.d.ts +5 -5
  33. package/dist/core/index.js +9 -6
  34. package/dist/{index-Cd45t5NM.d.ts → index-BzAC3p06.d.ts} +118 -23
  35. package/dist/{index-PqN-DIpn.d.ts → index-D4kRLj2o.d.ts} +128 -68
  36. package/dist/index.d.ts +5 -5
  37. package/dist/index.js +10 -922
  38. package/dist/{merge-styles-CU7JbEwg.d.ts → merge-styles-BFktNP8J.d.ts} +2 -2
  39. package/dist/ssr/astro-client.js +1 -1
  40. package/dist/ssr/astro-middleware-extract-static.d.ts +11 -0
  41. package/dist/ssr/astro-middleware-extract-static.js +9 -0
  42. package/dist/ssr/astro-middleware-extract-static.js.map +1 -0
  43. package/dist/ssr/astro-middleware-extract.d.ts +11 -0
  44. package/dist/ssr/astro-middleware-extract.js +9 -0
  45. package/dist/ssr/astro-middleware-extract.js.map +1 -0
  46. package/dist/ssr/astro-middleware-static.d.ts +3 -1
  47. package/dist/ssr/astro-middleware.d.ts +3 -1
  48. package/dist/ssr/astro.d.ts +45 -3
  49. package/dist/ssr/astro.js +157 -14
  50. package/dist/ssr/astro.js.map +1 -1
  51. package/dist/ssr/index.d.ts +7 -7
  52. package/dist/ssr/index.js +4 -4
  53. package/dist/ssr/index.js.map +1 -1
  54. package/dist/ssr/next-config.d.ts +66 -0
  55. package/dist/ssr/next-config.js +135 -0
  56. package/dist/ssr/next-config.js.map +1 -0
  57. package/dist/ssr/next.d.ts +9 -2
  58. package/dist/ssr/next.js +26 -10
  59. package/dist/ssr/next.js.map +1 -1
  60. package/dist/static/index.d.ts +2 -2
  61. package/dist/static/index.js +1 -1
  62. package/dist/zero/babel.d.ts +1 -1
  63. package/dist/zero/babel.js +25 -24
  64. package/dist/zero/babel.js.map +1 -1
  65. package/dist/zero/index.d.ts +1 -1
  66. package/dist/zero/index.js +1 -1
  67. package/dist/zero/next.d.ts +1 -1
  68. package/docs/README.md +5 -3
  69. package/docs/adoption.md +3 -3
  70. package/docs/ai-agents.md +83 -78
  71. package/docs/comparison.md +12 -12
  72. package/docs/configuration.md +47 -47
  73. package/docs/debug.md +19 -7
  74. package/docs/dsl.md +3 -3
  75. package/docs/getting-started.md +10 -10
  76. package/docs/injector.md +62 -25
  77. package/docs/methodology.md +3 -3
  78. package/docs/migration-v3.md +49 -49
  79. package/docs/plugins.md +37 -33
  80. package/docs/react-api.md +2 -2
  81. package/docs/runtime-benchmarks.md +351 -0
  82. package/docs/ssr.md +219 -61
  83. package/docs/styles.md +43 -11
  84. package/docs/tasty-static.md +136 -103
  85. package/package.json +80 -11
  86. package/dist/async-storage-DKK-wTD4.js.map +0 -1
  87. package/dist/collector-DTahQUiV.js.map +0 -1
  88. package/dist/config-B5kHzuNz.js.map +0 -1
  89. package/dist/context-CA8YKeMn.js +0 -24
  90. package/dist/context-CA8YKeMn.js.map +0 -1
  91. package/dist/core-Dr4u1NVD.js +0 -1566
  92. package/dist/core-Dr4u1NVD.js.map +0 -1
  93. package/dist/css-writer-B-J87ncv.js.map +0 -1
  94. package/dist/format-global-rules-DklyaXv-.js +0 -22
  95. package/dist/format-global-rules-DklyaXv-.js.map +0 -1
  96. package/dist/format-rules-DKOA-6qu.js +0 -130
  97. package/dist/format-rules-DKOA-6qu.js.map +0 -1
  98. package/dist/hydrate-OeMX99We.js +0 -37
  99. package/dist/hydrate-OeMX99We.js.map +0 -1
  100. package/dist/index.js.map +0 -1
  101. package/dist/keyframes-CV8azJf3.js +0 -493
  102. package/dist/keyframes-CV8azJf3.js.map +0 -1
  103. package/dist/merge-styles-oklji0KB.js.map +0 -1
  104. package/dist/resolve-recipes-DTG81rzl.js +0 -144
  105. package/dist/resolve-recipes-DTG81rzl.js.map +0 -1
  106. /package/dist/{async-storage-DKK-wTD4.js → chunks/async-storage-DKK-wTD4.js} +0 -0
@@ -0,0 +1,583 @@
1
+ import { j as tastyClassRegex } from "./css-definitions-BZ9vm0ci.js";
2
+ import { j as CHUNK_NAMES } from "./style-engine-CBuOt1e4.js";
3
+ import { S as injector, V as getNamePrefix, X as flushStyles, g as getCSSTextForNode } from "./runtime-engine-DQ5laRou.js";
4
+ //#region src/debug.ts
5
+ function fmtSize(bytes) {
6
+ return bytes > 1024 ? `${(bytes / 1024).toFixed(1)}KB` : `${bytes}B`;
7
+ }
8
+ function countRules(css) {
9
+ return (css.match(/\{[^}]*\}/g) || []).length;
10
+ }
11
+ function sortTastyClasses(classes) {
12
+ return Array.from(classes).sort((a, b) => a.localeCompare(b));
13
+ }
14
+ /**
15
+ * The root these helpers read, or `null` where there is no DOM.
16
+ *
17
+ * `document` used to be a default parameter value, and a default is evaluated
18
+ * at the call site — so every read below threw a bare `ReferenceError` under
19
+ * Node, taking out five of the eight public methods. A debug utility must not
20
+ * be able to fail an SSR render because a call was left in, so the DOM-less
21
+ * case reports an empty result and says why.
22
+ */
23
+ function defaultRoot() {
24
+ return typeof document === "undefined" ? null : document;
25
+ }
26
+ let warnedNoDom = false;
27
+ /** Say once why the numbers are empty. Silent under `{ raw: true }`. */
28
+ function warnNoDom(raw) {
29
+ if (raw || warnedNoDom) return;
30
+ warnedNoDom = true;
31
+ console.warn("[Tasty] tastyDebug reads the DOM and this environment has none, so the result is empty. During SSR, read the ServerStyleCollector instead.");
32
+ }
33
+ /**
34
+ * The registry for `root`, with every queued write landed first.
35
+ *
36
+ * Every injector read API is a flush point, and the reads below reach past
37
+ * those APIs straight into the registry and the sheet manager. Without this
38
+ * they would report a batch window's contents as absent — a rule that is
39
+ * enqueued but not yet in a sheet is missing from `globalRules`, from the
40
+ * sheets, and from anything counting either.
41
+ */
42
+ function getRegistry(root = defaultRoot()) {
43
+ if (!root) return void 0;
44
+ flushStyles();
45
+ return injector.instance._sheetManager?.getRegistry(root);
46
+ }
47
+ function findDomTastyClasses(root = defaultRoot()) {
48
+ if (!root) return [];
49
+ const classes = /* @__PURE__ */ new Set();
50
+ const elements = root.querySelectorAll?.("[class]") || [];
51
+ const classRegex = tastyClassRegex(getNamePrefix());
52
+ elements.forEach((el) => {
53
+ const attr = el.getAttribute("class");
54
+ if (attr) {
55
+ for (const cls of attr.split(/\s+/)) if (classRegex.test(cls)) classes.add(cls);
56
+ }
57
+ });
58
+ return sortTastyClasses(classes);
59
+ }
60
+ /**
61
+ * Everything this injector holds in `root`, in the order the engine applies it,
62
+ * with the sources kept byte-for-byte — trimming would report a total smaller
63
+ * than one of its own parts whenever raw CSS has edge whitespace.
64
+ */
65
+ function getAllCSS(root = defaultRoot()) {
66
+ const registry = getRegistry(root);
67
+ const sheetManager = injector.instance._sheetManager;
68
+ if (!root || !registry || !sheetManager) return "";
69
+ return sheetManager.getOwnedCSSInOrder(registry, root).join("\n");
70
+ }
71
+ /**
72
+ * The injector's own readers fall back to `document` when `root` is omitted, so
73
+ * they have to be reached with a real root or not at all.
74
+ */
75
+ function cssTextForClasses(classNames, root) {
76
+ if (!root) return "";
77
+ return injector.instance.getCSSTextForClasses(classNames, { root });
78
+ }
79
+ function getInjectorMetrics(root) {
80
+ if (!root) return null;
81
+ return injector.instance.getMetrics({ root });
82
+ }
83
+ /**
84
+ * Injected classes that no element carries and nobody pinned — the exact set
85
+ * `gc({ force: true })` would delete.
86
+ *
87
+ * Deliberately borrowed from the injector rather than recomputed here: the two
88
+ * drifted apart once before, when this file still read "unused" off the pin
89
+ * counts the render path had stopped maintaining.
90
+ */
91
+ function getUnusedClasses(root = defaultRoot()) {
92
+ if (!root) return [];
93
+ return sortTastyClasses(injector.instance.getUnusedClasses({ root }));
94
+ }
95
+ /** Every class this injector holds CSS for in `root`. */
96
+ function getOwnedClasses(root = defaultRoot()) {
97
+ const registry = getRegistry(root);
98
+ if (!registry) return [];
99
+ const owned = [];
100
+ for (const [className, info] of registry.rules) if (info.sheetIndex >= 0) owned.push(className);
101
+ return sortTastyClasses(owned);
102
+ }
103
+ function prettifyCSS(css) {
104
+ if (!css || !css.trim()) return "";
105
+ const out = [];
106
+ let depth = 0;
107
+ const indent = () => " ".repeat(depth);
108
+ let normalized = css.replace(/\s+/g, " ").trim();
109
+ normalized = normalized.replace(/\s*\{\s*/g, " { ");
110
+ normalized = normalized.replace(/\s*\}\s*/g, " } ");
111
+ normalized = normalized.replace(/;\s*/g, "; ");
112
+ const tokens = normalized.split(/\s+/);
113
+ let buf = "";
114
+ for (const t of tokens) if (t === "{") {
115
+ const header = buf.trim();
116
+ if (header) {
117
+ const parts = splitOutsideParens(header, ",");
118
+ if (parts.length > 1) out.push(parts.map((p, idx) => idx === 0 ? `${indent()}${p.trim()},` : `${indent()}${p.trim()}${idx < parts.length - 1 ? "," : ""}`).join("\n") + " {");
119
+ else out.push(`${indent()}${header} {`);
120
+ } else out.push(`${indent()}{`);
121
+ depth++;
122
+ buf = "";
123
+ } else if (t === "}") {
124
+ if (buf.trim()) {
125
+ for (const decl of buf.split(";").filter((s) => s.trim())) out.push(`${indent()}${decl.trim()};`);
126
+ buf = "";
127
+ }
128
+ depth = Math.max(0, depth - 1);
129
+ out.push(`${indent()}}`);
130
+ } else if (t.endsWith(";")) {
131
+ buf += ` ${t}`;
132
+ const full = buf.trim();
133
+ if (full) out.push(`${indent()}${full}`);
134
+ buf = "";
135
+ } else buf += ` ${t}`;
136
+ if (buf.trim()) out.push(buf.trim());
137
+ return out.filter((l) => l.trim()).join("\n").replace(/\n{3,}/g, "\n\n").trim();
138
+ }
139
+ /** Split `str` by `sep` only when not inside parentheses */
140
+ function splitOutsideParens(str, sep) {
141
+ const parts = [];
142
+ let depth = 0;
143
+ let start = 0;
144
+ for (let i = 0; i < str.length; i++) {
145
+ const ch = str[i];
146
+ if (ch === "(") depth++;
147
+ else if (ch === ")") depth--;
148
+ else if (depth === 0 && str.startsWith(sep, i)) {
149
+ parts.push(str.slice(start, i));
150
+ start = i + sep.length;
151
+ }
152
+ }
153
+ parts.push(str.slice(start));
154
+ return parts;
155
+ }
156
+ function extractChunkName(cacheKey) {
157
+ for (const part of cacheKey.split("\0")) {
158
+ if (part.startsWith("[states:")) continue;
159
+ if (!part.includes(":") && part.length > 0) return part;
160
+ }
161
+ return null;
162
+ }
163
+ function getChunkForClass(className, root = defaultRoot()) {
164
+ const registry = getRegistry(root);
165
+ if (!registry) return null;
166
+ for (const [key, cn] of registry.cacheKeyToClassName) if (cn === className) return extractChunkName(key);
167
+ return null;
168
+ }
169
+ function buildChunkBreakdown(root = defaultRoot()) {
170
+ const registry = getRegistry(root);
171
+ if (!root || !registry) return {
172
+ byChunk: {},
173
+ totalChunkTypes: 0,
174
+ totalClasses: 0
175
+ };
176
+ const byChunk = {};
177
+ for (const [cacheKey, className] of registry.cacheKeyToClassName) {
178
+ const chunk = extractChunkName(cacheKey) || "unknown";
179
+ if (!byChunk[chunk]) byChunk[chunk] = {
180
+ classes: [],
181
+ cssSize: 0,
182
+ ruleCount: 0
183
+ };
184
+ byChunk[chunk].classes.push(className);
185
+ const css = injector.instance.getCSSTextForClasses([className], { root });
186
+ byChunk[chunk].cssSize += css.length;
187
+ byChunk[chunk].ruleCount += countRules(css);
188
+ }
189
+ for (const entry of Object.values(byChunk)) entry.classes = sortTastyClasses(entry.classes);
190
+ const totalClasses = Object.values(byChunk).reduce((s, e) => s + e.classes.length, 0);
191
+ return {
192
+ byChunk,
193
+ totalChunkTypes: Object.keys(byChunk).length,
194
+ totalClasses
195
+ };
196
+ }
197
+ /**
198
+ * Every prefix `registry.globalRules` is keyed by. Anything missing here is a
199
+ * rule the summary would hold but never count, which is how the totals stopped
200
+ * adding up the first time.
201
+ */
202
+ const GLOBAL_RULE_PREFIXES = {
203
+ global: "global:",
204
+ property: "property:",
205
+ fontFace: "fontface:",
206
+ counterStyle: "counterstyle:",
207
+ function: "function:"
208
+ };
209
+ function getGlobalTypeCSS(type, root = defaultRoot()) {
210
+ const registry = getRegistry(root);
211
+ if (!root || !registry) return {
212
+ css: "",
213
+ ruleCount: 0,
214
+ size: 0
215
+ };
216
+ const chunks = [];
217
+ let rc = 0;
218
+ if (type === "raw") {
219
+ const css = injector.instance.getRawCSSText({ root });
220
+ const sheetManager = injector.instance._sheetManager;
221
+ return {
222
+ css: prettifyCSS(css),
223
+ ruleCount: sheetManager?.getRawRuleCount(root) ?? 0,
224
+ size: css.length
225
+ };
226
+ }
227
+ if (type === "keyframes") for (const [, entry] of registry.keyframesCache) {
228
+ const info = entry.info;
229
+ const sheetInfo = registry.sheets[info.sheetIndex];
230
+ const sm = injector.instance._sheetManager;
231
+ const ss = sheetInfo && sm ? sm.getCSSSheet(sheetInfo) : null;
232
+ if (ss && info.ruleIndex < ss.cssRules.length) {
233
+ const rule = ss.cssRules[info.ruleIndex];
234
+ if (rule) {
235
+ chunks.push(rule.cssText);
236
+ rc++;
237
+ }
238
+ } else if (info.cssText) {
239
+ chunks.push(info.cssText);
240
+ rc++;
241
+ }
242
+ }
243
+ else {
244
+ const prefix = GLOBAL_RULE_PREFIXES[type];
245
+ for (const [key, ri] of registry.globalRules) {
246
+ if (!key.startsWith(prefix)) continue;
247
+ const sheetInfo = registry.sheets[ri.sheetIndex];
248
+ const sm = injector.instance._sheetManager;
249
+ const ss = sheetInfo && sm ? sm.getCSSSheet(sheetInfo) : null;
250
+ if (ss) {
251
+ const start = Math.max(0, ri.ruleIndex);
252
+ const end = Math.min(ss.cssRules.length - 1, ri.endRuleIndex ?? ri.ruleIndex);
253
+ if (start >= 0 && end >= start && start < ss.cssRules.length) for (let i = start; i <= end; i++) {
254
+ const rule = ss.cssRules[i];
255
+ if (rule) {
256
+ chunks.push(rule.cssText);
257
+ rc++;
258
+ }
259
+ }
260
+ } else if (ri.cssText?.length) {
261
+ chunks.push(...ri.cssText);
262
+ rc += ri.cssText.length;
263
+ }
264
+ }
265
+ }
266
+ const raw = chunks.join("\n");
267
+ return {
268
+ css: prettifyCSS(raw),
269
+ ruleCount: rc,
270
+ size: raw.length
271
+ };
272
+ }
273
+ function getSourceCssForClasses(classNames, root = defaultRoot()) {
274
+ const registry = getRegistry(root);
275
+ if (!registry) return null;
276
+ const chunks = [];
277
+ let found = false;
278
+ for (const cls of classNames) {
279
+ const info = registry.rules.get(cls);
280
+ if (info?.cssText?.length) {
281
+ chunks.push(...info.cssText);
282
+ found = true;
283
+ }
284
+ }
285
+ return found ? chunks.join("\n") : null;
286
+ }
287
+ function getDefs(root = defaultRoot()) {
288
+ const registry = getRegistry(root);
289
+ let properties = [];
290
+ if (registry?.injectedProperties) properties = Array.from(registry.injectedProperties.keys()).sort();
291
+ const keyframes = [];
292
+ if (registry) {
293
+ for (const entry of registry.keyframesCache.values()) keyframes.push({
294
+ name: entry.name,
295
+ refCount: entry.refCount
296
+ });
297
+ keyframes.sort((a, b) => a.name.localeCompare(b.name));
298
+ }
299
+ return {
300
+ properties,
301
+ keyframes
302
+ };
303
+ }
304
+ const CHUNK_ORDER = [
305
+ CHUNK_NAMES.COMBINED,
306
+ CHUNK_NAMES.APPEARANCE,
307
+ CHUNK_NAMES.FONT,
308
+ CHUNK_NAMES.DIMENSION,
309
+ CHUNK_NAMES.DISPLAY,
310
+ CHUNK_NAMES.LAYOUT,
311
+ CHUNK_NAMES.POSITION,
312
+ CHUNK_NAMES.MISC,
313
+ CHUNK_NAMES.SUBCOMPONENTS
314
+ ];
315
+ const tastyDebug = {
316
+ css(target, opts) {
317
+ const { root = defaultRoot(), prettify = true, raw = false, source = false } = opts || {};
318
+ if (!root) {
319
+ warnNoDom(raw);
320
+ return "";
321
+ }
322
+ let css = "";
323
+ const classRegex = tastyClassRegex(getNamePrefix());
324
+ if (source && typeof target === "string" && classRegex.test(target)) {
325
+ const src = getSourceCssForClasses([target], root);
326
+ if (src) css = src;
327
+ else {
328
+ if (!raw) console.warn("[Tasty] source CSS not available (requires dev mode or TASTY_DEBUG=true). Falling back to live CSSOM.");
329
+ css = injector.instance.getCSSTextForClasses([target], { root });
330
+ }
331
+ } else if (source && Array.isArray(target)) {
332
+ const src = getSourceCssForClasses(target, root);
333
+ if (src) css = src;
334
+ else {
335
+ if (!raw) console.warn("[Tasty] source CSS not available. Falling back to live CSSOM.");
336
+ css = injector.instance.getCSSTextForClasses(target, { root });
337
+ }
338
+ } else if (typeof target === "string") if (target === "all") css = getAllCSS(root);
339
+ else if (target === "global") {
340
+ css = getGlobalTypeCSS("global", root).css;
341
+ return css;
342
+ } else if (target === "active") {
343
+ const active = findDomTastyClasses(root);
344
+ css = injector.instance.getCSSTextForClasses(active, { root });
345
+ } else if (target === "unused") {
346
+ const unused = getUnusedClasses(root);
347
+ css = injector.instance.getCSSTextForClasses(unused, { root });
348
+ } else if (target === "page") css = getPageCSS(root);
349
+ else if (classRegex.test(target)) css = injector.instance.getCSSTextForClasses([target], { root });
350
+ else {
351
+ const el = root.querySelector?.(target);
352
+ if (el) css = getCSSTextForNode(el, { root });
353
+ }
354
+ else if (Array.isArray(target)) css = injector.instance.getCSSTextForClasses(target, { root });
355
+ else if (target instanceof Element) css = getCSSTextForNode(target, { root });
356
+ const result = prettify ? prettifyCSS(css) : css;
357
+ if (!raw) {
358
+ const label = Array.isArray(target) ? `[${target.join(", ")}]` : target;
359
+ const rc = countRules(css);
360
+ console.group(`CSS for ${label} (${rc} rules, ${fmtSize(css.length)})`);
361
+ console.log(result || "(empty)");
362
+ console.groupEnd();
363
+ }
364
+ return result;
365
+ },
366
+ inspect(target, opts) {
367
+ const { root = defaultRoot(), raw = false } = opts || {};
368
+ const element = !root ? null : typeof target === "string" ? root.querySelector?.(target) : target;
369
+ if (!root) warnNoDom(raw);
370
+ if (!element) {
371
+ const empty = {
372
+ element: null,
373
+ classes: [],
374
+ chunks: [],
375
+ css: "",
376
+ size: 0,
377
+ rules: 0
378
+ };
379
+ if (!raw && root) console.warn("[Tasty] debug.inspect: element not found");
380
+ return empty;
381
+ }
382
+ const classList = element.getAttribute("class") || "";
383
+ const classRegex = tastyClassRegex(getNamePrefix());
384
+ const tastyClasses = classList.split(/\s+/).filter((cls) => classRegex.test(cls));
385
+ const chunks = tastyClasses.map((className) => ({
386
+ className,
387
+ chunkName: getChunkForClass(className, root)
388
+ }));
389
+ const css = getCSSTextForNode(element, { root: root ?? void 0 });
390
+ const rules = countRules(css);
391
+ const result = {
392
+ element,
393
+ classes: tastyClasses,
394
+ chunks,
395
+ css: prettifyCSS(css),
396
+ size: css.length,
397
+ rules
398
+ };
399
+ if (!raw) {
400
+ const tag = element.tagName.toLowerCase();
401
+ const id = element.id ? `#${element.id}` : "";
402
+ console.group(`inspect ${tag}${id} — ${tastyClasses.length} classes, ${rules} rules, ${fmtSize(css.length)}`);
403
+ if (chunks.length) console.log("Chunks:", chunks.map((c) => `${c.className}→${c.chunkName || "?"}`).join(", "));
404
+ console.groupCollapsed("CSS");
405
+ console.log(result.css || "(empty)");
406
+ console.groupEnd();
407
+ console.groupEnd();
408
+ }
409
+ return result;
410
+ },
411
+ summary(opts) {
412
+ const { root = defaultRoot(), raw = false } = opts || {};
413
+ if (!root) warnNoDom(raw);
414
+ const activeClasses = findDomTastyClasses(root);
415
+ const unusedClasses = getUnusedClasses(root);
416
+ const ownedClasses = getOwnedClasses(root);
417
+ const totalStyledClasses = sortTastyClasses(new Set([...activeClasses, ...ownedClasses]));
418
+ const unusedSet = new Set(unusedClasses);
419
+ const activeSet = new Set(activeClasses);
420
+ const hotClasses = ownedClasses.filter((className) => !activeSet.has(className) && !unusedSet.has(className));
421
+ const hotCSS = cssTextForClasses(hotClasses, root);
422
+ const activeCSS = cssTextForClasses(activeClasses, root);
423
+ const unusedCSS = cssTextForClasses(unusedClasses, root);
424
+ const allCSS = getAllCSS(root);
425
+ const activeRuleCount = countRules(activeCSS);
426
+ const unusedRuleCount = countRules(unusedCSS);
427
+ const globalData = getGlobalTypeCSS("global", root);
428
+ const rawData = getGlobalTypeCSS("raw", root);
429
+ const kfData = getGlobalTypeCSS("keyframes", root);
430
+ const propData = getGlobalTypeCSS("property", root);
431
+ const atRuleData = [
432
+ "fontFace",
433
+ "counterStyle",
434
+ "function"
435
+ ].reduce((all, type) => {
436
+ const data = getGlobalTypeCSS(type, root);
437
+ return {
438
+ css: data.css ? `${all.css}\n${data.css}`.trim() : all.css,
439
+ ruleCount: all.ruleCount + data.ruleCount,
440
+ size: all.size + data.size
441
+ };
442
+ }, {
443
+ css: "",
444
+ ruleCount: 0,
445
+ size: 0
446
+ });
447
+ const totalRuleCount = activeRuleCount + unusedRuleCount + countRules(hotCSS) + globalData.ruleCount + atRuleData.ruleCount + rawData.ruleCount + kfData.ruleCount + propData.ruleCount;
448
+ const metrics = getInjectorMetrics(root);
449
+ const defs = getDefs(root);
450
+ const chunkBreakdown = buildChunkBreakdown(root);
451
+ const summary = {
452
+ activeClasses,
453
+ unusedClasses,
454
+ hotClasses,
455
+ totalStyledClasses,
456
+ activeCSSSize: activeCSS.length,
457
+ unusedCSSSize: unusedCSS.length,
458
+ globalCSSSize: globalData.size + atRuleData.size,
459
+ rawCSSSize: rawData.size,
460
+ keyframesCSSSize: kfData.size,
461
+ propertyCSSSize: propData.size,
462
+ totalCSSSize: allCSS.length,
463
+ activeRuleCount,
464
+ unusedRuleCount,
465
+ globalRuleCount: globalData.ruleCount + atRuleData.ruleCount,
466
+ rawRuleCount: rawData.ruleCount,
467
+ keyframesRuleCount: kfData.ruleCount,
468
+ propertyRuleCount: propData.ruleCount,
469
+ totalRuleCount,
470
+ metrics,
471
+ definedProperties: defs.properties,
472
+ definedKeyframes: defs.keyframes,
473
+ chunkBreakdown
474
+ };
475
+ if (!raw) {
476
+ console.group("Tasty Summary");
477
+ console.log(`Active: ${activeClasses.length} classes, ${activeRuleCount} rules, ${fmtSize(activeCSS.length)}`);
478
+ console.log(`Unused: ${unusedClasses.length} classes, ${unusedRuleCount} rules, ${fmtSize(unusedCSS.length)}`);
479
+ if (hotClasses.length) console.log(`Held: ${hotClasses.length} classes, ${countRules(hotCSS)} rules, ${fmtSize(hotCSS.length)} (not rendered, not yet collectable)`);
480
+ console.log(`Global: ${globalData.ruleCount + atRuleData.ruleCount} rules, ${fmtSize(globalData.size + atRuleData.size)}`);
481
+ if (rawData.ruleCount) console.log(`Raw: ${rawData.ruleCount} rules, ${fmtSize(rawData.size)}`);
482
+ if (kfData.ruleCount) console.log(`Keyframes: ${kfData.ruleCount} rules, ${fmtSize(kfData.size)}`);
483
+ if (propData.ruleCount) console.log(`@property: ${propData.ruleCount} rules, ${fmtSize(propData.size)}`);
484
+ console.log(`Total: ${totalStyledClasses.length} classes, ${totalRuleCount} rules, ${fmtSize(allCSS.length)}`);
485
+ if (metrics) {
486
+ const total = metrics.hits + metrics.misses;
487
+ const rate = total > 0 ? (metrics.hits / total * 100).toFixed(1) : 0;
488
+ console.log(`Cache: ${rate}% hit rate (${total} lookups)`);
489
+ }
490
+ if (chunkBreakdown.totalChunkTypes > 0) {
491
+ console.groupCollapsed(`Chunks (${chunkBreakdown.totalChunkTypes} types, ${chunkBreakdown.totalClasses} classes)`);
492
+ for (const name of CHUNK_ORDER) {
493
+ const d = chunkBreakdown.byChunk[name];
494
+ if (d) console.log(` ${name}: ${d.classes.length} cls, ${d.ruleCount} rules, ${fmtSize(d.cssSize)}`);
495
+ }
496
+ for (const [name, d] of Object.entries(chunkBreakdown.byChunk)) if (!CHUNK_ORDER.includes(name)) console.log(` ${name}: ${d.classes.length} cls, ${d.ruleCount} rules, ${fmtSize(d.cssSize)}`);
497
+ console.groupEnd();
498
+ }
499
+ if (defs.properties.length || defs.keyframes.length) console.log(`Defs: ${defs.properties.length} @property, ${defs.keyframes.length} @keyframes`);
500
+ console.groupEnd();
501
+ }
502
+ return summary;
503
+ },
504
+ chunks(opts) {
505
+ const { root = defaultRoot(), raw = false } = opts || {};
506
+ if (!root) warnNoDom(raw);
507
+ const breakdown = buildChunkBreakdown(root);
508
+ if (!raw) {
509
+ console.group(`Chunks (${breakdown.totalChunkTypes} types, ${breakdown.totalClasses} classes)`);
510
+ for (const name of CHUNK_ORDER) {
511
+ const d = breakdown.byChunk[name];
512
+ if (d) console.log(` ${name}: ${d.classes.length} cls, ${d.ruleCount} rules, ${fmtSize(d.cssSize)}`);
513
+ }
514
+ for (const [name, d] of Object.entries(breakdown.byChunk)) if (!CHUNK_ORDER.includes(name)) console.log(` ${name}: ${d.classes.length} cls, ${d.ruleCount} rules, ${fmtSize(d.cssSize)}`);
515
+ console.groupEnd();
516
+ }
517
+ return breakdown;
518
+ },
519
+ cache(opts) {
520
+ const { root = defaultRoot(), raw = false } = opts || {};
521
+ if (!root) warnNoDom(raw);
522
+ const active = findDomTastyClasses(root);
523
+ const unused = getUnusedClasses(root);
524
+ const metrics = getInjectorMetrics(root);
525
+ const status = {
526
+ classes: {
527
+ active,
528
+ unused,
529
+ all: sortTastyClasses(new Set([...active, ...getOwnedClasses(root)]))
530
+ },
531
+ metrics
532
+ };
533
+ if (!raw) {
534
+ console.group("Cache");
535
+ console.log(`Active: ${active.length}, Unused: ${unused.length}`);
536
+ if (metrics) {
537
+ const total = metrics.hits + metrics.misses;
538
+ const rate = total > 0 ? (metrics.hits / total * 100).toFixed(1) : 0;
539
+ console.log(`Hits: ${metrics.hits}, Misses: ${metrics.misses}, Rate: ${rate}%`);
540
+ }
541
+ console.groupEnd();
542
+ }
543
+ return status;
544
+ },
545
+ cleanup(opts) {
546
+ const root = opts?.root ?? defaultRoot();
547
+ if (!root) return;
548
+ injector.instance.cleanup(root);
549
+ },
550
+ help() {
551
+ console.log(`tastyDebug API:
552
+ .summary() — overview (classes, rules, sizes)
553
+ .css("active") — CSS for classes in DOM
554
+ .css("t42") — CSS for a specific class
555
+ .css("t42",{source:1})— original CSS before browser parsing (dev only)
556
+ .css(".selector") — CSS for a DOM element
557
+ .inspect(".selector") — element details (classes, chunks, rules)
558
+ .chunks() — style chunk breakdown
559
+ .cache() — cache status and metrics
560
+ .cleanup() — force unused style cleanup
561
+ Options: { raw: true } suppresses logging, { root: shadowRoot } targets Shadow DOM`);
562
+ },
563
+ install() {
564
+ if (typeof window !== "undefined" && window.tastyDebug !== tastyDebug) {
565
+ window.tastyDebug = tastyDebug;
566
+ console.log("tastyDebug installed. Run tastyDebug.help() for commands.");
567
+ }
568
+ }
569
+ };
570
+ function getPageCSS(root = defaultRoot()) {
571
+ if (!root) return "";
572
+ const chunks = [];
573
+ try {
574
+ if ("styleSheets" in root) for (const sheet of Array.from(root.styleSheets)) try {
575
+ if (sheet.cssRules) chunks.push(Array.from(sheet.cssRules).map((r) => r.cssText).join("\n"));
576
+ } catch {}
577
+ } catch {}
578
+ return chunks.join("\n");
579
+ }
580
+ //#endregion
581
+ export { tastyDebug as t };
582
+
583
+ //# sourceMappingURL=debug-Vyauml7U.js.map