@tenphi/tasty 2.6.5 → 2.7.0
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/dist/{collector-c00_hT9R.js → collector-BWvvN7_y.js} +3 -3
- package/dist/{collector-c00_hT9R.js.map → collector-BWvvN7_y.js.map} +1 -1
- package/dist/{config-IzenlK2R.js → config-DF2QZQEW.js} +144 -32
- package/dist/{config-IzenlK2R.js.map → config-DF2QZQEW.js.map} +1 -1
- package/dist/core/index.js +5 -5
- package/dist/{core-J9U8fXzr.js → core-BbdGIKAK.js} +5 -5
- package/dist/{core-J9U8fXzr.js.map → core-BbdGIKAK.js.map} +1 -1
- package/dist/{css-writer-CCyaR6ZM.js → css-writer-Bh05D6KI.js} +3 -3
- package/dist/{css-writer-CCyaR6ZM.js.map → css-writer-Bh05D6KI.js.map} +1 -1
- package/dist/{format-rules-CCb7qNPt.js → format-rules-DCI2lomx.js} +2 -2
- package/dist/{format-rules-CCb7qNPt.js.map → format-rules-DCI2lomx.js.map} +1 -1
- package/dist/{hydrate-DEsdmcdy.js → hydrate-DsFfFPVK.js} +2 -2
- package/dist/{hydrate-DEsdmcdy.js.map → hydrate-DsFfFPVK.js.map} +1 -1
- package/dist/index.js +6 -6
- package/dist/{keyframes-DxAp6xwG.js → keyframes-Dg95rDpN.js} +2 -2
- package/dist/{keyframes-DxAp6xwG.js.map → keyframes-Dg95rDpN.js.map} +1 -1
- package/dist/{merge-styles-Ugifi570.js → merge-styles-Bnn6j_SA.js} +2 -2
- package/dist/{merge-styles-Ugifi570.js.map → merge-styles-Bnn6j_SA.js.map} +1 -1
- package/dist/{resolve-recipes-DEmQhiop.js → resolve-recipes-CBQaQ3tD.js} +3 -3
- package/dist/{resolve-recipes-DEmQhiop.js.map → resolve-recipes-CBQaQ3tD.js.map} +1 -1
- package/dist/ssr/astro-client.js +1 -1
- package/dist/ssr/astro.js +3 -3
- package/dist/ssr/index.js +3 -3
- package/dist/ssr/next.js +4 -4
- package/dist/static/index.js +1 -1
- package/dist/zero/babel.js +4 -4
- package/dist/zero/index.js +1 -1
- package/docs/dsl.md +109 -0
- package/docs/pipeline.md +40 -2
- package/package.json +5 -5
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { F as fontFaceContentHash, I as formatFontFaceRule, M as formatCounterStyleRule, S as renderStyles, a as getGlobalCounterStyle, d as getNamePrefix, dt as makeCounterStyleName, ft as makeKeyframeName, gt as hashString, i as getGlobalConfigTokens, mt as validateNamePrefix, o as getGlobalFontFace, r as getEffectiveProperties, u as getGlobalStyles, ut as makeClassName } from "./config-
|
|
2
|
-
import { n as formatPropertyCSS, t as formatRules } from "./format-rules-
|
|
1
|
+
import { F as fontFaceContentHash, I as formatFontFaceRule, M as formatCounterStyleRule, S as renderStyles, a as getGlobalCounterStyle, d as getNamePrefix, dt as makeCounterStyleName, ft as makeKeyframeName, gt as hashString, i as getGlobalConfigTokens, mt as validateNamePrefix, o as getGlobalFontFace, r as getEffectiveProperties, u as getGlobalStyles, ut as makeClassName } from "./config-DF2QZQEW.js";
|
|
2
|
+
import { n as formatPropertyCSS, t as formatRules } from "./format-rules-DCI2lomx.js";
|
|
3
3
|
import { t as formatGlobalRules } from "./format-global-rules-Dbc_1tc3.js";
|
|
4
4
|
//#region src/ssr/collector.ts
|
|
5
5
|
/**
|
|
@@ -240,4 +240,4 @@ var ServerStyleCollector = class {
|
|
|
240
240
|
//#endregion
|
|
241
241
|
export { ServerStyleCollector as t };
|
|
242
242
|
|
|
243
|
-
//# sourceMappingURL=collector-
|
|
243
|
+
//# sourceMappingURL=collector-BWvvN7_y.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collector-c00_hT9R.js","names":[],"sources":["../src/ssr/collector.ts"],"sourcesContent":["/**\n * ServerStyleCollector — server-safe style collector for SSR.\n *\n * Accumulates CSS rules and cache metadata during server rendering.\n * This is the server-side counterpart to StyleInjector: it allocates\n * hash-based class names using the configured `namePrefix` (defaults\n * to `'t'`), formats CSS rules into text, and tracks rendered class\n * names for lightweight client transfer.\n *\n * One instance is created per HTTP request. Concurrent requests\n * each get their own collector (via AsyncLocalStorage or React context).\n */\n\nimport {\n getEffectiveProperties,\n getGlobalStyles,\n getGlobalCounterStyle,\n getGlobalFontFace,\n getGlobalConfigTokens,\n getNamePrefix,\n} from '../config';\nimport { formatCounterStyleRule } from '../counter-style';\nimport { fontFaceContentHash, formatFontFaceRule } from '../font-face';\nimport { renderStyles } from '../pipeline';\nimport type { StyleResult } from '../pipeline';\nimport { hashString } from '../utils/hash';\nimport {\n makeClassName,\n makeCounterStyleName,\n makeKeyframeName,\n validateNamePrefix,\n} from '../utils/name-prefix';\nimport { formatPropertyCSS } from './format-property';\nimport { formatGlobalRules } from './format-global-rules';\nimport { formatRules } from './format-rules';\n\nexport class ServerStyleCollector {\n private chunks = new Map<string, string>();\n private cacheKeyToClassName = new Map<string, string>();\n private flushedKeys = new Set<string>();\n private propertyRules = new Map<string, string>();\n private flushedPropertyKeys = new Set<string>();\n private keyframeRules = new Map<string, string>();\n private flushedKeyframeKeys = new Set<string>();\n private globalStyles = new Map<string, string>();\n private flushedGlobalKeys = new Set<string>();\n private rawCSS = new Map<string, string>();\n private flushedRawKeys = new Set<string>();\n private fontFaceRules = new Map<string, string>();\n private flushedFontFaceKeys = new Set<string>();\n private counterStyleRules = new Map<string, string>();\n private flushedCounterStyleKeys = new Set<string>();\n private keyframesCounter = 0;\n private counterStyleCounter = 0;\n private internalsCollected = false;\n private namePrefix: string;\n\n /**\n * @param namePrefix - Optional override for the configured prefix.\n * Defaults to the value from `configure({ namePrefix })` (or `'t'`).\n * Pass an explicit prefix when constructing a collector outside the\n * normal configure() lifecycle (e.g. in tests). Validated eagerly\n * so misconfiguration fails before any CSS is collected.\n */\n constructor(namePrefix?: string) {\n if (namePrefix !== undefined) {\n validateNamePrefix(namePrefix);\n }\n this.namePrefix = namePrefix ?? getNamePrefix();\n }\n\n private generateClassName(cacheKey: string): string {\n return makeClassName(this.namePrefix, hashString(cacheKey));\n }\n\n /**\n * Collect internal @property rules and :root token defaults.\n * Mirrors markStylesGenerated() from the client-side injector.\n * Called automatically on first chunk collection; idempotent.\n *\n * Internals are always emitted here — the RSC path deliberately\n * defers to SSR so that tokens appear exactly once per page in\n * <style data-tasty-ssr> (avoiding duplication of large token sets).\n */\n collectInternals(): void {\n if (this.internalsCollected) return;\n this.internalsCollected = true;\n\n for (const [token, definition] of Object.entries(\n getEffectiveProperties(),\n )) {\n const css = formatPropertyCSS(token, definition);\n if (css) {\n this.collectProperty(`__prop:${token}`, css);\n }\n }\n\n const tokenStyles = getGlobalConfigTokens();\n if (tokenStyles && Object.keys(tokenStyles).length > 0) {\n const tokenRules = renderStyles(tokenStyles, ':root') as StyleResult[];\n if (tokenRules.length > 0) {\n const css = formatGlobalRules(tokenRules);\n if (css) {\n this.collectGlobalStyles('__global:tokens', css);\n }\n }\n }\n\n const globalFF = getGlobalFontFace();\n if (globalFF) {\n for (const [family, input] of Object.entries(globalFF)) {\n const descriptors = Array.isArray(input) ? input : [input];\n for (const desc of descriptors) {\n const hash = fontFaceContentHash(family, desc);\n const css = formatFontFaceRule(family, desc);\n this.collectFontFace(hash, css);\n }\n }\n }\n\n const globalCS = getGlobalCounterStyle();\n if (globalCS) {\n for (const [name, descriptors] of Object.entries(globalCS)) {\n const css = formatCounterStyleRule(name, descriptors);\n this.collectCounterStyle(name, css);\n }\n }\n\n const globalStyles = getGlobalStyles();\n if (globalStyles) {\n for (const [selector, styles] of Object.entries(globalStyles)) {\n if (Object.keys(styles).length > 0) {\n const rules = renderStyles(styles, selector) as StyleResult[];\n if (rules.length > 0) {\n const css = formatGlobalRules(rules);\n if (css) {\n this.collectGlobalStyles(`__global:styles:${selector}`, css);\n }\n }\n }\n }\n }\n }\n\n /**\n * Allocate a className for a cache key, server-side.\n * Mirrors StyleInjector.allocateClassName but without DOM access.\n */\n allocateClassName(cacheKey: string): {\n className: string;\n isNewAllocation: boolean;\n } {\n const existing = this.cacheKeyToClassName.get(cacheKey);\n if (existing) {\n return { className: existing, isNewAllocation: false };\n }\n\n const className = this.generateClassName(cacheKey);\n this.cacheKeyToClassName.set(cacheKey, className);\n\n return { className, isNewAllocation: true };\n }\n\n /**\n * Record CSS rules for a chunk.\n * Called by useStyles during server render.\n */\n collectChunk(\n cacheKey: string,\n className: string,\n rules: StyleResult[],\n ): void {\n if (this.chunks.has(cacheKey)) return;\n const css = formatRules(rules, className);\n if (css) {\n this.chunks.set(cacheKey, css);\n }\n }\n\n /**\n * Record a @property rule. Deduplicated by name.\n */\n collectProperty(name: string, css: string): void {\n if (!this.propertyRules.has(name)) {\n this.propertyRules.set(name, css);\n }\n }\n\n /**\n * Record a @keyframes rule. Deduplicated by name.\n */\n collectKeyframes(name: string, css: string): void {\n if (!this.keyframeRules.has(name)) {\n this.keyframeRules.set(name, css);\n }\n }\n\n /**\n * Allocate a keyframe name for SSR. Uses provided name or generates one.\n */\n allocateKeyframeName(providedName?: string): string {\n return (\n providedName ??\n makeKeyframeName(this.namePrefix, String(this.keyframesCounter++))\n );\n }\n\n /**\n * Record a @font-face rule. Deduplicated by key (content hash).\n */\n collectFontFace(key: string, css: string): void {\n if (!this.fontFaceRules.has(key)) {\n this.fontFaceRules.set(key, css);\n }\n }\n\n /**\n * Record a @counter-style rule. Deduplicated by name.\n */\n collectCounterStyle(name: string, css: string): void {\n if (!this.counterStyleRules.has(name)) {\n this.counterStyleRules.set(name, css);\n }\n }\n\n /**\n * Allocate a counter-style name for SSR. Uses provided name or generates one.\n */\n allocateCounterStyleName(providedName?: string): string {\n return (\n providedName ??\n makeCounterStyleName(this.namePrefix, String(this.counterStyleCounter++))\n );\n }\n\n /**\n * Record global styles (from useGlobalStyles). Deduplicated by key.\n */\n collectGlobalStyles(key: string, css: string): void {\n if (!this.globalStyles.has(key)) {\n this.globalStyles.set(key, css);\n }\n }\n\n /**\n * Record raw CSS text (from useRawCSS). Deduplicated by key.\n */\n collectRawCSS(key: string, css: string): void {\n if (!this.rawCSS.has(key)) {\n this.rawCSS.set(key, css);\n }\n }\n\n /**\n * Extract all CSS collected so far as a single string.\n * Includes @property and @keyframes rules.\n * Used for non-streaming SSR (renderToString).\n */\n getCSS(): string {\n const parts: string[] = [];\n\n for (const css of this.propertyRules.values()) {\n parts.push(css);\n }\n\n for (const css of this.fontFaceRules.values()) {\n parts.push(css);\n }\n\n for (const css of this.counterStyleRules.values()) {\n parts.push(css);\n }\n\n for (const css of this.rawCSS.values()) {\n parts.push(css);\n }\n\n for (const css of this.globalStyles.values()) {\n parts.push(css);\n }\n\n for (const css of this.chunks.values()) {\n parts.push(css);\n }\n\n for (const css of this.keyframeRules.values()) {\n parts.push(css);\n }\n\n return parts.join('\\n');\n }\n\n /**\n * Flush only newly collected CSS since the last flush.\n * Used for streaming SSR (renderToPipeableStream + useServerInsertedHTML).\n */\n flushCSS(): string {\n const parts: string[] = [];\n\n for (const [name, css] of this.propertyRules) {\n if (!this.flushedPropertyKeys.has(name)) {\n parts.push(css);\n this.flushedPropertyKeys.add(name);\n }\n }\n\n for (const [key, css] of this.fontFaceRules) {\n if (!this.flushedFontFaceKeys.has(key)) {\n parts.push(css);\n this.flushedFontFaceKeys.add(key);\n }\n }\n\n for (const [key, css] of this.counterStyleRules) {\n if (!this.flushedCounterStyleKeys.has(key)) {\n parts.push(css);\n this.flushedCounterStyleKeys.add(key);\n }\n }\n\n for (const [key, css] of this.rawCSS) {\n if (!this.flushedRawKeys.has(key)) {\n parts.push(css);\n this.flushedRawKeys.add(key);\n }\n }\n\n for (const [key, css] of this.globalStyles) {\n if (!this.flushedGlobalKeys.has(key)) {\n parts.push(css);\n this.flushedGlobalKeys.add(key);\n }\n }\n\n for (const [key, css] of this.chunks) {\n if (!this.flushedKeys.has(key)) {\n parts.push(css);\n this.flushedKeys.add(key);\n }\n }\n\n for (const [name, css] of this.keyframeRules) {\n if (!this.flushedKeyframeKeys.has(name)) {\n parts.push(css);\n this.flushedKeyframeKeys.add(name);\n }\n }\n\n return parts.join('\\n');\n }\n\n private flushedClassNames = new Set<string>();\n\n /**\n * Return class names rendered since the last call (for streaming).\n * Used to emit lightweight class-list scripts for client hydration.\n */\n getRenderedClassNames(): string[] {\n const names: string[] = [];\n for (const className of this.cacheKeyToClassName.values()) {\n if (!this.flushedClassNames.has(className)) {\n this.flushedClassNames.add(className);\n names.push(className);\n }\n }\n return names;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"collector-BWvvN7_y.js","names":[],"sources":["../src/ssr/collector.ts"],"sourcesContent":["/**\n * ServerStyleCollector — server-safe style collector for SSR.\n *\n * Accumulates CSS rules and cache metadata during server rendering.\n * This is the server-side counterpart to StyleInjector: it allocates\n * hash-based class names using the configured `namePrefix` (defaults\n * to `'t'`), formats CSS rules into text, and tracks rendered class\n * names for lightweight client transfer.\n *\n * One instance is created per HTTP request. Concurrent requests\n * each get their own collector (via AsyncLocalStorage or React context).\n */\n\nimport {\n getEffectiveProperties,\n getGlobalStyles,\n getGlobalCounterStyle,\n getGlobalFontFace,\n getGlobalConfigTokens,\n getNamePrefix,\n} from '../config';\nimport { formatCounterStyleRule } from '../counter-style';\nimport { fontFaceContentHash, formatFontFaceRule } from '../font-face';\nimport { renderStyles } from '../pipeline';\nimport type { StyleResult } from '../pipeline';\nimport { hashString } from '../utils/hash';\nimport {\n makeClassName,\n makeCounterStyleName,\n makeKeyframeName,\n validateNamePrefix,\n} from '../utils/name-prefix';\nimport { formatPropertyCSS } from './format-property';\nimport { formatGlobalRules } from './format-global-rules';\nimport { formatRules } from './format-rules';\n\nexport class ServerStyleCollector {\n private chunks = new Map<string, string>();\n private cacheKeyToClassName = new Map<string, string>();\n private flushedKeys = new Set<string>();\n private propertyRules = new Map<string, string>();\n private flushedPropertyKeys = new Set<string>();\n private keyframeRules = new Map<string, string>();\n private flushedKeyframeKeys = new Set<string>();\n private globalStyles = new Map<string, string>();\n private flushedGlobalKeys = new Set<string>();\n private rawCSS = new Map<string, string>();\n private flushedRawKeys = new Set<string>();\n private fontFaceRules = new Map<string, string>();\n private flushedFontFaceKeys = new Set<string>();\n private counterStyleRules = new Map<string, string>();\n private flushedCounterStyleKeys = new Set<string>();\n private keyframesCounter = 0;\n private counterStyleCounter = 0;\n private internalsCollected = false;\n private namePrefix: string;\n\n /**\n * @param namePrefix - Optional override for the configured prefix.\n * Defaults to the value from `configure({ namePrefix })` (or `'t'`).\n * Pass an explicit prefix when constructing a collector outside the\n * normal configure() lifecycle (e.g. in tests). Validated eagerly\n * so misconfiguration fails before any CSS is collected.\n */\n constructor(namePrefix?: string) {\n if (namePrefix !== undefined) {\n validateNamePrefix(namePrefix);\n }\n this.namePrefix = namePrefix ?? getNamePrefix();\n }\n\n private generateClassName(cacheKey: string): string {\n return makeClassName(this.namePrefix, hashString(cacheKey));\n }\n\n /**\n * Collect internal @property rules and :root token defaults.\n * Mirrors markStylesGenerated() from the client-side injector.\n * Called automatically on first chunk collection; idempotent.\n *\n * Internals are always emitted here — the RSC path deliberately\n * defers to SSR so that tokens appear exactly once per page in\n * <style data-tasty-ssr> (avoiding duplication of large token sets).\n */\n collectInternals(): void {\n if (this.internalsCollected) return;\n this.internalsCollected = true;\n\n for (const [token, definition] of Object.entries(\n getEffectiveProperties(),\n )) {\n const css = formatPropertyCSS(token, definition);\n if (css) {\n this.collectProperty(`__prop:${token}`, css);\n }\n }\n\n const tokenStyles = getGlobalConfigTokens();\n if (tokenStyles && Object.keys(tokenStyles).length > 0) {\n const tokenRules = renderStyles(tokenStyles, ':root') as StyleResult[];\n if (tokenRules.length > 0) {\n const css = formatGlobalRules(tokenRules);\n if (css) {\n this.collectGlobalStyles('__global:tokens', css);\n }\n }\n }\n\n const globalFF = getGlobalFontFace();\n if (globalFF) {\n for (const [family, input] of Object.entries(globalFF)) {\n const descriptors = Array.isArray(input) ? input : [input];\n for (const desc of descriptors) {\n const hash = fontFaceContentHash(family, desc);\n const css = formatFontFaceRule(family, desc);\n this.collectFontFace(hash, css);\n }\n }\n }\n\n const globalCS = getGlobalCounterStyle();\n if (globalCS) {\n for (const [name, descriptors] of Object.entries(globalCS)) {\n const css = formatCounterStyleRule(name, descriptors);\n this.collectCounterStyle(name, css);\n }\n }\n\n const globalStyles = getGlobalStyles();\n if (globalStyles) {\n for (const [selector, styles] of Object.entries(globalStyles)) {\n if (Object.keys(styles).length > 0) {\n const rules = renderStyles(styles, selector) as StyleResult[];\n if (rules.length > 0) {\n const css = formatGlobalRules(rules);\n if (css) {\n this.collectGlobalStyles(`__global:styles:${selector}`, css);\n }\n }\n }\n }\n }\n }\n\n /**\n * Allocate a className for a cache key, server-side.\n * Mirrors StyleInjector.allocateClassName but without DOM access.\n */\n allocateClassName(cacheKey: string): {\n className: string;\n isNewAllocation: boolean;\n } {\n const existing = this.cacheKeyToClassName.get(cacheKey);\n if (existing) {\n return { className: existing, isNewAllocation: false };\n }\n\n const className = this.generateClassName(cacheKey);\n this.cacheKeyToClassName.set(cacheKey, className);\n\n return { className, isNewAllocation: true };\n }\n\n /**\n * Record CSS rules for a chunk.\n * Called by useStyles during server render.\n */\n collectChunk(\n cacheKey: string,\n className: string,\n rules: StyleResult[],\n ): void {\n if (this.chunks.has(cacheKey)) return;\n const css = formatRules(rules, className);\n if (css) {\n this.chunks.set(cacheKey, css);\n }\n }\n\n /**\n * Record a @property rule. Deduplicated by name.\n */\n collectProperty(name: string, css: string): void {\n if (!this.propertyRules.has(name)) {\n this.propertyRules.set(name, css);\n }\n }\n\n /**\n * Record a @keyframes rule. Deduplicated by name.\n */\n collectKeyframes(name: string, css: string): void {\n if (!this.keyframeRules.has(name)) {\n this.keyframeRules.set(name, css);\n }\n }\n\n /**\n * Allocate a keyframe name for SSR. Uses provided name or generates one.\n */\n allocateKeyframeName(providedName?: string): string {\n return (\n providedName ??\n makeKeyframeName(this.namePrefix, String(this.keyframesCounter++))\n );\n }\n\n /**\n * Record a @font-face rule. Deduplicated by key (content hash).\n */\n collectFontFace(key: string, css: string): void {\n if (!this.fontFaceRules.has(key)) {\n this.fontFaceRules.set(key, css);\n }\n }\n\n /**\n * Record a @counter-style rule. Deduplicated by name.\n */\n collectCounterStyle(name: string, css: string): void {\n if (!this.counterStyleRules.has(name)) {\n this.counterStyleRules.set(name, css);\n }\n }\n\n /**\n * Allocate a counter-style name for SSR. Uses provided name or generates one.\n */\n allocateCounterStyleName(providedName?: string): string {\n return (\n providedName ??\n makeCounterStyleName(this.namePrefix, String(this.counterStyleCounter++))\n );\n }\n\n /**\n * Record global styles (from useGlobalStyles). Deduplicated by key.\n */\n collectGlobalStyles(key: string, css: string): void {\n if (!this.globalStyles.has(key)) {\n this.globalStyles.set(key, css);\n }\n }\n\n /**\n * Record raw CSS text (from useRawCSS). Deduplicated by key.\n */\n collectRawCSS(key: string, css: string): void {\n if (!this.rawCSS.has(key)) {\n this.rawCSS.set(key, css);\n }\n }\n\n /**\n * Extract all CSS collected so far as a single string.\n * Includes @property and @keyframes rules.\n * Used for non-streaming SSR (renderToString).\n */\n getCSS(): string {\n const parts: string[] = [];\n\n for (const css of this.propertyRules.values()) {\n parts.push(css);\n }\n\n for (const css of this.fontFaceRules.values()) {\n parts.push(css);\n }\n\n for (const css of this.counterStyleRules.values()) {\n parts.push(css);\n }\n\n for (const css of this.rawCSS.values()) {\n parts.push(css);\n }\n\n for (const css of this.globalStyles.values()) {\n parts.push(css);\n }\n\n for (const css of this.chunks.values()) {\n parts.push(css);\n }\n\n for (const css of this.keyframeRules.values()) {\n parts.push(css);\n }\n\n return parts.join('\\n');\n }\n\n /**\n * Flush only newly collected CSS since the last flush.\n * Used for streaming SSR (renderToPipeableStream + useServerInsertedHTML).\n */\n flushCSS(): string {\n const parts: string[] = [];\n\n for (const [name, css] of this.propertyRules) {\n if (!this.flushedPropertyKeys.has(name)) {\n parts.push(css);\n this.flushedPropertyKeys.add(name);\n }\n }\n\n for (const [key, css] of this.fontFaceRules) {\n if (!this.flushedFontFaceKeys.has(key)) {\n parts.push(css);\n this.flushedFontFaceKeys.add(key);\n }\n }\n\n for (const [key, css] of this.counterStyleRules) {\n if (!this.flushedCounterStyleKeys.has(key)) {\n parts.push(css);\n this.flushedCounterStyleKeys.add(key);\n }\n }\n\n for (const [key, css] of this.rawCSS) {\n if (!this.flushedRawKeys.has(key)) {\n parts.push(css);\n this.flushedRawKeys.add(key);\n }\n }\n\n for (const [key, css] of this.globalStyles) {\n if (!this.flushedGlobalKeys.has(key)) {\n parts.push(css);\n this.flushedGlobalKeys.add(key);\n }\n }\n\n for (const [key, css] of this.chunks) {\n if (!this.flushedKeys.has(key)) {\n parts.push(css);\n this.flushedKeys.add(key);\n }\n }\n\n for (const [name, css] of this.keyframeRules) {\n if (!this.flushedKeyframeKeys.has(name)) {\n parts.push(css);\n this.flushedKeyframeKeys.add(name);\n }\n }\n\n return parts.join('\\n');\n }\n\n private flushedClassNames = new Set<string>();\n\n /**\n * Return class names rendered since the last call (for streaming).\n * Used to emit lightweight class-list scripts for client hydration.\n */\n getRenderedClassNames(): string[] {\n const names: string[] = [];\n for (const className of this.cacheKeyToClassName.values()) {\n if (!this.flushedClassNames.has(className)) {\n this.flushedClassNames.add(className);\n names.push(className);\n }\n }\n return names;\n }\n}\n"],"mappings":"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"}
|
|
@@ -7442,6 +7442,18 @@ function wrapInIsOrNot(args, negated) {
|
|
|
7442
7442
|
return `${negated ? ":not" : ":is"}(${args.sort().join(", ")})`;
|
|
7443
7443
|
}
|
|
7444
7444
|
/**
|
|
7445
|
+
* Wrap a non-empty selector fragment in `:where(...)` to zero its
|
|
7446
|
+
* specificity. Tasty anchors specificity solely on the doubled class
|
|
7447
|
+
* (`.tXX.tXX`) and `data-element` attributes; every stateful selector
|
|
7448
|
+
* (modifiers, pseudos, :is()/:not() groups, root/parent context) is wrapped
|
|
7449
|
+
* so it contributes nothing to specificity and the cascade is decided by
|
|
7450
|
+
* source order alone. Empty input passes through unchanged.
|
|
7451
|
+
*/
|
|
7452
|
+
function wrapWhere(inner) {
|
|
7453
|
+
if (!inner) return "";
|
|
7454
|
+
return `:where(${inner})`;
|
|
7455
|
+
}
|
|
7456
|
+
/**
|
|
7445
7457
|
* Convert a selector group to a CSS selector fragment.
|
|
7446
7458
|
*
|
|
7447
7459
|
* Single-branch groups are unwrapped (no :is() wrapper).
|
|
@@ -7545,7 +7557,7 @@ function rootGroupsToCSS(groups) {
|
|
|
7545
7557
|
if (optimized.length === 0) return void 0;
|
|
7546
7558
|
let prefix = ":root";
|
|
7547
7559
|
for (const group of optimized) prefix += selectorGroupToCSS(group);
|
|
7548
|
-
return prefix;
|
|
7560
|
+
return wrapWhere(prefix);
|
|
7549
7561
|
}
|
|
7550
7562
|
/**
|
|
7551
7563
|
* Convert parent groups to CSS selector fragments (for final output).
|
|
@@ -7557,7 +7569,8 @@ function parentGroupsToCSS(groups) {
|
|
|
7557
7569
|
for (const group of groups) {
|
|
7558
7570
|
const combinator = group.direct ? " > *" : " *";
|
|
7559
7571
|
const args = group.branches.map((branch) => branchToCSS(branch) + combinator);
|
|
7560
|
-
|
|
7572
|
+
const inner = group.negated ? `:not(${args.sort().join(", ")})` : args.sort().join(", ");
|
|
7573
|
+
result += wrapWhere(inner);
|
|
7561
7574
|
}
|
|
7562
7575
|
return result;
|
|
7563
7576
|
}
|
|
@@ -8227,6 +8240,21 @@ function buildAtRulesFromVariant(variant) {
|
|
|
8227
8240
|
return atRules;
|
|
8228
8241
|
}
|
|
8229
8242
|
//#endregion
|
|
8243
|
+
//#region src/pipeline/warnings.ts
|
|
8244
|
+
const defaultWarningHandler = (warning) => {
|
|
8245
|
+
console.warn(`[Tasty] ${warning.message}`);
|
|
8246
|
+
};
|
|
8247
|
+
let warningHandler = defaultWarningHandler;
|
|
8248
|
+
/**
|
|
8249
|
+
* Emit a structured pipeline warning via the configured handler.
|
|
8250
|
+
*/
|
|
8251
|
+
function emitWarning(code, message) {
|
|
8252
|
+
warningHandler({
|
|
8253
|
+
code,
|
|
8254
|
+
message
|
|
8255
|
+
});
|
|
8256
|
+
}
|
|
8257
|
+
//#endregion
|
|
8230
8258
|
//#region src/pipeline/exclusive.ts
|
|
8231
8259
|
/**
|
|
8232
8260
|
* Build exclusive conditions for a list of parsed style entries.
|
|
@@ -8255,7 +8283,12 @@ function buildAtRulesFromVariant(variant) {
|
|
|
8255
8283
|
function buildExclusiveConditions(entries) {
|
|
8256
8284
|
const result = [];
|
|
8257
8285
|
const priorConditions = [];
|
|
8286
|
+
const floors = [];
|
|
8258
8287
|
for (const entry of entries) {
|
|
8288
|
+
if (entry.floor) {
|
|
8289
|
+
floors.push(entry);
|
|
8290
|
+
continue;
|
|
8291
|
+
}
|
|
8259
8292
|
let exclusive = entry.condition;
|
|
8260
8293
|
for (const prior of priorConditions) {
|
|
8261
8294
|
if (prior.kind === "true") continue;
|
|
@@ -8270,6 +8303,10 @@ function buildExclusiveConditions(entries) {
|
|
|
8270
8303
|
});
|
|
8271
8304
|
if (entry.condition.kind !== "true") priorConditions.push(entry.condition);
|
|
8272
8305
|
}
|
|
8306
|
+
for (const floor of floors) result.push({
|
|
8307
|
+
...floor,
|
|
8308
|
+
exclusiveCondition: floor.condition
|
|
8309
|
+
});
|
|
8273
8310
|
return result;
|
|
8274
8311
|
}
|
|
8275
8312
|
/**
|
|
@@ -8282,19 +8319,85 @@ function buildExclusiveConditions(entries) {
|
|
|
8282
8319
|
*/
|
|
8283
8320
|
function parseStyleEntries(styleKey, valueMap, parseCondition) {
|
|
8284
8321
|
const entries = [];
|
|
8285
|
-
|
|
8322
|
+
let floorEntry = null;
|
|
8323
|
+
Object.keys(valueMap).forEach((stateKey) => {
|
|
8286
8324
|
const value = valueMap[stateKey];
|
|
8325
|
+
if (stateKey === "_") {
|
|
8326
|
+
floorEntry = {
|
|
8327
|
+
styleKey,
|
|
8328
|
+
stateKey,
|
|
8329
|
+
value,
|
|
8330
|
+
condition: trueCondition(),
|
|
8331
|
+
priority: 0,
|
|
8332
|
+
floor: true
|
|
8333
|
+
};
|
|
8334
|
+
return;
|
|
8335
|
+
}
|
|
8336
|
+
if (isMisusedFallbackKey(stateKey)) {
|
|
8337
|
+
emitWarning("INVALID_FALLBACK_KEY", `Style key "${stateKey}" (in "${styleKey}") combines the fallback "_" with other state logic. "_" can only be used on its own as a map-wide fallback floor. The key has been ignored.`);
|
|
8338
|
+
return;
|
|
8339
|
+
}
|
|
8287
8340
|
const condition = stateKey === "" ? trueCondition() : parseCondition(stateKey);
|
|
8288
8341
|
entries.push({
|
|
8289
8342
|
styleKey,
|
|
8290
8343
|
stateKey,
|
|
8291
8344
|
value,
|
|
8292
8345
|
condition,
|
|
8293
|
-
priority:
|
|
8346
|
+
priority: 0
|
|
8294
8347
|
});
|
|
8295
8348
|
});
|
|
8296
|
-
|
|
8297
|
-
|
|
8349
|
+
if (floorEntry !== null) {
|
|
8350
|
+
const hasOtherStates = entries.some((e) => e.condition.kind !== "true");
|
|
8351
|
+
const hasDefault = entries.some((e) => e.condition.kind === "true");
|
|
8352
|
+
if (!hasOtherStates && hasDefault) {
|
|
8353
|
+
emitWarning("REDUNDANT_DEFAULT_STATE", `Style "${styleKey}" defines both a "_" fallback and a "" default with no other states. The "" default is redundant (always superseded by "_"); the "_" value is used and the "" default is ignored.`);
|
|
8354
|
+
entries.length = 0;
|
|
8355
|
+
}
|
|
8356
|
+
}
|
|
8357
|
+
const normalized = normalizeDefaultStates(entries, styleKey);
|
|
8358
|
+
const ordered = floorEntry !== null ? [floorEntry, ...normalized] : normalized;
|
|
8359
|
+
ordered.forEach((entry, index) => {
|
|
8360
|
+
entry.priority = index;
|
|
8361
|
+
});
|
|
8362
|
+
ordered.reverse();
|
|
8363
|
+
return ordered;
|
|
8364
|
+
}
|
|
8365
|
+
/**
|
|
8366
|
+
* Detect a misused standalone `_` fallback key: a key that is not exactly
|
|
8367
|
+
* `_` but contains `_` as a standalone atom among state-logic operators
|
|
8368
|
+
* (`&`, `|`, `^`, `,`) or grouping parens. A `_` embedded in a longer token
|
|
8369
|
+
* (e.g. a modifier named `_private`) is not a misuse.
|
|
8370
|
+
*/
|
|
8371
|
+
function isMisusedFallbackKey(stateKey) {
|
|
8372
|
+
if (stateKey === "_" || !stateKey.includes("_")) return false;
|
|
8373
|
+
return /(?:^|[\s&|^,(])_(?:[\s&|^,)]|$)/.test(stateKey);
|
|
8374
|
+
}
|
|
8375
|
+
/**
|
|
8376
|
+
* Resolve the bare `''` default state (`condition.kind === 'true'`) in a
|
|
8377
|
+
* style value map.
|
|
8378
|
+
*
|
|
8379
|
+
* The bare default only behaves correctly as the **first** (lowest-priority)
|
|
8380
|
+
* key. When it appears later, `buildExclusiveConditions` processes it first
|
|
8381
|
+
* (after the reverse), never adds it to the prior list, and never negates it
|
|
8382
|
+
* — so it silently overrides every state authored before it.
|
|
8383
|
+
*
|
|
8384
|
+
* This function, given entries in authored order, moves a misplaced bare
|
|
8385
|
+
* default to the front (lowest priority), preserving the relative order of
|
|
8386
|
+
* all other entries, and emits a `MISPLACED_DEFAULT_STATE` warning.
|
|
8387
|
+
*
|
|
8388
|
+
* The `_` fallback floor is pulled out before this runs (see
|
|
8389
|
+
* `parseStyleEntries`), so only the bare `''` default is considered here.
|
|
8390
|
+
*/
|
|
8391
|
+
function normalizeDefaultStates(entries, styleKey) {
|
|
8392
|
+
const defaultPos = entries.findIndex((e) => e.condition.kind === "true");
|
|
8393
|
+
if (defaultPos <= 0) return entries;
|
|
8394
|
+
const defaultEntry = entries[defaultPos];
|
|
8395
|
+
emitWarning("MISPLACED_DEFAULT_STATE", `Style "${styleKey}" defines the default state "${defaultEntry.stateKey}" after other states. A bare default ("") must be the first key, otherwise it overrides the states above it. It has been moved to the first position. Define default states first.`);
|
|
8396
|
+
return [
|
|
8397
|
+
defaultEntry,
|
|
8398
|
+
...entries.slice(0, defaultPos),
|
|
8399
|
+
...entries.slice(defaultPos + 1)
|
|
8400
|
+
];
|
|
8298
8401
|
}
|
|
8299
8402
|
/**
|
|
8300
8403
|
* Merge parsed entries that share the same value.
|
|
@@ -8417,8 +8520,9 @@ function extractCompoundStates(valueMap) {
|
|
|
8417
8520
|
const keys = Object.keys(valueMap);
|
|
8418
8521
|
if (keys.length < 3 || !keys.some((k) => k.includes("&"))) return valueMap;
|
|
8419
8522
|
const entries = keys.map((key) => {
|
|
8523
|
+
const atoms = splitTopLevelAnd(key);
|
|
8420
8524
|
return {
|
|
8421
|
-
atoms:
|
|
8525
|
+
atoms: atoms === null || atoms.includes("_") ? [key] : atoms,
|
|
8422
8526
|
value: valueMap[key]
|
|
8423
8527
|
};
|
|
8424
8528
|
});
|
|
@@ -8723,21 +8827,6 @@ function transformSelectorContent(content) {
|
|
|
8723
8827
|
return content.replace(ELEMENT_NAME_RE, (_, prefix, name) => `${prefix}[data-element="${name}"]`);
|
|
8724
8828
|
}
|
|
8725
8829
|
//#endregion
|
|
8726
|
-
//#region src/pipeline/warnings.ts
|
|
8727
|
-
const defaultWarningHandler = (warning) => {
|
|
8728
|
-
console.warn(`[Tasty] ${warning.message}`);
|
|
8729
|
-
};
|
|
8730
|
-
let warningHandler = defaultWarningHandler;
|
|
8731
|
-
/**
|
|
8732
|
-
* Emit a structured pipeline warning via the configured handler.
|
|
8733
|
-
*/
|
|
8734
|
-
function emitWarning(code, message) {
|
|
8735
|
-
warningHandler({
|
|
8736
|
-
code,
|
|
8737
|
-
message
|
|
8738
|
-
});
|
|
8739
|
-
}
|
|
8740
|
-
//#endregion
|
|
8741
8830
|
//#region src/pipeline/parseStateKey.ts
|
|
8742
8831
|
/**
|
|
8743
8832
|
* State Key Parser
|
|
@@ -9252,7 +9341,17 @@ function runPipeline(styles, parserContext) {
|
|
|
9252
9341
|
const starting = [];
|
|
9253
9342
|
for (const rule of dedupedRules) if (rule.startingStyle) starting.push(rule);
|
|
9254
9343
|
else normal.push(rule);
|
|
9255
|
-
return normal.concat(starting);
|
|
9344
|
+
return stableSortByOrder(normal).concat(stableSortByOrder(starting));
|
|
9345
|
+
}
|
|
9346
|
+
/**
|
|
9347
|
+
* Stable sort CSS rules by their `order` hint ascending. Rules without an
|
|
9348
|
+
* `order` are treated as 0. `Array.prototype.sort` is stable (ES2019+,
|
|
9349
|
+
* Node >= 20), so equal-order rules keep their emission order — the `_`
|
|
9350
|
+
* fallback floor (low order) stays before the overrides that layer over it.
|
|
9351
|
+
*/
|
|
9352
|
+
function stableSortByOrder(rules) {
|
|
9353
|
+
if (rules.length <= 1) return rules;
|
|
9354
|
+
return [...rules].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
9256
9355
|
}
|
|
9257
9356
|
/**
|
|
9258
9357
|
* Process styles at a given nesting level.
|
|
@@ -9360,7 +9459,8 @@ function invokeHandler(handler, stateSnapshots, selectorSuffix) {
|
|
|
9360
9459
|
for (const suffix of suffixes) computedRules.push({
|
|
9361
9460
|
condition: snapshot.condition,
|
|
9362
9461
|
declarations,
|
|
9363
|
-
selectorSuffix: suffix
|
|
9462
|
+
selectorSuffix: suffix,
|
|
9463
|
+
order: snapshot.order
|
|
9364
9464
|
});
|
|
9365
9465
|
}
|
|
9366
9466
|
}
|
|
@@ -9778,10 +9878,15 @@ function computeStateCombinations(exclusiveByStyle, lookupStyles) {
|
|
|
9778
9878
|
const simplified = simplifyCondition(and(...combo.map((e) => e.exclusiveCondition)));
|
|
9779
9879
|
if (simplified.kind === "false") continue;
|
|
9780
9880
|
const values = {};
|
|
9781
|
-
|
|
9881
|
+
let order = 0;
|
|
9882
|
+
for (const entry of combo) {
|
|
9883
|
+
values[entry.styleKey] = entry.value;
|
|
9884
|
+
if (entry.priority > order) order = entry.priority;
|
|
9885
|
+
}
|
|
9782
9886
|
snapshots.push({
|
|
9783
9887
|
condition: simplified,
|
|
9784
|
-
values
|
|
9888
|
+
values,
|
|
9889
|
+
order
|
|
9785
9890
|
});
|
|
9786
9891
|
}
|
|
9787
9892
|
return snapshots;
|
|
@@ -9829,10 +9934,13 @@ function mergeByValue(rules) {
|
|
|
9829
9934
|
for (const [, groupRules] of groups) if (groupRules.length === 1) merged.push(groupRules[0]);
|
|
9830
9935
|
else {
|
|
9831
9936
|
const mergedCondition = simplifyCondition(or(...groupRules.map((r) => r.condition)));
|
|
9937
|
+
let order = groupRules[0].order;
|
|
9938
|
+
for (const r of groupRules) if (r.order < order) order = r.order;
|
|
9832
9939
|
merged.push({
|
|
9833
9940
|
condition: mergedCondition,
|
|
9834
9941
|
declarations: groupRules[0].declarations,
|
|
9835
|
-
selectorSuffix: groupRules[0].selectorSuffix
|
|
9942
|
+
selectorSuffix: groupRules[0].selectorSuffix,
|
|
9943
|
+
order
|
|
9836
9944
|
});
|
|
9837
9945
|
}
|
|
9838
9946
|
return merged;
|
|
@@ -9842,12 +9950,15 @@ function mergeByValue(rules) {
|
|
|
9842
9950
|
*/
|
|
9843
9951
|
function buildSelectorFromVariant(variant, selectorSuffix) {
|
|
9844
9952
|
let selector = "";
|
|
9845
|
-
|
|
9846
|
-
for (const group of variant.selectorGroups)
|
|
9953
|
+
let rootSegment = branchToCSS([...variant.modifierConditions, ...variant.pseudoConditions]);
|
|
9954
|
+
for (const group of variant.selectorGroups) rootSegment += selectorGroupToCSS(group);
|
|
9955
|
+
selector += wrapWhere(rootSegment);
|
|
9847
9956
|
if (variant.parentGroups.length > 0) selector += parentGroupsToCSS(variant.parentGroups);
|
|
9848
9957
|
selector += selectorSuffix;
|
|
9849
9958
|
const ownOptimized = optimizeGroups(variant.ownGroups);
|
|
9850
|
-
|
|
9959
|
+
let ownSegment = "";
|
|
9960
|
+
for (const group of ownOptimized) ownSegment += selectorGroupToCSS(group);
|
|
9961
|
+
selector += wrapWhere(ownSegment);
|
|
9851
9962
|
return selector;
|
|
9852
9963
|
}
|
|
9853
9964
|
/**
|
|
@@ -9882,7 +9993,8 @@ function materializeComputedRule(rule) {
|
|
|
9882
9993
|
const selectorFragments = mergeVariantsIntoSelectorGroups(group.variants).map((v) => buildSelectorFromVariant(v, rule.selectorSuffix));
|
|
9883
9994
|
const cssRule = {
|
|
9884
9995
|
selector: selectorFragments.length === 1 ? selectorFragments[0] : selectorFragments,
|
|
9885
|
-
declarations
|
|
9996
|
+
declarations,
|
|
9997
|
+
order: rule.order
|
|
9886
9998
|
};
|
|
9887
9999
|
if (group.atRules.length > 0) cssRule.atRules = group.atRules;
|
|
9888
10000
|
if (group.rootPrefix) cssRule.rootPrefix = group.rootPrefix;
|
|
@@ -10596,4 +10708,4 @@ function resetConfig() {
|
|
|
10596
10708
|
//#endregion
|
|
10597
10709
|
export { parseColor as $, StyleInjector as A, hasLocalProperties as At, styleHandlers as B, parseStateKey as C, getRgbValuesFromRgbaString as Ct, extractPredefinedStateRefs as D, Lru as Dt, extractLocalPredefinedStates as E, strToRgb as Et, fontFaceContentHash as F, CUSTOM_UNITS as G, warn as H, formatFontFaceRule as I, filterMods as J, DIRECTIONS as K, hasLocalFontFace as L, formatCounterStyleRule as M, hasLocalCounterStyle as N, getGlobalPredefinedStates as O, extractLocalProperties as Ot, extractLocalFontFace as P, normalizeColorTokenValue as Q, SheetManager as R, renderStyles as S, getNamedColorHex as St, createStateParserContext as T, hslToRgbValues as Tt, createStyle as U, deprecationWarning as V, PropertyTypeResolver as W, getGlobalParser as X, getGlobalFuncs as Y, getGlobalPredefinedTokens as Z, markStylesGenerated as _, colorInitialValueToComponents as _t, getGlobalCounterStyle as a, okhslPlugin as at, hasPipelineCacheEntry as b, getColorSpaceSuffix as bt, getGlobalKeyframes as c, DEFAULT_NAME_PREFIX as ct, getNamePrefix as d, makeCounterStyleName as dt, parseStyle as et, hasGlobalKeyframes as f, makeKeyframeName as ft, isTestEnvironment as g, hashString as gt, isConfigLocked as h, isDevEnv as ht, getGlobalConfigTokens as i, okhslFunc as it, extractLocalCounterStyle as j, parsePropertyToken as jt, setGlobalPredefinedStates as k, getEffectiveDefinition as kt, getGlobalRecipes as l, DEFAULT_ZERO_NAME_PREFIX as lt, hasStylesGenerated as m, validateNamePrefix as mt, getConfig as n, setGlobalPredefinedTokens as nt, getGlobalFontFace as o, StyleParser as ot, hasGlobalRecipes as p, tastyClassRegex as pt, customFunc as q, getEffectiveProperties as r, stringifyStyles as rt, getGlobalInjector as s, Bucket as st, configure as t, resetGlobalPredefinedTokens as tt, getGlobalStyles as u, makeClassName as ut, resetConfig as v, getColorSpaceComponents as vt, camelToKebab as w, hexToRgb as wt, isSelector as x, getComponentPropertySyntax as xt, generateTypographyTokens as y, getColorSpaceFunc as yt, STYLE_HANDLER_MAP as z };
|
|
10598
10710
|
|
|
10599
|
-
//# sourceMappingURL=config-
|
|
10711
|
+
//# sourceMappingURL=config-DF2QZQEW.js.map
|