@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.
- package/README.md +38 -54
- package/dist/{babel-BUQGeOXA.d.ts → babel-D6lOuSwk.d.ts} +2 -2
- package/dist/chunks/async-storage-DKK-wTD4.js.map +1 -0
- package/dist/chunks/build-config-BBThSdlo.js +45 -0
- package/dist/chunks/build-config-BBThSdlo.js.map +1 -0
- package/dist/{collector-DTahQUiV.js → chunks/collector-DcViW2ZQ.js} +28 -14
- package/dist/chunks/collector-DcViW2ZQ.js.map +1 -0
- package/dist/chunks/config-engine-DQVQK4NU.js +403 -0
- package/dist/chunks/config-engine-DQVQK4NU.js.map +1 -0
- package/dist/chunks/css-definitions-BZ9vm0ci.js +1284 -0
- package/dist/chunks/css-definitions-BZ9vm0ci.js.map +1 -0
- package/dist/chunks/css-resources-Cyl_axbI.js +149 -0
- package/dist/chunks/css-resources-Cyl_axbI.js.map +1 -0
- package/dist/chunks/debug-Vyauml7U.js +583 -0
- package/dist/chunks/debug-Vyauml7U.js.map +1 -0
- package/dist/chunks/dsl-CXvoaLnj.js +2097 -0
- package/dist/chunks/dsl-CXvoaLnj.js.map +1 -0
- package/dist/chunks/hydration-CLdVKcH2.js +59 -0
- package/dist/chunks/hydration-CLdVKcH2.js.map +1 -0
- package/dist/chunks/react-runtime-so_X_yMo.js +1526 -0
- package/dist/chunks/react-runtime-so_X_yMo.js.map +1 -0
- package/dist/chunks/runtime-engine-DQ5laRou.js +3056 -0
- package/dist/chunks/runtime-engine-DQ5laRou.js.map +1 -0
- package/dist/{merge-styles-oklji0KB.js → chunks/shared-utils-OIg0N_dp.js} +42 -3
- package/dist/chunks/shared-utils-OIg0N_dp.js.map +1 -0
- package/dist/{config-B5kHzuNz.js → chunks/style-engine-CBuOt1e4.js} +2387 -7442
- package/dist/chunks/style-engine-CBuOt1e4.js.map +1 -0
- package/dist/{css-writer-B-J87ncv.js → chunks/zero-engine-BFh7gKbK.js} +3 -3
- package/dist/chunks/zero-engine-BFh7gKbK.js.map +1 -0
- package/dist/{collector-DUaHCcTS.d.ts → collector-CAmndLXe.d.ts} +23 -3
- package/dist/{config-YsxGv4tq.d.ts → config-BWYrv_Aa.d.ts} +141 -37
- package/dist/core/index.d.ts +5 -5
- package/dist/core/index.js +9 -6
- package/dist/{index-Cd45t5NM.d.ts → index-BzAC3p06.d.ts} +118 -23
- package/dist/{index-PqN-DIpn.d.ts → index-D4kRLj2o.d.ts} +128 -68
- package/dist/index.d.ts +5 -5
- package/dist/index.js +10 -922
- package/dist/{merge-styles-CU7JbEwg.d.ts → merge-styles-BFktNP8J.d.ts} +2 -2
- package/dist/ssr/astro-client.js +1 -1
- package/dist/ssr/astro-middleware-extract-static.d.ts +11 -0
- package/dist/ssr/astro-middleware-extract-static.js +9 -0
- package/dist/ssr/astro-middleware-extract-static.js.map +1 -0
- package/dist/ssr/astro-middleware-extract.d.ts +11 -0
- package/dist/ssr/astro-middleware-extract.js +9 -0
- package/dist/ssr/astro-middleware-extract.js.map +1 -0
- package/dist/ssr/astro-middleware-static.d.ts +3 -1
- package/dist/ssr/astro-middleware.d.ts +3 -1
- package/dist/ssr/astro.d.ts +45 -3
- package/dist/ssr/astro.js +157 -14
- package/dist/ssr/astro.js.map +1 -1
- package/dist/ssr/index.d.ts +7 -7
- package/dist/ssr/index.js +4 -4
- package/dist/ssr/index.js.map +1 -1
- package/dist/ssr/next-config.d.ts +66 -0
- package/dist/ssr/next-config.js +135 -0
- package/dist/ssr/next-config.js.map +1 -0
- package/dist/ssr/next.d.ts +9 -2
- package/dist/ssr/next.js +26 -10
- package/dist/ssr/next.js.map +1 -1
- package/dist/static/index.d.ts +2 -2
- package/dist/static/index.js +1 -1
- package/dist/zero/babel.d.ts +1 -1
- package/dist/zero/babel.js +25 -24
- package/dist/zero/babel.js.map +1 -1
- package/dist/zero/index.d.ts +1 -1
- package/dist/zero/index.js +1 -1
- package/dist/zero/next.d.ts +1 -1
- package/docs/README.md +5 -3
- package/docs/adoption.md +3 -3
- package/docs/ai-agents.md +83 -78
- package/docs/comparison.md +12 -12
- package/docs/configuration.md +47 -47
- package/docs/debug.md +19 -7
- package/docs/dsl.md +3 -3
- package/docs/getting-started.md +10 -10
- package/docs/injector.md +62 -25
- package/docs/methodology.md +3 -3
- package/docs/migration-v3.md +49 -49
- package/docs/plugins.md +37 -33
- package/docs/react-api.md +2 -2
- package/docs/runtime-benchmarks.md +351 -0
- package/docs/ssr.md +219 -61
- package/docs/styles.md +43 -11
- package/docs/tasty-static.md +136 -103
- package/package.json +80 -11
- package/dist/async-storage-DKK-wTD4.js.map +0 -1
- package/dist/collector-DTahQUiV.js.map +0 -1
- package/dist/config-B5kHzuNz.js.map +0 -1
- package/dist/context-CA8YKeMn.js +0 -24
- package/dist/context-CA8YKeMn.js.map +0 -1
- package/dist/core-Dr4u1NVD.js +0 -1566
- package/dist/core-Dr4u1NVD.js.map +0 -1
- package/dist/css-writer-B-J87ncv.js.map +0 -1
- package/dist/format-global-rules-DklyaXv-.js +0 -22
- package/dist/format-global-rules-DklyaXv-.js.map +0 -1
- package/dist/format-rules-DKOA-6qu.js +0 -130
- package/dist/format-rules-DKOA-6qu.js.map +0 -1
- package/dist/hydrate-OeMX99We.js +0 -37
- package/dist/hydrate-OeMX99We.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/keyframes-CV8azJf3.js +0 -493
- package/dist/keyframes-CV8azJf3.js.map +0 -1
- package/dist/merge-styles-oklji0KB.js.map +0 -1
- package/dist/resolve-recipes-DTG81rzl.js +0 -144
- package/dist/resolve-recipes-DTG81rzl.js.map +0 -1
- /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
|