@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { hydrateTastyClasses } from "./hydrate.js";
|
|
2
|
+
//#region src/ssr/astro-client.ts
|
|
3
|
+
/**
|
|
4
|
+
* Client-side cache hydration for Astro islands.
|
|
5
|
+
*
|
|
6
|
+
* Reads the class name list from `window.__TASTY__` (populated by
|
|
7
|
+
* inline scripts emitted during SSR) and pre-populates the injector
|
|
8
|
+
* so island hydration skips the style pipeline entirely.
|
|
9
|
+
*
|
|
10
|
+
* This module is browser-safe — it does NOT import node:async_hooks.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* - Automatically injected by tastyIntegration() via injectScript('before-hydration')
|
|
14
|
+
* - Can be imported manually: `import '@tenphi/tasty/ssr/astro-client'`
|
|
15
|
+
*/
|
|
16
|
+
if (typeof window !== "undefined") hydrateTastyClasses();
|
|
17
|
+
//#endregion
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=astro-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"astro-client.js","names":[],"sources":["../../src/ssr/astro-client.ts"],"sourcesContent":["/**\n * Client-side cache hydration for Astro islands.\n *\n * Reads the class name list from `window.__TASTY__` (populated by\n * inline scripts emitted during SSR) and pre-populates the injector\n * so island hydration skips the style pipeline entirely.\n *\n * This module is browser-safe — it does NOT import node:async_hooks.\n *\n * Usage:\n * - Automatically injected by tastyIntegration() via injectScript('before-hydration')\n * - Can be imported manually: `import '@tenphi/tasty/ssr/astro-client'`\n */\n\nimport { hydrateTastyClasses } from './hydrate';\n\nif (typeof window !== 'undefined') {\n hydrateTastyClasses();\n}\n"],"mappings":";;;;;;;;;;;;;;;AAgBA,IAAI,OAAO,WAAW,YACpB,sBAAqB"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/ssr/astro-middleware.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Astro middleware entrypoint for tastyIntegration().
|
|
4
|
+
*
|
|
5
|
+
* Referenced by the integration via addMiddleware(). Not intended
|
|
6
|
+
* as a public package export — use tastyMiddleware() directly if
|
|
7
|
+
* you need manual middleware composition.
|
|
8
|
+
*
|
|
9
|
+
* The transferCache setting is controlled by setMiddlewareTransferCache(),
|
|
10
|
+
* called by tastyIntegration() before middleware is loaded.
|
|
11
|
+
*/
|
|
12
|
+
declare const onRequest: (_context: unknown, next: () => Promise<Response>) => Promise<Response>;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { onRequest };
|
|
15
|
+
//# sourceMappingURL=astro-middleware.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { getMiddlewareTransferCache, tastyMiddleware } from "./astro.js";
|
|
2
|
+
//#region src/ssr/astro-middleware.ts
|
|
3
|
+
/**
|
|
4
|
+
* Astro middleware entrypoint for tastyIntegration().
|
|
5
|
+
*
|
|
6
|
+
* Referenced by the integration via addMiddleware(). Not intended
|
|
7
|
+
* as a public package export — use tastyMiddleware() directly if
|
|
8
|
+
* you need manual middleware composition.
|
|
9
|
+
*
|
|
10
|
+
* The transferCache setting is controlled by setMiddlewareTransferCache(),
|
|
11
|
+
* called by tastyIntegration() before middleware is loaded.
|
|
12
|
+
*/
|
|
13
|
+
const onRequest = tastyMiddleware({ get transferCache() {
|
|
14
|
+
return getMiddlewareTransferCache();
|
|
15
|
+
} });
|
|
16
|
+
//#endregion
|
|
17
|
+
export { onRequest };
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=astro-middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"astro-middleware.js","names":[],"sources":["../../src/ssr/astro-middleware.ts"],"sourcesContent":["/**\n * Astro middleware entrypoint for tastyIntegration().\n *\n * Referenced by the integration via addMiddleware(). Not intended\n * as a public package export — use tastyMiddleware() directly if\n * you need manual middleware composition.\n *\n * The transferCache setting is controlled by setMiddlewareTransferCache(),\n * called by tastyIntegration() before middleware is loaded.\n */\n\nimport { getMiddlewareTransferCache, tastyMiddleware } from './astro';\n\nexport const onRequest = tastyMiddleware({\n get transferCache() {\n return getMiddlewareTransferCache();\n },\n});\n"],"mappings":";;;;;;;;;;;;AAaA,MAAa,YAAY,gBAAgB,EACvC,IAAI,gBAAgB;AAClB,QAAO,4BAA4B;GAEtC,CAAC"}
|
package/dist/ssr/astro.d.ts
CHANGED
|
@@ -1,29 +1,108 @@
|
|
|
1
|
-
import { hydrateTastyCache } from "./hydrate.js";
|
|
2
|
-
|
|
3
1
|
//#region src/ssr/astro.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Astro integration for Tasty SSR.
|
|
4
|
+
*
|
|
5
|
+
* Provides:
|
|
6
|
+
* - tastyIntegration() — Astro Integration API (recommended)
|
|
7
|
+
* - tastyMiddleware() — manual middleware for advanced composition
|
|
8
|
+
*
|
|
9
|
+
* Import from '@tenphi/tasty/ssr/astro'.
|
|
10
|
+
*/
|
|
4
11
|
interface TastyMiddlewareOptions {
|
|
5
12
|
/**
|
|
6
|
-
* Whether to embed the
|
|
7
|
-
* Set to false to skip
|
|
13
|
+
* Whether to embed the class-list script for client hydration.
|
|
14
|
+
* Set to false to skip class transfer (e.g. for CSP restrictions).
|
|
15
|
+
* Without it, client components may re-inject CSS that already exists
|
|
16
|
+
* in server-rendered `<style>` tags. Default: true.
|
|
8
17
|
*/
|
|
9
18
|
transferCache?: boolean;
|
|
10
19
|
}
|
|
11
20
|
/**
|
|
12
21
|
* Create an Astro middleware that collects Tasty styles during SSR.
|
|
13
22
|
*
|
|
14
|
-
* All React components rendered during the request
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* injects the collected CSS into </head>.
|
|
23
|
+
* All React components rendered during the request will have their
|
|
24
|
+
* computeStyles() calls captured by the collector via AsyncLocalStorage.
|
|
25
|
+
* After rendering, the middleware injects the collected CSS into </head>.
|
|
18
26
|
*
|
|
19
|
-
* @example
|
|
27
|
+
* @example Manual middleware setup
|
|
20
28
|
* ```ts
|
|
21
29
|
* // src/middleware.ts
|
|
22
30
|
* import { tastyMiddleware } from '@tenphi/tasty/ssr/astro';
|
|
23
31
|
* export const onRequest = tastyMiddleware();
|
|
24
32
|
* ```
|
|
33
|
+
*
|
|
34
|
+
* @example Composing with other middleware
|
|
35
|
+
* ```ts
|
|
36
|
+
* // src/middleware.ts
|
|
37
|
+
* import { sequence } from 'astro:middleware';
|
|
38
|
+
* import { tastyMiddleware } from '@tenphi/tasty/ssr/astro';
|
|
39
|
+
*
|
|
40
|
+
* export const onRequest = sequence(
|
|
41
|
+
* tastyMiddleware(),
|
|
42
|
+
* myOtherMiddleware,
|
|
43
|
+
* );
|
|
44
|
+
* ```
|
|
25
45
|
*/
|
|
26
46
|
declare function tastyMiddleware(options?: TastyMiddlewareOptions): (_context: unknown, next: () => Promise<Response>) => Promise<Response>;
|
|
47
|
+
/** @internal */
|
|
48
|
+
declare function setMiddlewareTransferCache(value: boolean): void;
|
|
49
|
+
/** @internal */
|
|
50
|
+
declare function getMiddlewareTransferCache(): boolean;
|
|
51
|
+
interface TastyIntegrationOptions {
|
|
52
|
+
/**
|
|
53
|
+
* Enable island hydration support.
|
|
54
|
+
*
|
|
55
|
+
* When `true` (default): injects a client hydration script via
|
|
56
|
+
* `injectScript('before-hydration')` and sets `transferCache: true`
|
|
57
|
+
* on the middleware. Islands skip the style pipeline during hydration.
|
|
58
|
+
*
|
|
59
|
+
* When `false`: no client JS is shipped and `transferCache` is set
|
|
60
|
+
* to `false`. Use this for fully static sites without `client:*`
|
|
61
|
+
* directives.
|
|
62
|
+
*/
|
|
63
|
+
islands?: boolean;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Astro integration that automatically sets up Tasty SSR.
|
|
67
|
+
*
|
|
68
|
+
* Registers middleware for cross-component CSS deduplication and
|
|
69
|
+
* optionally injects a client hydration script for island support.
|
|
70
|
+
*
|
|
71
|
+
* @example Basic setup (with islands)
|
|
72
|
+
* ```ts
|
|
73
|
+
* // astro.config.mjs
|
|
74
|
+
* import { tastyIntegration } from '@tenphi/tasty/ssr/astro';
|
|
75
|
+
*
|
|
76
|
+
* export default defineConfig({
|
|
77
|
+
* integrations: [tastyIntegration()],
|
|
78
|
+
* });
|
|
79
|
+
* ```
|
|
80
|
+
*
|
|
81
|
+
* @example Static-only (no client JS)
|
|
82
|
+
* ```ts
|
|
83
|
+
* // astro.config.mjs
|
|
84
|
+
* import { tastyIntegration } from '@tenphi/tasty/ssr/astro';
|
|
85
|
+
*
|
|
86
|
+
* export default defineConfig({
|
|
87
|
+
* integrations: [tastyIntegration({ islands: false })],
|
|
88
|
+
* });
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
declare function tastyIntegration(options?: TastyIntegrationOptions): {
|
|
92
|
+
name: string;
|
|
93
|
+
hooks: {
|
|
94
|
+
'astro:config:setup': ({
|
|
95
|
+
addMiddleware,
|
|
96
|
+
injectScript
|
|
97
|
+
}: {
|
|
98
|
+
addMiddleware: (middleware: {
|
|
99
|
+
entrypoint: string | URL;
|
|
100
|
+
order: "pre" | "post";
|
|
101
|
+
}) => void;
|
|
102
|
+
injectScript: (stage: string, content: string) => void;
|
|
103
|
+
}) => void;
|
|
104
|
+
};
|
|
105
|
+
};
|
|
27
106
|
//#endregion
|
|
28
|
-
export { TastyMiddlewareOptions,
|
|
107
|
+
export { TastyIntegrationOptions, TastyMiddlewareOptions, getMiddlewareTransferCache, setMiddlewareTransferCache, tastyIntegration, tastyMiddleware };
|
|
29
108
|
//# sourceMappingURL=astro.d.ts.map
|
package/dist/ssr/astro.js
CHANGED
|
@@ -1,64 +1,149 @@
|
|
|
1
1
|
import { getConfig } from "../config.js";
|
|
2
|
-
import {
|
|
2
|
+
import { registerSSRCollectorGetterGlobal } from "./ssr-collector-ref.js";
|
|
3
3
|
import { ServerStyleCollector } from "./collector.js";
|
|
4
4
|
import { getSSRCollector, runWithCollector } from "./async-storage.js";
|
|
5
|
-
import { hydrateTastyCache } from "./hydrate.js";
|
|
6
5
|
//#region src/ssr/astro.ts
|
|
7
6
|
/**
|
|
8
7
|
* Astro integration for Tasty SSR.
|
|
9
8
|
*
|
|
10
|
-
* Provides
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* Provides:
|
|
10
|
+
* - tastyIntegration() — Astro Integration API (recommended)
|
|
11
|
+
* - tastyMiddleware() — manual middleware for advanced composition
|
|
13
12
|
*
|
|
14
13
|
* Import from '@tenphi/tasty/ssr/astro'.
|
|
15
14
|
*/
|
|
16
|
-
|
|
15
|
+
registerSSRCollectorGetterGlobal(getSSRCollector);
|
|
17
16
|
/**
|
|
18
17
|
* Create an Astro middleware that collects Tasty styles during SSR.
|
|
19
18
|
*
|
|
20
|
-
* All React components rendered during the request
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* injects the collected CSS into </head>.
|
|
19
|
+
* All React components rendered during the request will have their
|
|
20
|
+
* computeStyles() calls captured by the collector via AsyncLocalStorage.
|
|
21
|
+
* After rendering, the middleware injects the collected CSS into </head>.
|
|
24
22
|
*
|
|
25
|
-
* @example
|
|
23
|
+
* @example Manual middleware setup
|
|
26
24
|
* ```ts
|
|
27
25
|
* // src/middleware.ts
|
|
28
26
|
* import { tastyMiddleware } from '@tenphi/tasty/ssr/astro';
|
|
29
27
|
* export const onRequest = tastyMiddleware();
|
|
30
28
|
* ```
|
|
29
|
+
*
|
|
30
|
+
* @example Composing with other middleware
|
|
31
|
+
* ```ts
|
|
32
|
+
* // src/middleware.ts
|
|
33
|
+
* import { sequence } from 'astro:middleware';
|
|
34
|
+
* import { tastyMiddleware } from '@tenphi/tasty/ssr/astro';
|
|
35
|
+
*
|
|
36
|
+
* export const onRequest = sequence(
|
|
37
|
+
* tastyMiddleware(),
|
|
38
|
+
* myOtherMiddleware,
|
|
39
|
+
* );
|
|
40
|
+
* ```
|
|
31
41
|
*/
|
|
32
42
|
function tastyMiddleware(options) {
|
|
33
|
-
const { transferCache = true } = options ?? {};
|
|
34
43
|
return async (_context, next) => {
|
|
44
|
+
const transferCache = options?.transferCache ?? true;
|
|
35
45
|
const collector = new ServerStyleCollector();
|
|
36
|
-
const
|
|
46
|
+
const rendered = await runWithCollector(collector, async () => {
|
|
47
|
+
const response = await next();
|
|
48
|
+
const body = response.body;
|
|
49
|
+
if (!body) return {
|
|
50
|
+
html: null,
|
|
51
|
+
status: response.status,
|
|
52
|
+
headers: response.headers
|
|
53
|
+
};
|
|
54
|
+
const reader = body.pipeThrough(new TextDecoderStream()).getReader();
|
|
55
|
+
const parts = [];
|
|
56
|
+
for (;;) {
|
|
57
|
+
const { done, value } = await reader.read();
|
|
58
|
+
if (done) break;
|
|
59
|
+
parts.push(value);
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
html: parts.join(""),
|
|
63
|
+
status: response.status,
|
|
64
|
+
headers: response.headers
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
if (!rendered.html) return new Response(null, {
|
|
68
|
+
status: rendered.status,
|
|
69
|
+
headers: rendered.headers
|
|
70
|
+
});
|
|
71
|
+
let { html } = rendered;
|
|
37
72
|
const css = collector.getCSS();
|
|
38
|
-
if (!css) return
|
|
73
|
+
if (!css) return new Response(html, {
|
|
74
|
+
status: rendered.status,
|
|
75
|
+
headers: rendered.headers
|
|
76
|
+
});
|
|
39
77
|
const nonce = getConfig().nonce;
|
|
40
78
|
const nonceAttr = nonce ? ` nonce="${nonce}"` : "";
|
|
41
|
-
const html = await response.text();
|
|
42
79
|
const styleTag = `<style data-tasty-ssr${nonceAttr}>${css}</style>`;
|
|
43
80
|
let cacheTag = "";
|
|
44
81
|
if (transferCache) {
|
|
45
|
-
const
|
|
46
|
-
if (
|
|
82
|
+
const classNames = collector.getRenderedClassNames();
|
|
83
|
+
if (classNames.length > 0) cacheTag = `<script${nonceAttr}>(window.__TASTY__=window.__TASTY__||[]).push(${classNames.map((n) => `"${n}"`).join(",")})<\/script>`;
|
|
47
84
|
}
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
85
|
+
const injection = styleTag + cacheTag;
|
|
86
|
+
const idx = html.indexOf("</head>");
|
|
87
|
+
if (idx !== -1) html = html.slice(0, idx) + injection + html.slice(idx);
|
|
88
|
+
else html = injection + html;
|
|
89
|
+
const headers = new Headers(rendered.headers);
|
|
90
|
+
headers.delete("content-length");
|
|
91
|
+
return new Response(html, {
|
|
92
|
+
status: rendered.status,
|
|
93
|
+
headers
|
|
52
94
|
});
|
|
53
95
|
};
|
|
54
96
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
97
|
+
let _middlewareTransferCache = true;
|
|
98
|
+
/** @internal */
|
|
99
|
+
function setMiddlewareTransferCache(value) {
|
|
100
|
+
_middlewareTransferCache = value;
|
|
101
|
+
}
|
|
102
|
+
/** @internal */
|
|
103
|
+
function getMiddlewareTransferCache() {
|
|
104
|
+
return _middlewareTransferCache;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Astro integration that automatically sets up Tasty SSR.
|
|
108
|
+
*
|
|
109
|
+
* Registers middleware for cross-component CSS deduplication and
|
|
110
|
+
* optionally injects a client hydration script for island support.
|
|
111
|
+
*
|
|
112
|
+
* @example Basic setup (with islands)
|
|
113
|
+
* ```ts
|
|
114
|
+
* // astro.config.mjs
|
|
115
|
+
* import { tastyIntegration } from '@tenphi/tasty/ssr/astro';
|
|
116
|
+
*
|
|
117
|
+
* export default defineConfig({
|
|
118
|
+
* integrations: [tastyIntegration()],
|
|
119
|
+
* });
|
|
120
|
+
* ```
|
|
121
|
+
*
|
|
122
|
+
* @example Static-only (no client JS)
|
|
123
|
+
* ```ts
|
|
124
|
+
* // astro.config.mjs
|
|
125
|
+
* import { tastyIntegration } from '@tenphi/tasty/ssr/astro';
|
|
126
|
+
*
|
|
127
|
+
* export default defineConfig({
|
|
128
|
+
* integrations: [tastyIntegration({ islands: false })],
|
|
129
|
+
* });
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
function tastyIntegration(options) {
|
|
133
|
+
const { islands = true } = options ?? {};
|
|
134
|
+
setMiddlewareTransferCache(islands);
|
|
135
|
+
return {
|
|
136
|
+
name: "@tenphi/tasty",
|
|
137
|
+
hooks: { "astro:config:setup": ({ addMiddleware, injectScript }) => {
|
|
138
|
+
addMiddleware({
|
|
139
|
+
entrypoint: new URL("./astro-middleware.js", import.meta.url),
|
|
140
|
+
order: "pre"
|
|
141
|
+
});
|
|
142
|
+
if (islands) injectScript("before-hydration", `import "@tenphi/tasty/ssr/astro-client";`);
|
|
143
|
+
} }
|
|
144
|
+
};
|
|
60
145
|
}
|
|
61
146
|
//#endregion
|
|
62
|
-
export {
|
|
147
|
+
export { getMiddlewareTransferCache, setMiddlewareTransferCache, tastyIntegration, tastyMiddleware };
|
|
63
148
|
|
|
64
149
|
//# sourceMappingURL=astro.js.map
|
package/dist/ssr/astro.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"astro.js","names":[],"sources":["../../src/ssr/astro.ts"],"sourcesContent":["/**\n * Astro integration for Tasty SSR.\n *\n * Provides
|
|
1
|
+
{"version":3,"file":"astro.js","names":[],"sources":["../../src/ssr/astro.ts"],"sourcesContent":["/**\n * Astro integration for Tasty SSR.\n *\n * Provides:\n * - tastyIntegration() — Astro Integration API (recommended)\n * - tastyMiddleware() — manual middleware for advanced composition\n *\n * Import from '@tenphi/tasty/ssr/astro'.\n */\n\nimport { getConfig } from '../config';\nimport { getSSRCollector, runWithCollector } from './async-storage';\nimport { ServerStyleCollector } from './collector';\nimport { registerSSRCollectorGetterGlobal } from './ssr-collector-ref';\n\n// Wire up ALS-based collector discovery so computeStyles() can find\n// the collector set by tastyMiddleware's runWithCollector().\n// Uses globalThis so the getter is visible across Astro's separate\n// module graphs (middleware vs page components).\nregisterSSRCollectorGetterGlobal(getSSRCollector);\n\nexport interface TastyMiddlewareOptions {\n /**\n * Whether to embed the class-list script for client hydration.\n * Set to false to skip class transfer (e.g. for CSP restrictions).\n * Without it, client components may re-inject CSS that already exists\n * in server-rendered `<style>` tags. Default: true.\n */\n transferCache?: boolean;\n}\n\n/**\n * Create an Astro middleware that collects Tasty styles during SSR.\n *\n * All React components rendered during the request will have their\n * computeStyles() calls captured by the collector via AsyncLocalStorage.\n * After rendering, the middleware injects the collected CSS into </head>.\n *\n * @example Manual middleware setup\n * ```ts\n * // src/middleware.ts\n * import { tastyMiddleware } from '@tenphi/tasty/ssr/astro';\n * export const onRequest = tastyMiddleware();\n * ```\n *\n * @example Composing with other middleware\n * ```ts\n * // src/middleware.ts\n * import { sequence } from 'astro:middleware';\n * import { tastyMiddleware } from '@tenphi/tasty/ssr/astro';\n *\n * export const onRequest = sequence(\n * tastyMiddleware(),\n * myOtherMiddleware,\n * );\n * ```\n */\nexport function tastyMiddleware(options?: TastyMiddlewareOptions) {\n return async (\n _context: unknown,\n next: () => Promise<Response>,\n ): Promise<Response> => {\n const transferCache = options?.transferCache ?? true;\n const collector = new ServerStyleCollector();\n\n // Run the entire request — including body stream consumption — inside\n // the ALS context so that components rendering lazily during stream\n // reads can still find the collector via getSSRCollector().\n const rendered = await runWithCollector(collector, async () => {\n const response = await next();\n const body = response.body;\n if (!body) {\n return {\n html: null as string | null,\n status: response.status,\n headers: response.headers,\n };\n }\n\n const reader = body.pipeThrough(new TextDecoderStream()).getReader();\n const parts: string[] = [];\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n parts.push(value);\n }\n return {\n html: parts.join(''),\n status: response.status,\n headers: response.headers,\n };\n });\n\n if (!rendered.html) {\n return new Response(null, {\n status: rendered.status,\n headers: rendered.headers,\n });\n }\n\n let { html } = rendered;\n\n const css = collector.getCSS();\n if (!css) {\n return new Response(html, {\n status: rendered.status,\n headers: rendered.headers,\n });\n }\n\n const nonce = getConfig().nonce;\n const nonceAttr = nonce ? ` nonce=\"${nonce}\"` : '';\n const styleTag = `<style data-tasty-ssr${nonceAttr}>${css}</style>`;\n\n let cacheTag = '';\n if (transferCache) {\n const classNames = collector.getRenderedClassNames();\n if (classNames.length > 0) {\n const classListJSON = classNames.map((n) => `\"${n}\"`).join(',');\n cacheTag = `<script${nonceAttr}>(window.__TASTY__=window.__TASTY__||[]).push(${classListJSON})</script>`;\n }\n }\n\n const injection = styleTag + cacheTag;\n const idx = html.indexOf('</head>');\n if (idx !== -1) {\n html = html.slice(0, idx) + injection + html.slice(idx);\n } else {\n html = injection + html;\n }\n\n const headers = new Headers(rendered.headers);\n headers.delete('content-length');\n\n return new Response(html, {\n status: rendered.status,\n headers,\n });\n };\n}\n\n// ============================================================================\n// Module-level middleware config (set by tastyIntegration, read by\n// astro-middleware.ts via getter property)\n// ============================================================================\n\nlet _middlewareTransferCache = true;\n\n/** @internal */\nexport function setMiddlewareTransferCache(value: boolean): void {\n _middlewareTransferCache = value;\n}\n\n/** @internal */\nexport function getMiddlewareTransferCache(): boolean {\n return _middlewareTransferCache;\n}\n\n// ============================================================================\n// Astro Integration API\n// ============================================================================\n\nexport interface TastyIntegrationOptions {\n /**\n * Enable island hydration support.\n *\n * When `true` (default): injects a client hydration script via\n * `injectScript('before-hydration')` and sets `transferCache: true`\n * on the middleware. Islands skip the style pipeline during hydration.\n *\n * When `false`: no client JS is shipped and `transferCache` is set\n * to `false`. Use this for fully static sites without `client:*`\n * directives.\n */\n islands?: boolean;\n}\n\n/**\n * Astro integration that automatically sets up Tasty SSR.\n *\n * Registers middleware for cross-component CSS deduplication and\n * optionally injects a client hydration script for island support.\n *\n * @example Basic setup (with islands)\n * ```ts\n * // astro.config.mjs\n * import { tastyIntegration } from '@tenphi/tasty/ssr/astro';\n *\n * export default defineConfig({\n * integrations: [tastyIntegration()],\n * });\n * ```\n *\n * @example Static-only (no client JS)\n * ```ts\n * // astro.config.mjs\n * import { tastyIntegration } from '@tenphi/tasty/ssr/astro';\n *\n * export default defineConfig({\n * integrations: [tastyIntegration({ islands: false })],\n * });\n * ```\n */\nexport function tastyIntegration(options?: TastyIntegrationOptions) {\n const { islands = true } = options ?? {};\n\n setMiddlewareTransferCache(islands);\n\n return {\n name: '@tenphi/tasty',\n hooks: {\n 'astro:config:setup': ({\n addMiddleware,\n injectScript,\n }: {\n addMiddleware: (middleware: {\n entrypoint: string | URL;\n order: 'pre' | 'post';\n }) => void;\n injectScript: (stage: string, content: string) => void;\n }) => {\n addMiddleware({\n entrypoint: new URL('./astro-middleware.js', import.meta.url),\n order: 'pre',\n });\n\n if (islands) {\n injectScript(\n 'before-hydration',\n `import \"@tenphi/tasty/ssr/astro-client\";`,\n );\n }\n },\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;AAmBA,iCAAiC,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCjD,SAAgB,gBAAgB,SAAkC;AAChE,QAAO,OACL,UACA,SACsB;EACtB,MAAM,gBAAgB,SAAS,iBAAiB;EAChD,MAAM,YAAY,IAAI,sBAAsB;EAK5C,MAAM,WAAW,MAAM,iBAAiB,WAAW,YAAY;GAC7D,MAAM,WAAW,MAAM,MAAM;GAC7B,MAAM,OAAO,SAAS;AACtB,OAAI,CAAC,KACH,QAAO;IACL,MAAM;IACN,QAAQ,SAAS;IACjB,SAAS,SAAS;IACnB;GAGH,MAAM,SAAS,KAAK,YAAY,IAAI,mBAAmB,CAAC,CAAC,WAAW;GACpE,MAAM,QAAkB,EAAE;AAC1B,YAAS;IACP,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,MAAM;AAC3C,QAAI,KAAM;AACV,UAAM,KAAK,MAAM;;AAEnB,UAAO;IACL,MAAM,MAAM,KAAK,GAAG;IACpB,QAAQ,SAAS;IACjB,SAAS,SAAS;IACnB;IACD;AAEF,MAAI,CAAC,SAAS,KACZ,QAAO,IAAI,SAAS,MAAM;GACxB,QAAQ,SAAS;GACjB,SAAS,SAAS;GACnB,CAAC;EAGJ,IAAI,EAAE,SAAS;EAEf,MAAM,MAAM,UAAU,QAAQ;AAC9B,MAAI,CAAC,IACH,QAAO,IAAI,SAAS,MAAM;GACxB,QAAQ,SAAS;GACjB,SAAS,SAAS;GACnB,CAAC;EAGJ,MAAM,QAAQ,WAAW,CAAC;EAC1B,MAAM,YAAY,QAAQ,WAAW,MAAM,KAAK;EAChD,MAAM,WAAW,wBAAwB,UAAU,GAAG,IAAI;EAE1D,IAAI,WAAW;AACf,MAAI,eAAe;GACjB,MAAM,aAAa,UAAU,uBAAuB;AACpD,OAAI,WAAW,SAAS,EAEtB,YAAW,UAAU,UAAU,gDADT,WAAW,KAAK,MAAM,IAAI,EAAE,GAAG,CAAC,KAAK,IAAI,CAC8B;;EAIjG,MAAM,YAAY,WAAW;EAC7B,MAAM,MAAM,KAAK,QAAQ,UAAU;AACnC,MAAI,QAAQ,GACV,QAAO,KAAK,MAAM,GAAG,IAAI,GAAG,YAAY,KAAK,MAAM,IAAI;MAEvD,QAAO,YAAY;EAGrB,MAAM,UAAU,IAAI,QAAQ,SAAS,QAAQ;AAC7C,UAAQ,OAAO,iBAAiB;AAEhC,SAAO,IAAI,SAAS,MAAM;GACxB,QAAQ,SAAS;GACjB;GACD,CAAC;;;AASN,IAAI,2BAA2B;;AAG/B,SAAgB,2BAA2B,OAAsB;AAC/D,4BAA2B;;;AAI7B,SAAgB,6BAAsC;AACpD,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDT,SAAgB,iBAAiB,SAAmC;CAClE,MAAM,EAAE,UAAU,SAAS,WAAW,EAAE;AAExC,4BAA2B,QAAQ;AAEnC,QAAO;EACL,MAAM;EACN,OAAO,EACL,uBAAuB,EACrB,eACA,mBAOI;AACJ,iBAAc;IACZ,YAAY,IAAI,IAAI,yBAAyB,OAAO,KAAK,IAAI;IAC7D,OAAO;IACR,CAAC;AAEF,OAAI,QACF,cACE,oBACA,2CACD;KAGN;EACF"}
|
|
@@ -8,25 +8,35 @@ import { AsyncLocalStorage } from "node:async_hooks";
|
|
|
8
8
|
* The middleware calls runWithCollector() around the render, and
|
|
9
9
|
* useStyles() calls getSSRCollector() to find it.
|
|
10
10
|
*
|
|
11
|
+
* Uses globalThis to ensure the AsyncLocalStorage instance is shared
|
|
12
|
+
* across module instances — frameworks like Astro may load middleware
|
|
13
|
+
* and page components from separate module graphs.
|
|
14
|
+
*
|
|
11
15
|
* This module imports from 'node:async_hooks' — it must be excluded
|
|
12
16
|
* from client bundles via the build configuration.
|
|
13
17
|
*/
|
|
14
|
-
const
|
|
18
|
+
const ALS_KEY = "__tasty_ssr_als__";
|
|
19
|
+
function getSharedStorage() {
|
|
20
|
+
const g = globalThis;
|
|
21
|
+
if (!g[ALS_KEY]) g[ALS_KEY] = new AsyncLocalStorage();
|
|
22
|
+
return g[ALS_KEY];
|
|
23
|
+
}
|
|
15
24
|
/**
|
|
16
25
|
* Run a function with a ServerStyleCollector bound to the current
|
|
17
26
|
* async context. All useStyles() calls within `fn` (and any async
|
|
18
27
|
* continuations) will find this collector via getSSRCollector().
|
|
19
28
|
*/
|
|
20
29
|
function runWithCollector(collector, fn) {
|
|
21
|
-
return
|
|
30
|
+
return getSharedStorage().run(collector, fn);
|
|
22
31
|
}
|
|
23
32
|
/**
|
|
24
33
|
* Retrieve the ServerStyleCollector bound to the current async context.
|
|
25
34
|
* Returns null when called outside of runWithCollector() or on the client.
|
|
26
35
|
*/
|
|
27
36
|
function getSSRCollector() {
|
|
28
|
-
|
|
29
|
-
|
|
37
|
+
const storage = getSharedStorage();
|
|
38
|
+
if (typeof storage?.getStore !== "function") return null;
|
|
39
|
+
return storage.getStore() ?? null;
|
|
30
40
|
}
|
|
31
41
|
//#endregion
|
|
32
42
|
export { getSSRCollector, runWithCollector };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"async-storage.js","names":[],"sources":["../../src/ssr/async-storage.ts"],"sourcesContent":["/**\n * AsyncLocalStorage integration for SSR collector discovery.\n *\n * Used by Astro middleware and generic framework integrations where\n * the library cannot wrap the React tree with a context provider.\n * The middleware calls runWithCollector() around the render, and\n * useStyles() calls getSSRCollector() to find it.\n *\n * This module imports from 'node:async_hooks' — it must be excluded\n * from client bundles via the build configuration.\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\n\nimport type { ServerStyleCollector } from './collector';\n\nconst
|
|
1
|
+
{"version":3,"file":"async-storage.js","names":[],"sources":["../../src/ssr/async-storage.ts"],"sourcesContent":["/**\n * AsyncLocalStorage integration for SSR collector discovery.\n *\n * Used by Astro middleware and generic framework integrations where\n * the library cannot wrap the React tree with a context provider.\n * The middleware calls runWithCollector() around the render, and\n * useStyles() calls getSSRCollector() to find it.\n *\n * Uses globalThis to ensure the AsyncLocalStorage instance is shared\n * across module instances — frameworks like Astro may load middleware\n * and page components from separate module graphs.\n *\n * This module imports from 'node:async_hooks' — it must be excluded\n * from client bundles via the build configuration.\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\n\nimport type { ServerStyleCollector } from './collector';\n\nconst ALS_KEY = '__tasty_ssr_als__';\n\nfunction getSharedStorage(): AsyncLocalStorage<ServerStyleCollector> {\n const g = globalThis as Record<string, unknown>;\n if (!g[ALS_KEY]) {\n g[ALS_KEY] = new AsyncLocalStorage<ServerStyleCollector>();\n }\n return g[ALS_KEY] as AsyncLocalStorage<ServerStyleCollector>;\n}\n\n/**\n * Run a function with a ServerStyleCollector bound to the current\n * async context. All useStyles() calls within `fn` (and any async\n * continuations) will find this collector via getSSRCollector().\n */\nexport function runWithCollector<T>(\n collector: ServerStyleCollector,\n fn: () => T,\n): T {\n return getSharedStorage().run(collector, fn);\n}\n\n/**\n * Retrieve the ServerStyleCollector bound to the current async context.\n * Returns null when called outside of runWithCollector() or on the client.\n */\nexport function getSSRCollector(): ServerStyleCollector | null {\n const storage = getSharedStorage();\n if (typeof storage?.getStore !== 'function') return null;\n return storage.getStore() ?? null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAoBA,MAAM,UAAU;AAEhB,SAAS,mBAA4D;CACnE,MAAM,IAAI;AACV,KAAI,CAAC,EAAE,SACL,GAAE,WAAW,IAAI,mBAAyC;AAE5D,QAAO,EAAE;;;;;;;AAQX,SAAgB,iBACd,WACA,IACG;AACH,QAAO,kBAAkB,CAAC,IAAI,WAAW,GAAG;;;;;;AAO9C,SAAgB,kBAA+C;CAC7D,MAAM,UAAU,kBAAkB;AAClC,KAAI,OAAO,SAAS,aAAa,WAAY,QAAO;AACpD,QAAO,QAAQ,UAAU,IAAI"}
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
import { parsePropertyToken } from "../properties/index.js";
|
|
2
2
|
import { PropertyTypeResolver } from "../properties/property-type-resolver.js";
|
|
3
|
+
import { pushRSCCSS } from "../rsc-cache.js";
|
|
3
4
|
import { formatPropertyCSS } from "./format-property.js";
|
|
4
5
|
//#region src/ssr/collect-auto-properties.ts
|
|
5
6
|
/**
|
|
6
|
-
* Scan rendered rules for custom
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* @param rules - Rendered style rules containing CSS declarations
|
|
10
|
-
* @param collector - SSR collector to emit @property CSS into
|
|
11
|
-
* @param styles - Original styles object (used to skip explicit @properties)
|
|
7
|
+
* Scan rendered rules for auto-inferable custom properties and emit
|
|
8
|
+
* @property CSS via the provided callback.
|
|
12
9
|
*/
|
|
13
|
-
function
|
|
10
|
+
function scanAndEmitAutoProperties(rules, styles, emit) {
|
|
14
11
|
const registered = /* @__PURE__ */ new Set();
|
|
15
12
|
if (styles) {
|
|
16
13
|
const localProps = styles["@properties"];
|
|
@@ -29,11 +26,33 @@ function collectAutoInferredProperties(rules, collector, styles) {
|
|
|
29
26
|
inherits: true,
|
|
30
27
|
initialValue
|
|
31
28
|
});
|
|
32
|
-
if (css)
|
|
29
|
+
if (css) emit(name, css);
|
|
33
30
|
});
|
|
34
31
|
}
|
|
35
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Scan rendered rules for custom property declarations and collect
|
|
35
|
+
* auto-inferred @property rules via the SSR collector.
|
|
36
|
+
*
|
|
37
|
+
* @param rules - Rendered style rules containing CSS declarations
|
|
38
|
+
* @param collector - SSR collector to emit @property CSS into
|
|
39
|
+
* @param styles - Original styles object (used to skip explicit @properties)
|
|
40
|
+
*/
|
|
41
|
+
function collectAutoInferredProperties(rules, collector, styles) {
|
|
42
|
+
scanAndEmitAutoProperties(rules, styles, (name, css) => {
|
|
43
|
+
collector.collectProperty(`__auto:${name}`, css);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* RSC variant: scan rendered rules and push auto-inferred @property CSS
|
|
48
|
+
* into the RSC pending buffer.
|
|
49
|
+
*/
|
|
50
|
+
function collectAutoInferredPropertiesRSC(rules, rscCache, styles) {
|
|
51
|
+
scanAndEmitAutoProperties(rules, styles, (name, css) => {
|
|
52
|
+
pushRSCCSS(rscCache, `__auto:${name}`, css);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
36
55
|
//#endregion
|
|
37
|
-
export { collectAutoInferredProperties };
|
|
56
|
+
export { collectAutoInferredProperties, collectAutoInferredPropertiesRSC };
|
|
38
57
|
|
|
39
58
|
//# sourceMappingURL=collect-auto-properties.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collect-auto-properties.js","names":[],"sources":["../../src/ssr/collect-auto-properties.ts"],"sourcesContent":["/**\n * SSR auto-property inference.\n *\n * Scans rendered CSS declarations for custom properties whose types\n * can be inferred from their values (e.g. `--angle: 30deg` → `<angle>`).\n * Mirrors the client-side auto-inference in StyleInjector.inject().\n */\n\nimport type { StyleResult } from '../pipeline';\nimport { parsePropertyToken } from '../properties';\nimport { PropertyTypeResolver } from '../properties/property-type-resolver';\nimport type { Styles } from '../styles/types';\n\nimport type { ServerStyleCollector } from './collector';\nimport { formatPropertyCSS } from './format-property';\n\n/**\n * Scan rendered rules for custom
|
|
1
|
+
{"version":3,"file":"collect-auto-properties.js","names":[],"sources":["../../src/ssr/collect-auto-properties.ts"],"sourcesContent":["/**\n * SSR / RSC auto-property inference.\n *\n * Scans rendered CSS declarations for custom properties whose types\n * can be inferred from their values (e.g. `--angle: 30deg` → `<angle>`).\n * Mirrors the client-side auto-inference in StyleInjector.inject().\n */\n\nimport type { StyleResult } from '../pipeline';\nimport { parsePropertyToken } from '../properties';\nimport { PropertyTypeResolver } from '../properties/property-type-resolver';\nimport type { RSCStyleCache } from '../rsc-cache';\nimport { pushRSCCSS } from '../rsc-cache';\nimport type { Styles } from '../styles/types';\n\nimport type { ServerStyleCollector } from './collector';\nimport { formatPropertyCSS } from './format-property';\n\n/**\n * Scan rendered rules for auto-inferable custom properties and emit\n * @property CSS via the provided callback.\n */\nfunction scanAndEmitAutoProperties(\n rules: StyleResult[],\n styles: Styles | undefined,\n emit: (name: string, css: string) => void,\n): void {\n const registered = new Set<string>();\n\n if (styles) {\n const localProps = styles['@properties'];\n if (localProps && typeof localProps === 'object') {\n for (const token of Object.keys(localProps as Record<string, unknown>)) {\n const parsed = parsePropertyToken(token);\n if (parsed.isValid) {\n registered.add(parsed.cssName);\n }\n }\n }\n }\n\n const resolver = new PropertyTypeResolver();\n\n for (const rule of rules) {\n if (!rule.declarations) continue;\n resolver.scanDeclarations(\n rule.declarations,\n (name) => registered.has(name),\n (name, syntax, initialValue) => {\n registered.add(name);\n const css = formatPropertyCSS(name, {\n syntax,\n inherits: true,\n initialValue,\n });\n if (css) {\n emit(name, css);\n }\n },\n );\n }\n}\n\n/**\n * Scan rendered rules for custom property declarations and collect\n * auto-inferred @property rules via the SSR collector.\n *\n * @param rules - Rendered style rules containing CSS declarations\n * @param collector - SSR collector to emit @property CSS into\n * @param styles - Original styles object (used to skip explicit @properties)\n */\nexport function collectAutoInferredProperties(\n rules: StyleResult[],\n collector: ServerStyleCollector,\n styles?: Styles,\n): void {\n scanAndEmitAutoProperties(rules, styles, (name, css) => {\n collector.collectProperty(`__auto:${name}`, css);\n });\n}\n\n/**\n * RSC variant: scan rendered rules and push auto-inferred @property CSS\n * into the RSC pending buffer.\n */\nexport function collectAutoInferredPropertiesRSC(\n rules: StyleResult[],\n rscCache: RSCStyleCache,\n styles?: Styles,\n): void {\n scanAndEmitAutoProperties(rules, styles, (name, css) => {\n pushRSCCSS(rscCache, `__auto:${name}`, css);\n });\n}\n"],"mappings":";;;;;;;;;AAsBA,SAAS,0BACP,OACA,QACA,MACM;CACN,MAAM,6BAAa,IAAI,KAAa;AAEpC,KAAI,QAAQ;EACV,MAAM,aAAa,OAAO;AAC1B,MAAI,cAAc,OAAO,eAAe,SACtC,MAAK,MAAM,SAAS,OAAO,KAAK,WAAsC,EAAE;GACtE,MAAM,SAAS,mBAAmB,MAAM;AACxC,OAAI,OAAO,QACT,YAAW,IAAI,OAAO,QAAQ;;;CAMtC,MAAM,WAAW,IAAI,sBAAsB;AAE3C,MAAK,MAAM,QAAQ,OAAO;AACxB,MAAI,CAAC,KAAK,aAAc;AACxB,WAAS,iBACP,KAAK,eACJ,SAAS,WAAW,IAAI,KAAK,GAC7B,MAAM,QAAQ,iBAAiB;AAC9B,cAAW,IAAI,KAAK;GACpB,MAAM,MAAM,kBAAkB,MAAM;IAClC;IACA,UAAU;IACV;IACD,CAAC;AACF,OAAI,IACF,MAAK,MAAM,IAAI;IAGpB;;;;;;;;;;;AAYL,SAAgB,8BACd,OACA,WACA,QACM;AACN,2BAA0B,OAAO,SAAS,MAAM,QAAQ;AACtD,YAAU,gBAAgB,UAAU,QAAQ,IAAI;GAChD;;;;;;AAOJ,SAAgB,iCACd,OACA,UACA,QACM;AACN,2BAA0B,OAAO,SAAS,MAAM,QAAQ;AACtD,aAAW,UAAU,UAAU,QAAQ,IAAI;GAC3C"}
|
package/dist/ssr/collector.d.ts
CHANGED
|
@@ -1,19 +1,9 @@
|
|
|
1
1
|
import { StyleResult } from "../pipeline/index.js";
|
|
2
2
|
|
|
3
3
|
//#region src/ssr/collector.d.ts
|
|
4
|
-
/**
|
|
5
|
-
* Cache state serialized to the client for hydration.
|
|
6
|
-
*/
|
|
7
|
-
interface SSRCacheState {
|
|
8
|
-
/** cacheKey → className map, to pre-populate the client registry */
|
|
9
|
-
entries: Record<string, string>;
|
|
10
|
-
/** Counter value so client allocations don't collide with server ones */
|
|
11
|
-
classCounter: number;
|
|
12
|
-
}
|
|
13
4
|
declare class ServerStyleCollector {
|
|
14
5
|
private chunks;
|
|
15
6
|
private cacheKeyToClassName;
|
|
16
|
-
private classCounter;
|
|
17
7
|
private flushedKeys;
|
|
18
8
|
private propertyRules;
|
|
19
9
|
private flushedPropertyKeys;
|
|
@@ -92,11 +82,13 @@ declare class ServerStyleCollector {
|
|
|
92
82
|
* Used for streaming SSR (renderToPipeableStream + useServerInsertedHTML).
|
|
93
83
|
*/
|
|
94
84
|
flushCSS(): string;
|
|
85
|
+
private flushedClassNames;
|
|
95
86
|
/**
|
|
96
|
-
*
|
|
87
|
+
* Return class names rendered since the last call (for streaming).
|
|
88
|
+
* Used to emit lightweight class-list scripts for client hydration.
|
|
97
89
|
*/
|
|
98
|
-
|
|
90
|
+
getRenderedClassNames(): string[];
|
|
99
91
|
}
|
|
100
92
|
//#endregion
|
|
101
|
-
export {
|
|
93
|
+
export { ServerStyleCollector };
|
|
102
94
|
//# sourceMappingURL=collector.d.ts.map
|