@tenphi/tasty 0.0.0-snapshot.cfcf770 → 0.0.0-snapshot.d2dcdeb
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 +25 -19
- package/dist/compute-styles.js +6 -28
- package/dist/compute-styles.js.map +1 -1
- package/dist/config.d.ts +41 -1
- package/dist/config.js +92 -7
- package/dist/config.js.map +1 -1
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +1 -1
- package/dist/debug.js +4 -4
- package/dist/debug.js.map +1 -1
- package/dist/hooks/useCounterStyle.d.ts +3 -17
- package/dist/hooks/useCounterStyle.js +55 -35
- package/dist/hooks/useCounterStyle.js.map +1 -1
- package/dist/hooks/useFontFace.d.ts +3 -1
- package/dist/hooks/useFontFace.js +21 -24
- package/dist/hooks/useFontFace.js.map +1 -1
- package/dist/hooks/useGlobalStyles.d.ts +18 -2
- package/dist/hooks/useGlobalStyles.js +51 -40
- package/dist/hooks/useGlobalStyles.js.map +1 -1
- package/dist/hooks/useKeyframes.d.ts +4 -2
- package/dist/hooks/useKeyframes.js +42 -50
- package/dist/hooks/useKeyframes.js.map +1 -1
- package/dist/hooks/useProperty.d.ts +4 -2
- package/dist/hooks/useProperty.js +29 -41
- package/dist/hooks/useProperty.js.map +1 -1
- package/dist/hooks/useRawCSS.d.ts +13 -44
- package/dist/hooks/useRawCSS.js +90 -21
- package/dist/hooks/useRawCSS.js.map +1 -1
- package/dist/hooks/useStyles.d.ts +4 -4
- package/dist/hooks/useStyles.js +7 -5
- package/dist/hooks/useStyles.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/injector/index.js +1 -1
- package/dist/injector/index.js.map +1 -1
- package/dist/injector/injector.d.ts +9 -7
- package/dist/injector/injector.js +126 -38
- package/dist/injector/injector.js.map +1 -1
- package/dist/injector/sheet-manager.js +4 -2
- package/dist/injector/sheet-manager.js.map +1 -1
- package/dist/injector/types.d.ts +11 -2
- package/dist/pipeline/parseStateKey.js +4 -4
- package/dist/pipeline/parseStateKey.js.map +1 -1
- package/dist/plugins/types.d.ts +12 -1
- package/dist/rsc-cache.js +79 -0
- package/dist/rsc-cache.js.map +1 -0
- package/dist/ssr/astro-client.d.ts +1 -0
- package/dist/ssr/astro-client.js +19 -0
- package/dist/ssr/astro-client.js.map +1 -0
- package/dist/ssr/astro-middleware.d.ts +15 -0
- package/dist/ssr/astro-middleware.js +19 -0
- package/dist/ssr/astro-middleware.js.map +1 -0
- package/dist/ssr/astro.d.ts +89 -10
- package/dist/ssr/astro.js +112 -27
- package/dist/ssr/astro.js.map +1 -1
- package/dist/ssr/async-storage.js +14 -4
- package/dist/ssr/async-storage.js.map +1 -1
- package/dist/ssr/collect-auto-properties.js +28 -9
- package/dist/ssr/collect-auto-properties.js.map +1 -1
- package/dist/ssr/collector.d.ts +5 -13
- package/dist/ssr/collector.js +27 -15
- package/dist/ssr/collector.js.map +1 -1
- package/dist/ssr/context.js +16 -0
- package/dist/ssr/context.js.map +1 -0
- package/dist/ssr/hydrate.d.ts +20 -13
- package/dist/ssr/hydrate.js +24 -28
- package/dist/ssr/hydrate.js.map +1 -1
- package/dist/ssr/index.d.ts +3 -3
- package/dist/ssr/index.js +4 -4
- package/dist/ssr/index.js.map +1 -1
- package/dist/ssr/next.d.ts +7 -4
- package/dist/ssr/next.js +7 -6
- package/dist/ssr/next.js.map +1 -1
- package/dist/ssr/ssr-collector-ref.js +19 -2
- package/dist/ssr/ssr-collector-ref.js.map +1 -1
- package/dist/tasty.d.ts +1 -1
- package/dist/tasty.js +9 -4
- package/dist/tasty.js.map +1 -1
- package/dist/utils/deps-equal.js +15 -0
- package/dist/utils/deps-equal.js.map +1 -0
- package/dist/utils/hash.js +14 -0
- package/dist/utils/hash.js.map +1 -0
- package/dist/utils/typography.d.ts +21 -10
- package/dist/utils/typography.js +1 -1
- package/dist/utils/typography.js.map +1 -1
- package/dist/zero/babel.d.ts +7 -108
- package/dist/zero/babel.js +36 -12
- package/dist/zero/babel.js.map +1 -1
- package/docs/README.md +2 -2
- package/docs/adoption.md +5 -3
- package/docs/comparison.md +24 -25
- package/docs/configuration.md +69 -1
- package/docs/design-system.md +22 -10
- package/docs/dsl.md +3 -3
- package/docs/getting-started.md +10 -10
- package/docs/injector.md +9 -7
- package/docs/methodology.md +2 -2
- package/docs/{runtime.md → react-api.md} +17 -32
- package/docs/ssr.md +125 -39
- package/docs/tasty-static.md +14 -2
- package/package.json +9 -3
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getEffectiveDefinition, normalizePropertyDefinition } from "../properties/index.js";
|
|
2
|
+
import { hashString } from "../utils/hash.js";
|
|
2
3
|
import { isDevEnv } from "../utils/is-dev-env.js";
|
|
3
4
|
import { parseStyle } from "../utils/styles.js";
|
|
4
5
|
import { SheetManager } from "./sheet-manager.js";
|
|
@@ -6,16 +7,66 @@ import { fontFaceContentHash, formatFontFaceDeclarations } from "../font-face/in
|
|
|
6
7
|
import { formatCounterStyleDeclarations } from "../counter-style/index.js";
|
|
7
8
|
//#region src/injector/injector.ts
|
|
8
9
|
/**
|
|
9
|
-
* Generate
|
|
10
|
+
* Generate a deterministic class name from a cache key using content hash.
|
|
11
|
+
* The same cache key always produces the same class name across environments.
|
|
10
12
|
*/
|
|
11
|
-
function generateClassName(
|
|
12
|
-
return `t${
|
|
13
|
+
function generateClassName(cacheKey) {
|
|
14
|
+
return `t${hashString(cacheKey)}`;
|
|
15
|
+
}
|
|
16
|
+
const RSC_CLASS_RE = /\.(t[a-z0-9]+)\.\1/g;
|
|
17
|
+
/**
|
|
18
|
+
* Extract class names from `<style data-tasty-rsc>` tags.
|
|
19
|
+
* The doubled-specificity pattern `.tXXX.tXXX` makes extraction reliable.
|
|
20
|
+
*/
|
|
21
|
+
function extractRSCClassNames() {
|
|
22
|
+
if (typeof document === "undefined") return [];
|
|
23
|
+
const styles = document.querySelectorAll("style[data-tasty-rsc]");
|
|
24
|
+
if (styles.length === 0) return [];
|
|
25
|
+
const classSet = /* @__PURE__ */ new Set();
|
|
26
|
+
for (const style of styles) {
|
|
27
|
+
const text = style.textContent;
|
|
28
|
+
if (!text) continue;
|
|
29
|
+
let match;
|
|
30
|
+
RSC_CLASS_RE.lastIndex = 0;
|
|
31
|
+
while ((match = RSC_CLASS_RE.exec(text)) !== null) classSet.add(match[1]);
|
|
32
|
+
}
|
|
33
|
+
return Array.from(classSet);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Lazily sync server-rendered class names into the client registry.
|
|
37
|
+
*
|
|
38
|
+
* Sources:
|
|
39
|
+
* 1. `window.__TASTY__` — pushed by SSR/RSC streaming scripts
|
|
40
|
+
* 2. `<style data-tasty-rsc>` tags — inline CSS emitted by RSC components
|
|
41
|
+
*
|
|
42
|
+
* Called inside `inject()` / `allocateClassName()` to pick up
|
|
43
|
+
* class names rendered on the server (including during SPA navigation).
|
|
44
|
+
*/
|
|
45
|
+
function syncServerClasses(registry) {
|
|
46
|
+
if (typeof window === "undefined") return;
|
|
47
|
+
const classes = window.__TASTY__;
|
|
48
|
+
if (classes && classes.length > registry.serverClassSyncIndex) {
|
|
49
|
+
for (let i = registry.serverClassSyncIndex; i < classes.length; i++) registerHydratedClass(registry, classes[i]);
|
|
50
|
+
registry.serverClassSyncIndex = classes.length;
|
|
51
|
+
}
|
|
52
|
+
if (!registry.rscStylesScanned) {
|
|
53
|
+
registry.rscStylesScanned = true;
|
|
54
|
+
for (const cls of extractRSCClassNames()) registerHydratedClass(registry, cls);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function registerHydratedClass(registry, className) {
|
|
58
|
+
if (registry.rules.has(className)) return;
|
|
59
|
+
registry.rules.set(className, {
|
|
60
|
+
className,
|
|
61
|
+
ruleIndex: -2,
|
|
62
|
+
sheetIndex: -2
|
|
63
|
+
});
|
|
64
|
+
registry.refCounts.set(className, 0);
|
|
13
65
|
}
|
|
14
66
|
var StyleInjector = class StyleInjector {
|
|
15
67
|
sheetManager;
|
|
16
68
|
config;
|
|
17
69
|
globalRuleCounter = 0;
|
|
18
|
-
touchCount = 0;
|
|
19
70
|
pendingGCHandle = null;
|
|
20
71
|
/** @internal — exposed for debug utilities only */
|
|
21
72
|
get _sheetManager() {
|
|
@@ -26,6 +77,19 @@ var StyleInjector = class StyleInjector {
|
|
|
26
77
|
this.sheetManager = new SheetManager(config);
|
|
27
78
|
}
|
|
28
79
|
/**
|
|
80
|
+
* Check if `className` was hydrated from server-rendered styles and,
|
|
81
|
+
* if so, wire the cacheKey mapping. Returns true on hit.
|
|
82
|
+
*/
|
|
83
|
+
tryHydratedHit(registry, cacheKey, className) {
|
|
84
|
+
syncServerClasses(registry);
|
|
85
|
+
const rule = registry.rules.get(className);
|
|
86
|
+
if (rule && rule.ruleIndex === -2 && rule.sheetIndex === -2) {
|
|
87
|
+
registry.cacheKeyToClassName.set(cacheKey, className);
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
29
93
|
* Allocate a className for a cacheKey without injecting styles yet.
|
|
30
94
|
* This allows separating className allocation (render phase) from style injection (insertion phase).
|
|
31
95
|
*/
|
|
@@ -36,7 +100,19 @@ var StyleInjector = class StyleInjector {
|
|
|
36
100
|
className: registry.cacheKeyToClassName.get(cacheKey),
|
|
37
101
|
isNewAllocation: false
|
|
38
102
|
};
|
|
39
|
-
const className = generateClassName(
|
|
103
|
+
const className = generateClassName(cacheKey);
|
|
104
|
+
if (this.tryHydratedHit(registry, cacheKey, className)) return {
|
|
105
|
+
className,
|
|
106
|
+
isNewAllocation: false
|
|
107
|
+
};
|
|
108
|
+
if (registry.rules.get(className)) {
|
|
109
|
+
if (isDevEnv()) console.warn(`[tasty] Hash collision: cache keys produce the same class "${className}". Styles may be incorrect.`);
|
|
110
|
+
registry.cacheKeyToClassName.set(cacheKey, className);
|
|
111
|
+
return {
|
|
112
|
+
className,
|
|
113
|
+
isNewAllocation: false
|
|
114
|
+
};
|
|
115
|
+
}
|
|
40
116
|
const placeholderRuleInfo = {
|
|
41
117
|
className,
|
|
42
118
|
ruleIndex: -1,
|
|
@@ -75,7 +151,17 @@ var StyleInjector = class StyleInjector {
|
|
|
75
151
|
dispose: () => this.dispose(className, registry)
|
|
76
152
|
};
|
|
77
153
|
}
|
|
78
|
-
} else
|
|
154
|
+
} else if (cacheKey) {
|
|
155
|
+
className = generateClassName(cacheKey);
|
|
156
|
+
if (this.tryHydratedHit(registry, cacheKey, className)) {
|
|
157
|
+
registry.refCounts.set(className, (registry.refCounts.get(className) || 0) + 1);
|
|
158
|
+
if (registry.metrics) registry.metrics.hits++;
|
|
159
|
+
return {
|
|
160
|
+
className,
|
|
161
|
+
dispose: () => this.dispose(className, registry)
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
} else className = `t${hashString(rules.map((r) => `${r.selector}\0${r.declarations}`).join("\n"))}`;
|
|
79
165
|
const rulesToInsert = rules.map((rule) => {
|
|
80
166
|
let newSelector = rule.selector;
|
|
81
167
|
if (rule.needsClassName) {
|
|
@@ -448,7 +534,7 @@ var StyleInjector = class StyleInjector {
|
|
|
448
534
|
}
|
|
449
535
|
}
|
|
450
536
|
}
|
|
451
|
-
static TASTY_CLASS_RE = /^t
|
|
537
|
+
static TASTY_CLASS_RE = /^t[a-z0-9]+$/;
|
|
452
538
|
/**
|
|
453
539
|
* Record a render-time usage hit for one or more classNames.
|
|
454
540
|
* Handles space-separated multi-chunk classNames.
|
|
@@ -469,35 +555,35 @@ var StyleInjector = class StyleInjector {
|
|
|
469
555
|
const entry = registry.usageMap.get(cls);
|
|
470
556
|
if (entry) entry.lastTouchedAt = now;
|
|
471
557
|
else registry.usageMap.set(cls, { lastTouchedAt: now });
|
|
472
|
-
|
|
558
|
+
registry.touchCount++;
|
|
473
559
|
}
|
|
474
560
|
const touchInterval = this.config.gc.touchInterval ?? 1e3;
|
|
475
|
-
if (
|
|
476
|
-
|
|
477
|
-
this.scheduleGC(
|
|
561
|
+
if (registry.touchCount >= touchInterval) {
|
|
562
|
+
registry.touchCount = 0;
|
|
563
|
+
this.scheduleGC();
|
|
478
564
|
}
|
|
479
565
|
}
|
|
480
566
|
/**
|
|
481
567
|
* Schedule a GC via `requestIdleCallback` (or synchronously as fallback).
|
|
482
|
-
* Avoids double-scheduling via `pendingGCHandle`.
|
|
568
|
+
* Runs GC on all active roots. Avoids double-scheduling via `pendingGCHandle`.
|
|
483
569
|
*/
|
|
484
|
-
scheduleGC(
|
|
570
|
+
scheduleGC() {
|
|
485
571
|
if (this.pendingGCHandle != null) return;
|
|
486
|
-
|
|
572
|
+
const runGC = () => {
|
|
487
573
|
this.pendingGCHandle = null;
|
|
488
|
-
this.
|
|
489
|
-
|
|
490
|
-
|
|
574
|
+
this.sheetManager.pruneDisconnectedRoots();
|
|
575
|
+
for (const root of this.sheetManager.getActiveRoots()) this.gc({ root });
|
|
576
|
+
};
|
|
577
|
+
if (typeof requestIdleCallback !== "undefined") this.pendingGCHandle = requestIdleCallback(() => runGC());
|
|
578
|
+
else runGC();
|
|
491
579
|
}
|
|
492
580
|
/**
|
|
493
581
|
* Synchronous garbage collection.
|
|
494
582
|
*
|
|
495
|
-
* 1. Quick check: if
|
|
583
|
+
* 1. Quick upper-bound check: skip if unused count can't exceed capacity.
|
|
496
584
|
* 2. Scans the DOM for live tasty classNames (safety guard).
|
|
497
|
-
* 3.
|
|
498
|
-
*
|
|
499
|
-
* 5. Sorts unused by lastTouchedAt ascending, evicts oldest until at capacity.
|
|
500
|
-
* With `force: true`, evicts ALL unused regardless of capacity.
|
|
585
|
+
* 3. With `force: true`: deletes all unused entries inline.
|
|
586
|
+
* Without `force`: collects unused, sorts oldest-first, evicts over capacity.
|
|
501
587
|
*
|
|
502
588
|
* @returns Number of styles evicted.
|
|
503
589
|
*/
|
|
@@ -518,28 +604,30 @@ var StyleInjector = class StyleInjector {
|
|
|
518
604
|
}
|
|
519
605
|
const liveClasses = /* @__PURE__ */ new Set();
|
|
520
606
|
for (const el of root.querySelectorAll("[class]")) for (const token of el.classList) if (StyleInjector.TASTY_CLASS_RE.test(token)) liveClasses.add(token);
|
|
521
|
-
|
|
522
|
-
for (const [className
|
|
607
|
+
let swept = 0;
|
|
608
|
+
if (force) for (const [className] of registry.usageMap) {
|
|
523
609
|
if (liveClasses.has(className)) continue;
|
|
524
610
|
if ((registry.refCounts.get(className) ?? 0) > 0) continue;
|
|
525
|
-
unused.push({
|
|
526
|
-
className,
|
|
527
|
-
lastTouchedAt: usage.lastTouchedAt
|
|
528
|
-
});
|
|
529
|
-
}
|
|
530
|
-
if (unused.length === 0) return 0;
|
|
531
|
-
if (!force && unused.length <= capacity) return 0;
|
|
532
|
-
let swept = 0;
|
|
533
|
-
if (force) for (const { className } of unused) {
|
|
534
611
|
registry.usageMap.delete(className);
|
|
535
612
|
swept++;
|
|
536
613
|
}
|
|
537
614
|
else {
|
|
538
|
-
unused
|
|
539
|
-
const
|
|
540
|
-
|
|
541
|
-
registry.
|
|
542
|
-
|
|
615
|
+
const unused = [];
|
|
616
|
+
for (const [className, usage] of registry.usageMap) {
|
|
617
|
+
if (liveClasses.has(className)) continue;
|
|
618
|
+
if ((registry.refCounts.get(className) ?? 0) > 0) continue;
|
|
619
|
+
unused.push({
|
|
620
|
+
className,
|
|
621
|
+
lastTouchedAt: usage.lastTouchedAt
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
if (unused.length > capacity) {
|
|
625
|
+
unused.sort((a, b) => a.lastTouchedAt - b.lastTouchedAt);
|
|
626
|
+
const toEvict = unused.length - capacity;
|
|
627
|
+
for (let i = 0; i < toEvict; i++) {
|
|
628
|
+
registry.usageMap.delete(unused[i].className);
|
|
629
|
+
swept++;
|
|
630
|
+
}
|
|
543
631
|
}
|
|
544
632
|
}
|
|
545
633
|
if (swept > 0) this.sheetManager.forceCleanup(registry);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"injector.js","names":[],"sources":["../../src/injector/injector.ts"],"sourcesContent":["/**\n * Style injector that works with structured style objects\n * Eliminates CSS string parsing for better performance\n */\n\nimport type { StyleResult } from '../pipeline';\nimport {\n getEffectiveDefinition,\n normalizePropertyDefinition,\n} from '../properties';\nimport { isDevEnv } from '../utils/is-dev-env';\nimport type { StyleValue } from '../utils/styles';\nimport { parseStyle } from '../utils/styles';\n\nimport { SheetManager } from './sheet-manager';\nimport { fontFaceContentHash, formatFontFaceDeclarations } from '../font-face';\nimport { formatCounterStyleDeclarations } from '../counter-style';\nimport type {\n CacheMetrics,\n CounterStyleDescriptors,\n FontFaceDescriptors,\n GCOptions,\n GlobalInjectResult,\n InjectResult,\n KeyframesResult,\n KeyframesSteps,\n PropertyDefinition,\n RawCSSResult,\n RootRegistry,\n StyleInjectorConfig,\n StyleRule,\n} from './types';\n\n/**\n * Generate sequential class name with format t{number}\n */\nfunction generateClassName(counter: number): string {\n return `t${counter}`;\n}\n\nexport class StyleInjector {\n private sheetManager: SheetManager;\n private config: StyleInjectorConfig;\n private globalRuleCounter = 0;\n private touchCount = 0;\n private pendingGCHandle: ReturnType<typeof requestIdleCallback> | null = null;\n\n /** @internal — exposed for debug utilities only */\n get _sheetManager(): SheetManager {\n return this.sheetManager;\n }\n\n constructor(config: StyleInjectorConfig = {}) {\n this.config = config;\n this.sheetManager = new SheetManager(config);\n }\n\n /**\n * Allocate a className for a cacheKey without injecting styles yet.\n * This allows separating className allocation (render phase) from style injection (insertion phase).\n */\n allocateClassName(\n cacheKey: string,\n options?: { root?: Document | ShadowRoot },\n ): { className: string; isNewAllocation: boolean } {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n\n // Check if we can reuse existing className for this cache key\n if (registry.cacheKeyToClassName.has(cacheKey)) {\n const className = registry.cacheKeyToClassName.get(cacheKey)!;\n return {\n className,\n isNewAllocation: false,\n };\n }\n\n // Generate new className and reserve it\n const className = generateClassName(registry.classCounter++);\n\n // Create placeholder RuleInfo to reserve the className\n const placeholderRuleInfo = {\n className,\n ruleIndex: -1, // Placeholder - will be set during actual injection\n sheetIndex: -1, // Placeholder - will be set during actual injection\n };\n\n // Store RuleInfo only once by className, and map cacheKey separately\n registry.rules.set(className, placeholderRuleInfo);\n registry.cacheKeyToClassName.set(cacheKey, className);\n\n return {\n className,\n isNewAllocation: true,\n };\n }\n\n /**\n * Inject styles from StyleResult objects\n */\n inject(\n rules: StyleResult[],\n options?: { root?: Document | ShadowRoot; cacheKey?: string },\n ): InjectResult {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n\n if (rules.length === 0) {\n return {\n className: '',\n dispose: () => {\n /* noop */\n },\n };\n }\n\n // Rules are now in StyleRule format directly\n\n // Check if we can reuse based on cache key\n const cacheKey = options?.cacheKey;\n let className: string;\n let isPreAllocated = false;\n\n if (cacheKey && registry.cacheKeyToClassName.has(cacheKey)) {\n // Reuse existing class for this cache key\n className = registry.cacheKeyToClassName.get(cacheKey)!;\n const existingRuleInfo = registry.rules.get(className)!;\n\n // Check if this is a placeholder (pre-allocated but not yet injected)\n isPreAllocated =\n existingRuleInfo.ruleIndex === -1 && existingRuleInfo.sheetIndex === -1;\n\n if (!isPreAllocated) {\n // Already injected - just increment refCount\n const currentRefCount = registry.refCounts.get(className) || 0;\n registry.refCounts.set(className, currentRefCount + 1);\n\n // Update metrics\n if (registry.metrics) {\n registry.metrics.hits++;\n }\n\n return {\n className,\n dispose: () => this.dispose(className, registry),\n };\n }\n } else {\n // Generate new className\n className = generateClassName(registry.classCounter++);\n }\n\n // Process rules: handle needsClassName flag and apply specificity\n const rulesToInsert = rules.map((rule) => {\n let newSelector = rule.selector;\n\n // If rule needs className prepended\n if (rule.needsClassName) {\n // Handle multiple selectors (separated by ||| for OR conditions)\n const selectorParts = newSelector ? newSelector.split('|||') : [''];\n\n const classPrefix = `.${className}.${className}`;\n\n newSelector = selectorParts\n .map((part) => {\n const classSelector = part ? `${classPrefix}${part}` : classPrefix;\n\n // If there's a root prefix, add it before the class selector\n if (rule.rootPrefix) {\n return `${rule.rootPrefix} ${classSelector}`;\n }\n return classSelector;\n })\n .join(', ');\n }\n\n return {\n ...rule,\n selector: newSelector,\n needsClassName: undefined, // Remove the flag after processing\n rootPrefix: undefined, // Remove rootPrefix after processing\n };\n });\n\n // Auto-register @property for custom properties with inferable types.\n // Colors are detected by --*-color name pattern, numeric types by value.\n if (this.config.autoPropertyTypes !== false) {\n const resolver = registry.propertyTypeResolver;\n const defined = registry.injectedProperties;\n for (const rule of rulesToInsert) {\n if (!rule.declarations) continue;\n resolver.scanDeclarations(\n rule.declarations,\n (name) => defined.has(name),\n (name, syntax, initialValue) => {\n this.property(name, {\n syntax,\n inherits: true,\n initialValue,\n root,\n });\n },\n );\n }\n }\n\n // Insert rules using existing sheet manager\n const ruleInfo = this.sheetManager.insertRule(\n registry,\n rulesToInsert,\n className,\n root,\n );\n\n if (!ruleInfo) {\n // Update metrics\n if (registry.metrics) {\n registry.metrics.misses++;\n }\n\n return {\n className,\n dispose: () => {\n /* noop */\n },\n };\n }\n\n // Store in registry\n registry.refCounts.set(className, 1);\n\n if (isPreAllocated) {\n // Update the existing placeholder entry with real rule info\n registry.rules.set(className, ruleInfo);\n // cacheKey mapping already exists from allocation\n } else {\n // Store new entries\n registry.rules.set(className, ruleInfo);\n if (cacheKey) {\n registry.cacheKeyToClassName.set(cacheKey, className);\n }\n }\n\n // Update metrics\n if (registry.metrics) {\n registry.metrics.totalInsertions++;\n registry.metrics.misses++;\n }\n\n return {\n className,\n dispose: () => this.dispose(className, registry),\n };\n }\n\n /**\n * Inject global styles (rules without a generated tasty class selector)\n * This ensures we don't reserve a tasty class name (t{number}) for global rules,\n * which could otherwise collide with element-level styles and break lookups.\n */\n injectGlobal(\n rules: StyleResult[],\n options?: { root?: Document | ShadowRoot },\n ): GlobalInjectResult {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n\n if (!rules || rules.length === 0) {\n return {\n dispose: () => {\n /* noop */\n },\n };\n }\n\n // Auto-register @property for custom properties in global rules\n if (this.config.autoPropertyTypes !== false) {\n const resolver = registry.propertyTypeResolver;\n const defined = registry.injectedProperties;\n for (const rule of rules) {\n if (!rule.declarations) continue;\n resolver.scanDeclarations(\n rule.declarations,\n (name) => defined.has(name),\n (name, syntax, initialValue) => {\n this.property(name, {\n syntax,\n inherits: true,\n initialValue,\n root,\n });\n },\n );\n }\n }\n\n // Use a non-tasty identifier to avoid any collisions with .t{number} classes\n const key = `global:${this.globalRuleCounter++}`;\n\n const info = this.sheetManager.insertGlobalRule(\n registry,\n rules as unknown as StyleRule[],\n key,\n root,\n );\n\n if (registry.metrics) {\n registry.metrics.totalInsertions++;\n }\n\n return {\n dispose: () => {\n if (info) this.sheetManager.deleteGlobalRule(registry, key);\n },\n };\n }\n\n /**\n * Inject raw CSS text directly without parsing\n * This is a low-overhead alternative to createGlobalStyle for raw CSS\n * The CSS is inserted into a separate style element to avoid conflicts with tasty's chunking\n */\n injectRawCSS(\n css: string,\n options?: { root?: Document | ShadowRoot },\n ): RawCSSResult {\n const root = options?.root || document;\n return this.sheetManager.injectRawCSS(css, root);\n }\n\n /**\n * Get raw CSS text for SSR\n */\n getRawCSSText(options?: { root?: Document | ShadowRoot }): string {\n const root = options?.root || document;\n return this.sheetManager.getRawCSSText(root);\n }\n\n /**\n * Increment refCount for an already-injected cacheKey and return a dispose.\n * Used by useStyles on cache hits (hydration or runtime reuse) where\n * the pipeline was skipped but refCount tracking is still needed.\n * Returns null if the cacheKey is not found.\n */\n trackRef(\n cacheKey: string,\n options?: { root?: Document | ShadowRoot },\n ): InjectResult | null {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n\n if (!registry.cacheKeyToClassName.has(cacheKey)) return null;\n\n const className = registry.cacheKeyToClassName.get(cacheKey)!;\n const currentRefCount = registry.refCounts.get(className) || 0;\n registry.refCounts.set(className, currentRefCount + 1);\n\n if (registry.metrics) {\n registry.metrics.hits++;\n }\n\n return {\n className,\n dispose: () => this.dispose(className, registry),\n };\n }\n\n /**\n * Dispose of a className (decrements refCount only).\n */\n private dispose(className: string, registry: RootRegistry): void {\n const currentRefCount = registry.refCounts.get(className);\n if (currentRefCount == null || currentRefCount <= 0) {\n return;\n }\n\n const newRefCount = currentRefCount - 1;\n registry.refCounts.set(className, newRefCount);\n\n if (newRefCount === 0 && registry.metrics) {\n registry.metrics.totalUnused++;\n }\n }\n\n /**\n * Force bulk cleanup of unused styles\n */\n cleanup(root?: Document | ShadowRoot): void {\n const registry = this.sheetManager.getRegistry(root || document);\n // Clean up ALL unused rules regardless of batch ratio\n this.sheetManager.forceCleanup(registry);\n }\n\n /**\n * Get CSS text from all sheets (for SSR)\n */\n getCssText(options?: { root?: Document | ShadowRoot }): string {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n return this.sheetManager.getCssText(registry);\n }\n\n /**\n * Get CSS only for the provided tasty classNames (e.g., [\"t0\",\"t3\"])\n */\n getCssTextForClasses(\n classNames: Iterable<string>,\n options?: { root?: Document | ShadowRoot },\n ): string {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n\n const cssChunks: string[] = [];\n for (const cls of classNames) {\n const info = registry.rules.get(cls);\n if (info) {\n // Always prefer reading from the live stylesheet, since indices can change\n const sheet = registry.sheets[info.sheetIndex];\n const styleSheet = sheet?.sheet?.sheet;\n if (styleSheet) {\n const start = Math.max(0, info.ruleIndex);\n const end = Math.min(\n styleSheet.cssRules.length - 1,\n (info.endRuleIndex as number) ?? info.ruleIndex,\n );\n // Additional validation: ensure indices are valid and in correct order\n if (\n start >= 0 &&\n end >= start &&\n start < styleSheet.cssRules.length\n ) {\n for (let i = start; i <= end; i++) {\n const rule = styleSheet.cssRules[i] as CSSRule | undefined;\n if (rule) cssChunks.push(rule.cssText);\n }\n }\n } else if (info.cssText && info.cssText.length) {\n // Fallback in environments without CSSOM access\n cssChunks.push(...info.cssText);\n }\n }\n }\n return cssChunks.join('\\n');\n }\n\n /**\n * Get cache performance metrics\n */\n getMetrics(options?: { root?: Document | ShadowRoot }): CacheMetrics | null {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n return this.sheetManager.getMetrics(registry);\n }\n\n /**\n * Reset cache performance metrics\n */\n resetMetrics(options?: { root?: Document | ShadowRoot }): void {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n this.sheetManager.resetMetrics(registry);\n }\n\n /**\n * Define a CSS @property custom property.\n *\n * Accepts tasty token syntax for the property name:\n * - `$name` → defines `--name`\n * - `#name` → defines `--name-color` (auto-sets syntax: '<color>', defaults initialValue: 'transparent')\n * - `--name` → defines `--name` (legacy format)\n *\n * Example:\n * @property --rotation { syntax: \"<angle>\"; inherits: false; initial-value: 45deg; }\n *\n * Note: No caching or dispose — this defines a global property.\n *\n * If the same property is registered with different options, a warning is emitted\n * but the original definition is preserved (CSS @property cannot be redefined).\n */\n property(\n name: string,\n options?: PropertyDefinition & {\n root?: Document | ShadowRoot;\n },\n ): void {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n\n // Parse the token and get effective definition\n // This handles $name, #name, --name formats and auto-sets syntax for colors\n const userDefinition: PropertyDefinition = {\n syntax: options?.syntax,\n inherits: options?.inherits,\n initialValue: options?.initialValue,\n };\n\n const effectiveResult = getEffectiveDefinition(name, userDefinition);\n\n if (!effectiveResult.isValid) {\n if (isDevEnv()) {\n console.warn(\n `[Tasty] property(): ${effectiveResult.error}. Got: \"${name}\"`,\n );\n }\n return;\n }\n\n const cssName = effectiveResult.cssName;\n const definition = effectiveResult.definition;\n\n // Normalize the definition for comparison\n const normalizedDef = normalizePropertyDefinition(definition);\n\n // Check if already defined\n const existingDef = registry.injectedProperties.get(cssName);\n if (existingDef !== undefined) {\n return;\n }\n\n const parts: string[] = [];\n\n if (definition.syntax != null) {\n let syntax = String(definition.syntax).trim();\n if (!/^['\"]/u.test(syntax)) syntax = `\"${syntax}\"`;\n parts.push(`syntax: ${syntax};`);\n }\n\n // inherits is required by the CSS @property spec - default to true\n const inherits = definition.inherits ?? true;\n parts.push(`inherits: ${inherits ? 'true' : 'false'};`);\n\n if (definition.initialValue != null) {\n let initialValueStr: string;\n if (typeof definition.initialValue === 'number') {\n initialValueStr = String(definition.initialValue);\n } else {\n // Process via tasty parser to resolve custom units/functions\n initialValueStr = parseStyle(\n definition.initialValue as StyleValue,\n ).output;\n }\n parts.push(`initial-value: ${initialValueStr};`);\n }\n\n const declarations = parts.join(' ').trim();\n\n const rule: StyleRule = {\n selector: `@property ${cssName}`,\n declarations,\n } as StyleRule;\n\n // Insert as a global rule; only mark injected when insertion succeeds\n const info = this.sheetManager.insertGlobalRule(\n registry,\n [rule],\n `property:${name}`,\n root,\n );\n\n if (!info) {\n return;\n }\n\n // Track that this property was injected with its normalized definition\n registry.injectedProperties.set(cssName, normalizedDef);\n }\n\n /**\n * Check whether a given @property name was already injected by this injector.\n *\n * Accepts tasty token syntax:\n * - `$name` → checks `--name`\n * - `#name` → checks `--name-color`\n * - `--name` → checks `--name` (legacy format)\n */\n isPropertyDefined(\n name: string,\n options?: { root?: Document | ShadowRoot },\n ): boolean {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n\n // Parse the token to get the CSS property name\n const effectiveResult = getEffectiveDefinition(name, {});\n if (!effectiveResult.isValid) {\n return false;\n }\n\n return registry.injectedProperties.has(effectiveResult.cssName);\n }\n\n /**\n * Inject a CSS @font-face rule.\n *\n * Permanent and global — no dispose or ref-counting.\n * Deduplicates by content hash (family + descriptors).\n */\n fontFace(\n family: string,\n descriptors: FontFaceDescriptors,\n options?: { root?: Document | ShadowRoot },\n ): void {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n\n const hash = fontFaceContentHash(family, descriptors);\n\n if (registry.injectedFontFaces.has(hash)) {\n return;\n }\n\n const rule: StyleRule = {\n selector: '@font-face',\n declarations: formatFontFaceDeclarations(family, descriptors),\n } as StyleRule;\n\n const info = this.sheetManager.insertGlobalRule(\n registry,\n [rule],\n `fontface:${hash}`,\n root,\n );\n\n if (info) {\n registry.injectedFontFaces.add(hash);\n }\n }\n\n /**\n * Inject a CSS @counter-style rule.\n *\n * Permanent and global — no dispose or ref-counting.\n * Deduplicates by name (first definition wins).\n */\n counterStyle(\n name: string,\n descriptors: CounterStyleDescriptors,\n options?: { root?: Document | ShadowRoot },\n ): void {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n\n if (registry.injectedCounterStyles.has(name)) {\n return;\n }\n\n const rule: StyleRule = {\n selector: `@counter-style ${name}`,\n declarations: formatCounterStyleDeclarations(descriptors),\n } as StyleRule;\n\n const info = this.sheetManager.insertGlobalRule(\n registry,\n [rule],\n `counterstyle:${name}`,\n root,\n );\n\n if (info) {\n registry.injectedCounterStyles.add(name);\n }\n }\n\n /**\n * Inject keyframes and return object with toString() and dispose()\n *\n * Keyframes are cached by content (steps). If the same content is injected\n * multiple times with different provided names, the first injected name is reused.\n *\n * If the same name is provided with different content (collision), a unique\n * name is generated to avoid overwriting the existing keyframes.\n */\n keyframes(\n steps: KeyframesSteps,\n nameOrOptions?: string | { root?: Document | ShadowRoot; name?: string },\n ): KeyframesResult {\n // Parse parameters\n const isStringName = typeof nameOrOptions === 'string';\n const providedName = isStringName ? nameOrOptions : nameOrOptions?.name;\n const root = isStringName ? document : nameOrOptions?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n\n if (Object.keys(steps).length === 0) {\n return {\n toString: () => '',\n dispose: () => {\n /* noop */\n },\n };\n }\n\n // Generate content-based cache key (independent of provided name)\n const contentHash = JSON.stringify(steps);\n\n // Check if this exact content is already cached\n const existing = registry.keyframesCache.get(contentHash);\n if (existing) {\n existing.refCount++;\n return {\n toString: () => existing.name,\n dispose: () => this.disposeKeyframes(contentHash, registry),\n };\n }\n\n // Determine the actual name to use\n let actualName: string;\n\n if (providedName) {\n // Check if this name is already used with different content\n const existingContentForName =\n registry.keyframesNameToContent.get(providedName);\n\n if (existingContentForName && existingContentForName !== contentHash) {\n // Name collision: same name, different content\n // Generate a unique name to avoid overwriting\n actualName = `${providedName}-k${registry.keyframesCounter++}`;\n } else {\n // Name is available or used with same content\n actualName = providedName;\n // Track this name -> content mapping\n registry.keyframesNameToContent.set(providedName, contentHash);\n }\n } else {\n // No name provided, generate one\n actualName = `k${registry.keyframesCounter++}`;\n }\n\n // Insert keyframes\n const result = this.sheetManager.insertKeyframes(\n registry,\n steps,\n actualName,\n root,\n );\n if (!result) {\n return {\n toString: () => '',\n dispose: () => {\n /* noop */\n },\n };\n }\n\n const { info, declarations } = result;\n\n // Auto-register @property for custom properties found in keyframe declarations\n if (this.config.autoPropertyTypes !== false && declarations) {\n const resolver = registry.propertyTypeResolver;\n resolver.scanDeclarations(\n declarations,\n (name) => registry.injectedProperties.has(name),\n (name, syntax, initialValue) => {\n this.property(name, {\n syntax,\n inherits: true,\n initialValue,\n root,\n });\n },\n );\n }\n\n // Cache the result by content hash\n registry.keyframesCache.set(contentHash, {\n name: actualName,\n refCount: 1,\n info,\n });\n\n // Update metrics\n if (registry.metrics) {\n registry.metrics.totalInsertions++;\n registry.metrics.misses++;\n }\n\n return {\n toString: () => actualName,\n dispose: () => this.disposeKeyframes(contentHash, registry),\n };\n }\n\n /**\n * Dispose keyframes\n */\n private disposeKeyframes(contentHash: string, registry: RootRegistry): void {\n const entry = registry.keyframesCache.get(contentHash);\n if (!entry) return;\n\n entry.refCount--;\n if (entry.refCount <= 0) {\n // Dispose immediately - keyframes are global and safe to clean up right away\n this.sheetManager.deleteKeyframes(registry, entry.info);\n registry.keyframesCache.delete(contentHash);\n\n // Clean up name-to-content mapping if this name was tracked\n // Find and remove the mapping for this content hash\n for (const [name, hash] of registry.keyframesNameToContent.entries()) {\n if (hash === contentHash) {\n registry.keyframesNameToContent.delete(name);\n break;\n }\n }\n\n // Update metrics\n if (registry.metrics) {\n registry.metrics.totalUnused++;\n registry.metrics.stylesCleanedUp++;\n }\n }\n }\n\n // =========================================================================\n // GC: touch-count-driven garbage collection with DOM safety guard\n // =========================================================================\n\n private static readonly TASTY_CLASS_RE = /^t\\d+$/;\n\n /**\n * Record a render-time usage hit for one or more classNames.\n * Handles space-separated multi-chunk classNames.\n * When the global touch counter reaches `touchInterval`, schedules a GC\n * via `requestIdleCallback`.\n * No-op on the server.\n */\n touch(className: string, options?: { root?: Document | ShadowRoot }): void {\n if (typeof document === 'undefined') return;\n if (!this.config.gc) return;\n\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n const now = Date.now();\n\n const parts =\n className.indexOf(' ') === -1 ? [className] : className.split(' ');\n\n for (const cls of parts) {\n if (!StyleInjector.TASTY_CLASS_RE.test(cls)) continue;\n if (!registry.rules.has(cls)) continue;\n\n const entry = registry.usageMap.get(cls);\n if (entry) {\n entry.lastTouchedAt = now;\n } else {\n registry.usageMap.set(cls, { lastTouchedAt: now });\n }\n this.touchCount++;\n }\n\n const touchInterval = this.config.gc.touchInterval ?? 1000;\n if (this.touchCount >= touchInterval) {\n this.touchCount = 0;\n this.scheduleGC(root);\n }\n }\n\n /**\n * Schedule a GC via `requestIdleCallback` (or synchronously as fallback).\n * Avoids double-scheduling via `pendingGCHandle`.\n */\n private scheduleGC(root: Document | ShadowRoot): void {\n if (this.pendingGCHandle != null) return;\n\n if (typeof requestIdleCallback !== 'undefined') {\n this.pendingGCHandle = requestIdleCallback(() => {\n this.pendingGCHandle = null;\n this.gc({ root });\n });\n } else {\n this.gc({ root });\n }\n }\n\n /**\n * Synchronous garbage collection.\n *\n * 1. Quick check: if non-active entries can't exceed capacity, skip entirely.\n * 2. Scans the DOM for live tasty classNames (safety guard).\n * 3. Collects unused entries (refCount === 0, not in DOM).\n * 4. Checks if unused count exceeds capacity (skip if not, unless `force`).\n * 5. Sorts unused by lastTouchedAt ascending, evicts oldest until at capacity.\n * With `force: true`, evicts ALL unused regardless of capacity.\n *\n * @returns Number of styles evicted.\n */\n gc(options?: GCOptions): number {\n if (typeof document === 'undefined') return 0;\n\n // Cancel any pending idle-scheduled GC to prevent double runs\n if (this.pendingGCHandle != null) {\n if (typeof cancelIdleCallback !== 'undefined') {\n cancelIdleCallback(this.pendingGCHandle);\n }\n this.pendingGCHandle = null;\n }\n\n const root = options?.root || document;\n const force = options?.force ?? false;\n const registry = this.sheetManager.getRegistry(root);\n const capacity = this.config.gc?.capacity ?? 1000;\n\n // Quick upper-bound check: count active refs to see if there could\n // possibly be enough unused entries to exceed capacity.\n // This avoids the expensive DOM scan when most styles are active.\n if (!force) {\n let activeCount = 0;\n for (const refCount of registry.refCounts.values()) {\n if (refCount > 0) activeCount++;\n }\n if (registry.usageMap.size - activeCount <= capacity) {\n return 0;\n }\n }\n\n // Scan DOM for live classes (classList handles SVG elements too)\n const liveClasses = new Set<string>();\n for (const el of root.querySelectorAll('[class]')) {\n for (const token of el.classList) {\n if (StyleInjector.TASTY_CLASS_RE.test(token)) {\n liveClasses.add(token);\n }\n }\n }\n\n // Collect unused entries (refCount === 0 and not in DOM)\n const unused: { className: string; lastTouchedAt: number }[] = [];\n for (const [className, usage] of registry.usageMap) {\n if (liveClasses.has(className)) continue;\n if ((registry.refCounts.get(className) ?? 0) > 0) continue;\n unused.push({ className, lastTouchedAt: usage.lastTouchedAt });\n }\n\n if (unused.length === 0) return 0;\n\n if (!force && unused.length <= capacity) {\n return 0;\n }\n\n let swept = 0;\n\n if (force) {\n for (const { className } of unused) {\n registry.usageMap.delete(className);\n swept++;\n }\n } else {\n // Sort oldest first\n unused.sort((a, b) => a.lastTouchedAt - b.lastTouchedAt);\n\n const toEvict = unused.length - capacity;\n for (let i = 0; i < toEvict; i++) {\n registry.usageMap.delete(unused[i].className);\n swept++;\n }\n }\n\n if (swept > 0) {\n this.sheetManager.forceCleanup(registry);\n }\n\n return swept;\n }\n\n /**\n * Destroy all resources for a root\n */\n destroy(root?: Document | ShadowRoot): void {\n const targetRoot = root || document;\n this.sheetManager.cleanup(targetRoot);\n\n // Clear pending GC when no active roots remain\n if (this.pendingGCHandle != null && !this.sheetManager.hasActiveRoots()) {\n if (typeof cancelIdleCallback !== 'undefined') {\n cancelIdleCallback(this.pendingGCHandle);\n }\n this.pendingGCHandle = null;\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"injector.js","names":[],"sources":["../../src/injector/injector.ts"],"sourcesContent":["/**\n * Style injector that works with structured style objects\n * Eliminates CSS string parsing for better performance\n */\n\nimport type { StyleResult } from '../pipeline';\nimport {\n getEffectiveDefinition,\n normalizePropertyDefinition,\n} from '../properties';\nimport { hashString } from '../utils/hash';\nimport { isDevEnv } from '../utils/is-dev-env';\nimport type { StyleValue } from '../utils/styles';\nimport { parseStyle } from '../utils/styles';\n\nimport { SheetManager } from './sheet-manager';\nimport { fontFaceContentHash, formatFontFaceDeclarations } from '../font-face';\nimport { formatCounterStyleDeclarations } from '../counter-style';\nimport { HYDRATED_RULE_INDEX, PLACEHOLDER_RULE_INDEX } from './types';\nimport type {\n CacheMetrics,\n CounterStyleDescriptors,\n FontFaceDescriptors,\n GCOptions,\n GlobalInjectResult,\n InjectResult,\n KeyframesResult,\n KeyframesSteps,\n PropertyDefinition,\n RawCSSResult,\n RootRegistry,\n StyleInjectorConfig,\n StyleRule,\n} from './types';\n\n/**\n * Generate a deterministic class name from a cache key using content hash.\n * The same cache key always produces the same class name across environments.\n */\nfunction generateClassName(cacheKey: string): string {\n return `t${hashString(cacheKey)}`;\n}\n\nconst RSC_CLASS_RE = /\\.(t[a-z0-9]+)\\.\\1/g;\n\n/**\n * Extract class names from `<style data-tasty-rsc>` tags.\n * The doubled-specificity pattern `.tXXX.tXXX` makes extraction reliable.\n */\nfunction extractRSCClassNames(): string[] {\n if (typeof document === 'undefined') return [];\n const styles = document.querySelectorAll('style[data-tasty-rsc]');\n if (styles.length === 0) return [];\n\n const classSet = new Set<string>();\n for (const style of styles) {\n const text = style.textContent;\n if (!text) continue;\n let match: RegExpExecArray | null;\n RSC_CLASS_RE.lastIndex = 0;\n while ((match = RSC_CLASS_RE.exec(text)) !== null) {\n classSet.add(match[1]);\n }\n }\n return Array.from(classSet);\n}\n\n/**\n * Lazily sync server-rendered class names into the client registry.\n *\n * Sources:\n * 1. `window.__TASTY__` — pushed by SSR/RSC streaming scripts\n * 2. `<style data-tasty-rsc>` tags — inline CSS emitted by RSC components\n *\n * Called inside `inject()` / `allocateClassName()` to pick up\n * class names rendered on the server (including during SPA navigation).\n */\nfunction syncServerClasses(registry: RootRegistry): void {\n if (typeof window === 'undefined') return;\n\n // Source 1: window.__TASTY__ (SSR streaming scripts)\n const classes = window.__TASTY__;\n if (classes && classes.length > registry.serverClassSyncIndex) {\n for (let i = registry.serverClassSyncIndex; i < classes.length; i++) {\n registerHydratedClass(registry, classes[i]);\n }\n registry.serverClassSyncIndex = classes.length;\n }\n\n // Source 2: <style data-tasty-rsc> tags (RSC inline styles)\n if (!registry.rscStylesScanned) {\n registry.rscStylesScanned = true;\n for (const cls of extractRSCClassNames()) {\n registerHydratedClass(registry, cls);\n }\n }\n}\n\nfunction registerHydratedClass(\n registry: RootRegistry,\n className: string,\n): void {\n if (registry.rules.has(className)) return;\n registry.rules.set(className, {\n className,\n ruleIndex: HYDRATED_RULE_INDEX,\n sheetIndex: HYDRATED_RULE_INDEX,\n });\n registry.refCounts.set(className, 0);\n}\n\nexport class StyleInjector {\n private sheetManager: SheetManager;\n private config: StyleInjectorConfig;\n private globalRuleCounter = 0;\n private pendingGCHandle: ReturnType<typeof requestIdleCallback> | null = null;\n\n /** @internal — exposed for debug utilities only */\n get _sheetManager(): SheetManager {\n return this.sheetManager;\n }\n\n constructor(config: StyleInjectorConfig = {}) {\n this.config = config;\n this.sheetManager = new SheetManager(config);\n }\n\n /**\n * Check if `className` was hydrated from server-rendered styles and,\n * if so, wire the cacheKey mapping. Returns true on hit.\n */\n private tryHydratedHit(\n registry: RootRegistry,\n cacheKey: string,\n className: string,\n ): boolean {\n syncServerClasses(registry);\n const rule = registry.rules.get(className);\n if (\n rule &&\n rule.ruleIndex === HYDRATED_RULE_INDEX &&\n rule.sheetIndex === HYDRATED_RULE_INDEX\n ) {\n registry.cacheKeyToClassName.set(cacheKey, className);\n return true;\n }\n return false;\n }\n\n /**\n * Allocate a className for a cacheKey without injecting styles yet.\n * This allows separating className allocation (render phase) from style injection (insertion phase).\n */\n allocateClassName(\n cacheKey: string,\n options?: { root?: Document | ShadowRoot },\n ): { className: string; isNewAllocation: boolean } {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n\n // Check if we can reuse existing className for this cache key\n if (registry.cacheKeyToClassName.has(cacheKey)) {\n const className = registry.cacheKeyToClassName.get(cacheKey)!;\n return {\n className,\n isNewAllocation: false,\n };\n }\n\n // Generate deterministic className from cache key\n const className = generateClassName(cacheKey);\n\n // Check if this className was hydrated from server-rendered styles\n if (this.tryHydratedHit(registry, cacheKey, className)) {\n return { className, isNewAllocation: false };\n }\n\n // Hash collision guard: another cache key already owns this class name\n const existingRule = registry.rules.get(className);\n if (existingRule) {\n if (isDevEnv()) {\n console.warn(\n `[tasty] Hash collision: cache keys produce the same class \"${className}\". Styles may be incorrect.`,\n );\n }\n // Treat as already allocated to avoid overwriting\n registry.cacheKeyToClassName.set(cacheKey, className);\n return { className, isNewAllocation: false };\n }\n\n // Create placeholder RuleInfo to reserve the className\n const placeholderRuleInfo = {\n className,\n ruleIndex: PLACEHOLDER_RULE_INDEX,\n sheetIndex: PLACEHOLDER_RULE_INDEX,\n };\n\n // Store RuleInfo only once by className, and map cacheKey separately\n registry.rules.set(className, placeholderRuleInfo);\n registry.cacheKeyToClassName.set(cacheKey, className);\n\n return {\n className,\n isNewAllocation: true,\n };\n }\n\n /**\n * Inject styles from StyleResult objects\n */\n inject(\n rules: StyleResult[],\n options?: { root?: Document | ShadowRoot; cacheKey?: string },\n ): InjectResult {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n\n if (rules.length === 0) {\n return {\n className: '',\n dispose: () => {\n /* noop */\n },\n };\n }\n\n // Rules are now in StyleRule format directly\n\n // Check if we can reuse based on cache key\n const cacheKey = options?.cacheKey;\n let className: string;\n let isPreAllocated = false;\n\n if (cacheKey && registry.cacheKeyToClassName.has(cacheKey)) {\n // Reuse existing class for this cache key\n className = registry.cacheKeyToClassName.get(cacheKey)!;\n const existingRuleInfo = registry.rules.get(className)!;\n\n // Check if this is a placeholder (pre-allocated but not yet injected)\n isPreAllocated =\n existingRuleInfo.ruleIndex === PLACEHOLDER_RULE_INDEX &&\n existingRuleInfo.sheetIndex === PLACEHOLDER_RULE_INDEX;\n\n if (!isPreAllocated) {\n // Already injected - just increment refCount\n const currentRefCount = registry.refCounts.get(className) || 0;\n registry.refCounts.set(className, currentRefCount + 1);\n\n // Update metrics\n if (registry.metrics) {\n registry.metrics.hits++;\n }\n\n return {\n className,\n dispose: () => this.dispose(className, registry),\n };\n }\n } else if (cacheKey) {\n // Generate deterministic className from cache key\n className = generateClassName(cacheKey);\n\n // Check if this className was hydrated from server-rendered styles\n if (this.tryHydratedHit(registry, cacheKey, className)) {\n registry.refCounts.set(\n className,\n (registry.refCounts.get(className) || 0) + 1,\n );\n\n if (registry.metrics) {\n registry.metrics.hits++;\n }\n\n return {\n className,\n dispose: () => this.dispose(className, registry),\n };\n }\n } else {\n // No cache key — generate from rules content\n const parts = rules.map((r) => `${r.selector}\\0${r.declarations}`);\n className = `t${hashString(parts.join('\\n'))}`;\n }\n\n // Process rules: handle needsClassName flag and apply specificity\n const rulesToInsert = rules.map((rule) => {\n let newSelector = rule.selector;\n\n // If rule needs className prepended\n if (rule.needsClassName) {\n // Handle multiple selectors (separated by ||| for OR conditions)\n const selectorParts = newSelector ? newSelector.split('|||') : [''];\n\n const classPrefix = `.${className}.${className}`;\n\n newSelector = selectorParts\n .map((part) => {\n const classSelector = part ? `${classPrefix}${part}` : classPrefix;\n\n // If there's a root prefix, add it before the class selector\n if (rule.rootPrefix) {\n return `${rule.rootPrefix} ${classSelector}`;\n }\n return classSelector;\n })\n .join(', ');\n }\n\n return {\n ...rule,\n selector: newSelector,\n needsClassName: undefined, // Remove the flag after processing\n rootPrefix: undefined, // Remove rootPrefix after processing\n };\n });\n\n // Auto-register @property for custom properties with inferable types.\n // Colors are detected by --*-color name pattern, numeric types by value.\n if (this.config.autoPropertyTypes !== false) {\n const resolver = registry.propertyTypeResolver;\n const defined = registry.injectedProperties;\n for (const rule of rulesToInsert) {\n if (!rule.declarations) continue;\n resolver.scanDeclarations(\n rule.declarations,\n (name) => defined.has(name),\n (name, syntax, initialValue) => {\n this.property(name, {\n syntax,\n inherits: true,\n initialValue,\n root,\n });\n },\n );\n }\n }\n\n // Insert rules using existing sheet manager\n const ruleInfo = this.sheetManager.insertRule(\n registry,\n rulesToInsert,\n className,\n root,\n );\n\n if (!ruleInfo) {\n // Update metrics\n if (registry.metrics) {\n registry.metrics.misses++;\n }\n\n return {\n className,\n dispose: () => {\n /* noop */\n },\n };\n }\n\n // Store in registry\n registry.refCounts.set(className, 1);\n\n if (isPreAllocated) {\n // Update the existing placeholder entry with real rule info\n registry.rules.set(className, ruleInfo);\n // cacheKey mapping already exists from allocation\n } else {\n // Store new entries\n registry.rules.set(className, ruleInfo);\n if (cacheKey) {\n registry.cacheKeyToClassName.set(cacheKey, className);\n }\n }\n\n // Update metrics\n if (registry.metrics) {\n registry.metrics.totalInsertions++;\n registry.metrics.misses++;\n }\n\n return {\n className,\n dispose: () => this.dispose(className, registry),\n };\n }\n\n /**\n * Inject global styles (rules without a generated tasty class selector)\n * This ensures we don't reserve a tasty class name (t{number}) for global rules,\n * which could otherwise collide with element-level styles and break lookups.\n */\n injectGlobal(\n rules: StyleResult[],\n options?: { root?: Document | ShadowRoot },\n ): GlobalInjectResult {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n\n if (!rules || rules.length === 0) {\n return {\n dispose: () => {\n /* noop */\n },\n };\n }\n\n // Auto-register @property for custom properties in global rules\n if (this.config.autoPropertyTypes !== false) {\n const resolver = registry.propertyTypeResolver;\n const defined = registry.injectedProperties;\n for (const rule of rules) {\n if (!rule.declarations) continue;\n resolver.scanDeclarations(\n rule.declarations,\n (name) => defined.has(name),\n (name, syntax, initialValue) => {\n this.property(name, {\n syntax,\n inherits: true,\n initialValue,\n root,\n });\n },\n );\n }\n }\n\n // Use a non-tasty identifier to avoid any collisions with .t{number} classes\n const key = `global:${this.globalRuleCounter++}`;\n\n const info = this.sheetManager.insertGlobalRule(\n registry,\n rules as unknown as StyleRule[],\n key,\n root,\n );\n\n if (registry.metrics) {\n registry.metrics.totalInsertions++;\n }\n\n return {\n dispose: () => {\n if (info) this.sheetManager.deleteGlobalRule(registry, key);\n },\n };\n }\n\n /**\n * Inject raw CSS text directly without parsing\n * This is a low-overhead alternative to createGlobalStyle for raw CSS\n * The CSS is inserted into a separate style element to avoid conflicts with tasty's chunking\n */\n injectRawCSS(\n css: string,\n options?: { root?: Document | ShadowRoot },\n ): RawCSSResult {\n const root = options?.root || document;\n return this.sheetManager.injectRawCSS(css, root);\n }\n\n /**\n * Get raw CSS text for SSR\n */\n getRawCSSText(options?: { root?: Document | ShadowRoot }): string {\n const root = options?.root || document;\n return this.sheetManager.getRawCSSText(root);\n }\n\n /**\n * Increment refCount for an already-injected cacheKey and return a dispose.\n * Used by useStyles on cache hits (hydration or runtime reuse) where\n * the pipeline was skipped but refCount tracking is still needed.\n * Returns null if the cacheKey is not found.\n */\n trackRef(\n cacheKey: string,\n options?: { root?: Document | ShadowRoot },\n ): InjectResult | null {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n\n if (!registry.cacheKeyToClassName.has(cacheKey)) return null;\n\n const className = registry.cacheKeyToClassName.get(cacheKey)!;\n const currentRefCount = registry.refCounts.get(className) || 0;\n registry.refCounts.set(className, currentRefCount + 1);\n\n if (registry.metrics) {\n registry.metrics.hits++;\n }\n\n return {\n className,\n dispose: () => this.dispose(className, registry),\n };\n }\n\n /**\n * Dispose of a className (decrements refCount only).\n */\n private dispose(className: string, registry: RootRegistry): void {\n const currentRefCount = registry.refCounts.get(className);\n if (currentRefCount == null || currentRefCount <= 0) {\n return;\n }\n\n const newRefCount = currentRefCount - 1;\n registry.refCounts.set(className, newRefCount);\n\n if (newRefCount === 0 && registry.metrics) {\n registry.metrics.totalUnused++;\n }\n }\n\n /**\n * Force bulk cleanup of unused styles\n */\n cleanup(root?: Document | ShadowRoot): void {\n const registry = this.sheetManager.getRegistry(root || document);\n // Clean up ALL unused rules regardless of batch ratio\n this.sheetManager.forceCleanup(registry);\n }\n\n /**\n * Get CSS text from all sheets (for SSR)\n */\n getCssText(options?: { root?: Document | ShadowRoot }): string {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n return this.sheetManager.getCssText(registry);\n }\n\n /**\n * Get CSS only for the provided tasty classNames (e.g., [\"t0\",\"t3\"])\n */\n getCssTextForClasses(\n classNames: Iterable<string>,\n options?: { root?: Document | ShadowRoot },\n ): string {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n\n const cssChunks: string[] = [];\n for (const cls of classNames) {\n const info = registry.rules.get(cls);\n if (info) {\n // Always prefer reading from the live stylesheet, since indices can change\n const sheet = registry.sheets[info.sheetIndex];\n const styleSheet = sheet?.sheet?.sheet;\n if (styleSheet) {\n const start = Math.max(0, info.ruleIndex);\n const end = Math.min(\n styleSheet.cssRules.length - 1,\n (info.endRuleIndex as number) ?? info.ruleIndex,\n );\n // Additional validation: ensure indices are valid and in correct order\n if (\n start >= 0 &&\n end >= start &&\n start < styleSheet.cssRules.length\n ) {\n for (let i = start; i <= end; i++) {\n const rule = styleSheet.cssRules[i] as CSSRule | undefined;\n if (rule) cssChunks.push(rule.cssText);\n }\n }\n } else if (info.cssText && info.cssText.length) {\n // Fallback in environments without CSSOM access\n cssChunks.push(...info.cssText);\n }\n }\n }\n return cssChunks.join('\\n');\n }\n\n /**\n * Get cache performance metrics\n */\n getMetrics(options?: { root?: Document | ShadowRoot }): CacheMetrics | null {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n return this.sheetManager.getMetrics(registry);\n }\n\n /**\n * Reset cache performance metrics\n */\n resetMetrics(options?: { root?: Document | ShadowRoot }): void {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n this.sheetManager.resetMetrics(registry);\n }\n\n /**\n * Define a CSS @property custom property.\n *\n * Accepts tasty token syntax for the property name:\n * - `$name` → defines `--name`\n * - `#name` → defines `--name-color` (auto-sets syntax: '<color>', defaults initialValue: 'transparent')\n * - `--name` → defines `--name` (legacy format)\n *\n * Example:\n * @property --rotation { syntax: \"<angle>\"; inherits: false; initial-value: 45deg; }\n *\n * Note: No caching or dispose — this defines a global property.\n *\n * If the same property is registered with different options, a warning is emitted\n * but the original definition is preserved (CSS @property cannot be redefined).\n */\n property(\n name: string,\n options?: PropertyDefinition & {\n root?: Document | ShadowRoot;\n },\n ): void {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n\n // Parse the token and get effective definition\n // This handles $name, #name, --name formats and auto-sets syntax for colors\n const userDefinition: PropertyDefinition = {\n syntax: options?.syntax,\n inherits: options?.inherits,\n initialValue: options?.initialValue,\n };\n\n const effectiveResult = getEffectiveDefinition(name, userDefinition);\n\n if (!effectiveResult.isValid) {\n if (isDevEnv()) {\n console.warn(\n `[Tasty] property(): ${effectiveResult.error}. Got: \"${name}\"`,\n );\n }\n return;\n }\n\n const cssName = effectiveResult.cssName;\n const definition = effectiveResult.definition;\n\n // Normalize the definition for comparison\n const normalizedDef = normalizePropertyDefinition(definition);\n\n // Check if already defined\n const existingDef = registry.injectedProperties.get(cssName);\n if (existingDef !== undefined) {\n return;\n }\n\n const parts: string[] = [];\n\n if (definition.syntax != null) {\n let syntax = String(definition.syntax).trim();\n if (!/^['\"]/u.test(syntax)) syntax = `\"${syntax}\"`;\n parts.push(`syntax: ${syntax};`);\n }\n\n // inherits is required by the CSS @property spec - default to true\n const inherits = definition.inherits ?? true;\n parts.push(`inherits: ${inherits ? 'true' : 'false'};`);\n\n if (definition.initialValue != null) {\n let initialValueStr: string;\n if (typeof definition.initialValue === 'number') {\n initialValueStr = String(definition.initialValue);\n } else {\n // Process via tasty parser to resolve custom units/functions\n initialValueStr = parseStyle(\n definition.initialValue as StyleValue,\n ).output;\n }\n parts.push(`initial-value: ${initialValueStr};`);\n }\n\n const declarations = parts.join(' ').trim();\n\n const rule: StyleRule = {\n selector: `@property ${cssName}`,\n declarations,\n } as StyleRule;\n\n // Insert as a global rule; only mark injected when insertion succeeds\n const info = this.sheetManager.insertGlobalRule(\n registry,\n [rule],\n `property:${name}`,\n root,\n );\n\n if (!info) {\n return;\n }\n\n // Track that this property was injected with its normalized definition\n registry.injectedProperties.set(cssName, normalizedDef);\n }\n\n /**\n * Check whether a given @property name was already injected by this injector.\n *\n * Accepts tasty token syntax:\n * - `$name` → checks `--name`\n * - `#name` → checks `--name-color`\n * - `--name` → checks `--name` (legacy format)\n */\n isPropertyDefined(\n name: string,\n options?: { root?: Document | ShadowRoot },\n ): boolean {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n\n // Parse the token to get the CSS property name\n const effectiveResult = getEffectiveDefinition(name, {});\n if (!effectiveResult.isValid) {\n return false;\n }\n\n return registry.injectedProperties.has(effectiveResult.cssName);\n }\n\n /**\n * Inject a CSS @font-face rule.\n *\n * Permanent and global — no dispose or ref-counting.\n * Deduplicates by content hash (family + descriptors).\n */\n fontFace(\n family: string,\n descriptors: FontFaceDescriptors,\n options?: { root?: Document | ShadowRoot },\n ): void {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n\n const hash = fontFaceContentHash(family, descriptors);\n\n if (registry.injectedFontFaces.has(hash)) {\n return;\n }\n\n const rule: StyleRule = {\n selector: '@font-face',\n declarations: formatFontFaceDeclarations(family, descriptors),\n } as StyleRule;\n\n const info = this.sheetManager.insertGlobalRule(\n registry,\n [rule],\n `fontface:${hash}`,\n root,\n );\n\n if (info) {\n registry.injectedFontFaces.add(hash);\n }\n }\n\n /**\n * Inject a CSS @counter-style rule.\n *\n * Permanent and global — no dispose or ref-counting.\n * Deduplicates by name (first definition wins).\n */\n counterStyle(\n name: string,\n descriptors: CounterStyleDescriptors,\n options?: { root?: Document | ShadowRoot },\n ): void {\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n\n if (registry.injectedCounterStyles.has(name)) {\n return;\n }\n\n const rule: StyleRule = {\n selector: `@counter-style ${name}`,\n declarations: formatCounterStyleDeclarations(descriptors),\n } as StyleRule;\n\n const info = this.sheetManager.insertGlobalRule(\n registry,\n [rule],\n `counterstyle:${name}`,\n root,\n );\n\n if (info) {\n registry.injectedCounterStyles.add(name);\n }\n }\n\n /**\n * Inject keyframes and return object with toString() and dispose()\n *\n * Keyframes are cached by content (steps). If the same content is injected\n * multiple times with different provided names, the first injected name is reused.\n *\n * If the same name is provided with different content (collision), a unique\n * name is generated to avoid overwriting the existing keyframes.\n */\n keyframes(\n steps: KeyframesSteps,\n nameOrOptions?: string | { root?: Document | ShadowRoot; name?: string },\n ): KeyframesResult {\n // Parse parameters\n const isStringName = typeof nameOrOptions === 'string';\n const providedName = isStringName ? nameOrOptions : nameOrOptions?.name;\n const root = isStringName ? document : nameOrOptions?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n\n if (Object.keys(steps).length === 0) {\n return {\n toString: () => '',\n dispose: () => {\n /* noop */\n },\n };\n }\n\n // Generate content-based cache key (independent of provided name)\n const contentHash = JSON.stringify(steps);\n\n // Check if this exact content is already cached\n const existing = registry.keyframesCache.get(contentHash);\n if (existing) {\n existing.refCount++;\n return {\n toString: () => existing.name,\n dispose: () => this.disposeKeyframes(contentHash, registry),\n };\n }\n\n // Determine the actual name to use\n let actualName: string;\n\n if (providedName) {\n // Check if this name is already used with different content\n const existingContentForName =\n registry.keyframesNameToContent.get(providedName);\n\n if (existingContentForName && existingContentForName !== contentHash) {\n // Name collision: same name, different content\n // Generate a unique name to avoid overwriting\n actualName = `${providedName}-k${registry.keyframesCounter++}`;\n } else {\n // Name is available or used with same content\n actualName = providedName;\n // Track this name -> content mapping\n registry.keyframesNameToContent.set(providedName, contentHash);\n }\n } else {\n // No name provided, generate one\n actualName = `k${registry.keyframesCounter++}`;\n }\n\n // Insert keyframes\n const result = this.sheetManager.insertKeyframes(\n registry,\n steps,\n actualName,\n root,\n );\n if (!result) {\n return {\n toString: () => '',\n dispose: () => {\n /* noop */\n },\n };\n }\n\n const { info, declarations } = result;\n\n // Auto-register @property for custom properties found in keyframe declarations\n if (this.config.autoPropertyTypes !== false && declarations) {\n const resolver = registry.propertyTypeResolver;\n resolver.scanDeclarations(\n declarations,\n (name) => registry.injectedProperties.has(name),\n (name, syntax, initialValue) => {\n this.property(name, {\n syntax,\n inherits: true,\n initialValue,\n root,\n });\n },\n );\n }\n\n // Cache the result by content hash\n registry.keyframesCache.set(contentHash, {\n name: actualName,\n refCount: 1,\n info,\n });\n\n // Update metrics\n if (registry.metrics) {\n registry.metrics.totalInsertions++;\n registry.metrics.misses++;\n }\n\n return {\n toString: () => actualName,\n dispose: () => this.disposeKeyframes(contentHash, registry),\n };\n }\n\n /**\n * Dispose keyframes\n */\n private disposeKeyframes(contentHash: string, registry: RootRegistry): void {\n const entry = registry.keyframesCache.get(contentHash);\n if (!entry) return;\n\n entry.refCount--;\n if (entry.refCount <= 0) {\n // Dispose immediately - keyframes are global and safe to clean up right away\n this.sheetManager.deleteKeyframes(registry, entry.info);\n registry.keyframesCache.delete(contentHash);\n\n // Clean up name-to-content mapping if this name was tracked\n // Find and remove the mapping for this content hash\n for (const [name, hash] of registry.keyframesNameToContent.entries()) {\n if (hash === contentHash) {\n registry.keyframesNameToContent.delete(name);\n break;\n }\n }\n\n // Update metrics\n if (registry.metrics) {\n registry.metrics.totalUnused++;\n registry.metrics.stylesCleanedUp++;\n }\n }\n }\n\n // =========================================================================\n // GC: touch-count-driven garbage collection with DOM safety guard\n // =========================================================================\n\n private static readonly TASTY_CLASS_RE = /^t[a-z0-9]+$/;\n\n /**\n * Record a render-time usage hit for one or more classNames.\n * Handles space-separated multi-chunk classNames.\n * When the global touch counter reaches `touchInterval`, schedules a GC\n * via `requestIdleCallback`.\n * No-op on the server.\n */\n touch(className: string, options?: { root?: Document | ShadowRoot }): void {\n if (typeof document === 'undefined') return;\n if (!this.config.gc) return;\n\n const root = options?.root || document;\n const registry = this.sheetManager.getRegistry(root);\n const now = Date.now();\n\n const parts =\n className.indexOf(' ') === -1 ? [className] : className.split(' ');\n\n for (const cls of parts) {\n if (!StyleInjector.TASTY_CLASS_RE.test(cls)) continue;\n if (!registry.rules.has(cls)) continue;\n\n const entry = registry.usageMap.get(cls);\n if (entry) {\n entry.lastTouchedAt = now;\n } else {\n registry.usageMap.set(cls, { lastTouchedAt: now });\n }\n registry.touchCount++;\n }\n\n const touchInterval = this.config.gc.touchInterval ?? 1000;\n if (registry.touchCount >= touchInterval) {\n registry.touchCount = 0;\n this.scheduleGC();\n }\n }\n\n /**\n * Schedule a GC via `requestIdleCallback` (or synchronously as fallback).\n * Runs GC on all active roots. Avoids double-scheduling via `pendingGCHandle`.\n */\n private scheduleGC(): void {\n if (this.pendingGCHandle != null) return;\n\n const runGC = () => {\n this.pendingGCHandle = null;\n this.sheetManager.pruneDisconnectedRoots();\n for (const root of this.sheetManager.getActiveRoots()) {\n this.gc({ root });\n }\n };\n\n if (typeof requestIdleCallback !== 'undefined') {\n this.pendingGCHandle = requestIdleCallback(() => runGC());\n } else {\n runGC();\n }\n }\n\n /**\n * Synchronous garbage collection.\n *\n * 1. Quick upper-bound check: skip if unused count can't exceed capacity.\n * 2. Scans the DOM for live tasty classNames (safety guard).\n * 3. With `force: true`: deletes all unused entries inline.\n * Without `force`: collects unused, sorts oldest-first, evicts over capacity.\n *\n * @returns Number of styles evicted.\n */\n gc(options?: GCOptions): number {\n if (typeof document === 'undefined') return 0;\n\n // Cancel any pending idle-scheduled GC to prevent double runs\n if (this.pendingGCHandle != null) {\n if (typeof cancelIdleCallback !== 'undefined') {\n cancelIdleCallback(this.pendingGCHandle);\n }\n this.pendingGCHandle = null;\n }\n\n const root = options?.root || document;\n const force = options?.force ?? false;\n const registry = this.sheetManager.getRegistry(root);\n const capacity = this.config.gc?.capacity ?? 1000;\n\n // Quick upper-bound check: count active refs to see if there could\n // possibly be enough unused entries to exceed capacity.\n // This avoids the expensive DOM scan when most styles are active.\n if (!force) {\n let activeCount = 0;\n for (const refCount of registry.refCounts.values()) {\n if (refCount > 0) activeCount++;\n }\n if (registry.usageMap.size - activeCount <= capacity) {\n return 0;\n }\n }\n\n // Scan DOM for live classes (classList handles SVG elements too)\n const liveClasses = new Set<string>();\n for (const el of root.querySelectorAll('[class]')) {\n for (const token of el.classList) {\n if (StyleInjector.TASTY_CLASS_RE.test(token)) {\n liveClasses.add(token);\n }\n }\n }\n\n let swept = 0;\n\n if (force) {\n for (const [className] of registry.usageMap) {\n if (liveClasses.has(className)) continue;\n if ((registry.refCounts.get(className) ?? 0) > 0) continue;\n registry.usageMap.delete(className);\n swept++;\n }\n } else {\n const unused: { className: string; lastTouchedAt: number }[] = [];\n for (const [className, usage] of registry.usageMap) {\n if (liveClasses.has(className)) continue;\n if ((registry.refCounts.get(className) ?? 0) > 0) continue;\n unused.push({ className, lastTouchedAt: usage.lastTouchedAt });\n }\n\n if (unused.length > capacity) {\n unused.sort((a, b) => a.lastTouchedAt - b.lastTouchedAt);\n const toEvict = unused.length - capacity;\n for (let i = 0; i < toEvict; i++) {\n registry.usageMap.delete(unused[i].className);\n swept++;\n }\n }\n }\n\n if (swept > 0) {\n this.sheetManager.forceCleanup(registry);\n }\n\n return swept;\n }\n\n /**\n * Destroy all resources for a root\n */\n destroy(root?: Document | ShadowRoot): void {\n const targetRoot = root || document;\n this.sheetManager.cleanup(targetRoot);\n\n // Clear pending GC when no active roots remain\n if (this.pendingGCHandle != null && !this.sheetManager.hasActiveRoots()) {\n if (typeof cancelIdleCallback !== 'undefined') {\n cancelIdleCallback(this.pendingGCHandle);\n }\n this.pendingGCHandle = null;\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -39,7 +39,6 @@ var SheetManager = class {
|
|
|
39
39
|
cacheKeyToClassName: /* @__PURE__ */ new Map(),
|
|
40
40
|
ruleTextSet: /* @__PURE__ */ new Set(),
|
|
41
41
|
metrics,
|
|
42
|
-
classCounter: 0,
|
|
43
42
|
keyframesCache: /* @__PURE__ */ new Map(),
|
|
44
43
|
keyframesNameToContent: /* @__PURE__ */ new Map(),
|
|
45
44
|
keyframesCounter: 0,
|
|
@@ -48,7 +47,10 @@ var SheetManager = class {
|
|
|
48
47
|
injectedCounterStyles: /* @__PURE__ */ new Set(),
|
|
49
48
|
globalRules: /* @__PURE__ */ new Map(),
|
|
50
49
|
propertyTypeResolver: new PropertyTypeResolver(),
|
|
51
|
-
usageMap: /* @__PURE__ */ new Map()
|
|
50
|
+
usageMap: /* @__PURE__ */ new Map(),
|
|
51
|
+
touchCount: 0,
|
|
52
|
+
serverClassSyncIndex: 0,
|
|
53
|
+
rscStylesScanned: false
|
|
52
54
|
};
|
|
53
55
|
this.rootRegistries.set(root, registry);
|
|
54
56
|
this.activeRoots.add(root);
|