@tenphi/tasty 0.0.0-snapshot.01d8a9e
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/LICENSE +21 -0
- package/README.md +635 -0
- package/dist/_virtual/_rolldown/runtime.js +7 -0
- package/dist/chunks/cacheKey.d.ts +1 -0
- package/dist/chunks/cacheKey.js +77 -0
- package/dist/chunks/cacheKey.js.map +1 -0
- package/dist/chunks/definitions.d.ts +37 -0
- package/dist/chunks/definitions.js +258 -0
- package/dist/chunks/definitions.js.map +1 -0
- package/dist/chunks/index.d.ts +1 -0
- package/dist/chunks/renderChunk.d.ts +1 -0
- package/dist/chunks/renderChunk.js +59 -0
- package/dist/chunks/renderChunk.js.map +1 -0
- package/dist/compute-styles.d.ts +31 -0
- package/dist/compute-styles.js +336 -0
- package/dist/compute-styles.js.map +1 -0
- package/dist/config.d.ts +407 -0
- package/dist/config.js +591 -0
- package/dist/config.js.map +1 -0
- package/dist/core/index.d.ts +34 -0
- package/dist/core/index.js +27 -0
- package/dist/counter-style/index.js +51 -0
- package/dist/counter-style/index.js.map +1 -0
- package/dist/debug.d.ts +89 -0
- package/dist/debug.js +453 -0
- package/dist/debug.js.map +1 -0
- package/dist/font-face/index.js +63 -0
- package/dist/font-face/index.js.map +1 -0
- package/dist/hooks/index.d.ts +7 -0
- package/dist/hooks/useCounterStyle.d.ts +36 -0
- package/dist/hooks/useCounterStyle.js +65 -0
- package/dist/hooks/useCounterStyle.js.map +1 -0
- package/dist/hooks/useFontFace.d.ts +45 -0
- package/dist/hooks/useFontFace.js +66 -0
- package/dist/hooks/useFontFace.js.map +1 -0
- package/dist/hooks/useGlobalStyles.d.ts +46 -0
- package/dist/hooks/useGlobalStyles.js +88 -0
- package/dist/hooks/useGlobalStyles.js.map +1 -0
- package/dist/hooks/useKeyframes.d.ts +58 -0
- package/dist/hooks/useKeyframes.js +55 -0
- package/dist/hooks/useKeyframes.js.map +1 -0
- package/dist/hooks/useProperty.d.ts +81 -0
- package/dist/hooks/useProperty.js +96 -0
- package/dist/hooks/useProperty.js.map +1 -0
- package/dist/hooks/useRawCSS.d.ts +22 -0
- package/dist/hooks/useRawCSS.js +103 -0
- package/dist/hooks/useRawCSS.js.map +1 -0
- package/dist/hooks/useStyles.d.ts +40 -0
- package/dist/hooks/useStyles.js +31 -0
- package/dist/hooks/useStyles.js.map +1 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.js +36 -0
- package/dist/injector/index.d.ts +182 -0
- package/dist/injector/index.js +185 -0
- package/dist/injector/index.js.map +1 -0
- package/dist/injector/injector.d.ts +198 -0
- package/dist/injector/injector.js +651 -0
- package/dist/injector/injector.js.map +1 -0
- package/dist/injector/sheet-manager.d.ts +132 -0
- package/dist/injector/sheet-manager.js +699 -0
- package/dist/injector/sheet-manager.js.map +1 -0
- package/dist/injector/types.d.ts +235 -0
- package/dist/keyframes/index.js +206 -0
- package/dist/keyframes/index.js.map +1 -0
- package/dist/parser/classify.js +319 -0
- package/dist/parser/classify.js.map +1 -0
- package/dist/parser/const.js +60 -0
- package/dist/parser/const.js.map +1 -0
- package/dist/parser/lru.js +109 -0
- package/dist/parser/lru.js.map +1 -0
- package/dist/parser/parser.d.ts +25 -0
- package/dist/parser/parser.js +115 -0
- package/dist/parser/parser.js.map +1 -0
- package/dist/parser/tokenizer.js +69 -0
- package/dist/parser/tokenizer.js.map +1 -0
- package/dist/parser/types.d.ts +51 -0
- package/dist/parser/types.js +46 -0
- package/dist/parser/types.js.map +1 -0
- package/dist/pipeline/conditions.d.ts +134 -0
- package/dist/pipeline/conditions.js +406 -0
- package/dist/pipeline/conditions.js.map +1 -0
- package/dist/pipeline/exclusive.js +283 -0
- package/dist/pipeline/exclusive.js.map +1 -0
- package/dist/pipeline/index.d.ts +55 -0
- package/dist/pipeline/index.js +708 -0
- package/dist/pipeline/index.js.map +1 -0
- package/dist/pipeline/materialize.js +1157 -0
- package/dist/pipeline/materialize.js.map +1 -0
- package/dist/pipeline/parseStateKey.d.ts +15 -0
- package/dist/pipeline/parseStateKey.js +446 -0
- package/dist/pipeline/parseStateKey.js.map +1 -0
- package/dist/pipeline/simplify.js +690 -0
- package/dist/pipeline/simplify.js.map +1 -0
- package/dist/pipeline/warnings.js +18 -0
- package/dist/pipeline/warnings.js.map +1 -0
- package/dist/plugins/index.d.ts +2 -0
- package/dist/plugins/okhsl-plugin.d.ts +35 -0
- package/dist/plugins/okhsl-plugin.js +97 -0
- package/dist/plugins/okhsl-plugin.js.map +1 -0
- package/dist/plugins/types.d.ts +87 -0
- package/dist/properties/index.js +222 -0
- package/dist/properties/index.js.map +1 -0
- package/dist/properties/property-type-resolver.d.ts +24 -0
- package/dist/properties/property-type-resolver.js +90 -0
- package/dist/properties/property-type-resolver.js.map +1 -0
- 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 +108 -0
- package/dist/ssr/astro.js +149 -0
- package/dist/ssr/astro.js.map +1 -0
- package/dist/ssr/async-storage.d.ts +17 -0
- package/dist/ssr/async-storage.js +44 -0
- package/dist/ssr/async-storage.js.map +1 -0
- package/dist/ssr/collect-auto-properties.js +58 -0
- package/dist/ssr/collect-auto-properties.js.map +1 -0
- package/dist/ssr/collector.d.ts +94 -0
- package/dist/ssr/collector.js +233 -0
- package/dist/ssr/collector.js.map +1 -0
- package/dist/ssr/context.js +16 -0
- package/dist/ssr/context.js.map +1 -0
- package/dist/ssr/format-global-rules.js +22 -0
- package/dist/ssr/format-global-rules.js.map +1 -0
- package/dist/ssr/format-keyframes.js +69 -0
- package/dist/ssr/format-keyframes.js.map +1 -0
- package/dist/ssr/format-property.js +49 -0
- package/dist/ssr/format-property.js.map +1 -0
- package/dist/ssr/format-rules.js +73 -0
- package/dist/ssr/format-rules.js.map +1 -0
- package/dist/ssr/hydrate.d.ts +29 -0
- package/dist/ssr/hydrate.js +45 -0
- package/dist/ssr/hydrate.js.map +1 -0
- package/dist/ssr/index.d.ts +4 -0
- package/dist/ssr/index.js +10 -0
- package/dist/ssr/index.js.map +1 -0
- package/dist/ssr/next.d.ts +46 -0
- package/dist/ssr/next.js +75 -0
- package/dist/ssr/next.js.map +1 -0
- package/dist/ssr/ssr-collector-ref.js +29 -0
- package/dist/ssr/ssr-collector-ref.js.map +1 -0
- package/dist/states/index.d.ts +49 -0
- package/dist/states/index.js +170 -0
- package/dist/states/index.js.map +1 -0
- package/dist/static/index.d.ts +5 -0
- package/dist/static/index.js +4 -0
- package/dist/static/inject.d.ts +5 -0
- package/dist/static/inject.js +17 -0
- package/dist/static/inject.js.map +1 -0
- package/dist/static/tastyStatic.d.ts +46 -0
- package/dist/static/tastyStatic.js +30 -0
- package/dist/static/tastyStatic.js.map +1 -0
- package/dist/static/types.d.ts +49 -0
- package/dist/static/types.js +24 -0
- package/dist/static/types.js.map +1 -0
- package/dist/styles/border.d.ts +25 -0
- package/dist/styles/border.js +120 -0
- package/dist/styles/border.js.map +1 -0
- package/dist/styles/color.d.ts +14 -0
- package/dist/styles/color.js +26 -0
- package/dist/styles/color.js.map +1 -0
- package/dist/styles/const.js +17 -0
- package/dist/styles/const.js.map +1 -0
- package/dist/styles/createStyle.js +79 -0
- package/dist/styles/createStyle.js.map +1 -0
- package/dist/styles/dimension.js +109 -0
- package/dist/styles/dimension.js.map +1 -0
- package/dist/styles/directional.js +133 -0
- package/dist/styles/directional.js.map +1 -0
- package/dist/styles/display.d.ts +30 -0
- package/dist/styles/display.js +73 -0
- package/dist/styles/display.js.map +1 -0
- package/dist/styles/fade.d.ts +15 -0
- package/dist/styles/fade.js +62 -0
- package/dist/styles/fade.js.map +1 -0
- package/dist/styles/fill.d.ts +42 -0
- package/dist/styles/fill.js +51 -0
- package/dist/styles/fill.js.map +1 -0
- package/dist/styles/flow.d.ts +16 -0
- package/dist/styles/flow.js +12 -0
- package/dist/styles/flow.js.map +1 -0
- package/dist/styles/gap.d.ts +31 -0
- package/dist/styles/gap.js +38 -0
- package/dist/styles/gap.js.map +1 -0
- package/dist/styles/height.d.ts +17 -0
- package/dist/styles/height.js +19 -0
- package/dist/styles/height.js.map +1 -0
- package/dist/styles/index.d.ts +1 -0
- package/dist/styles/index.js +8 -0
- package/dist/styles/index.js.map +1 -0
- package/dist/styles/inset.d.ts +24 -0
- package/dist/styles/inset.js +34 -0
- package/dist/styles/inset.js.map +1 -0
- package/dist/styles/list.d.ts +16 -0
- package/dist/styles/list.js +100 -0
- package/dist/styles/list.js.map +1 -0
- package/dist/styles/margin.d.ts +24 -0
- package/dist/styles/margin.js +32 -0
- package/dist/styles/margin.js.map +1 -0
- package/dist/styles/outline.d.ts +29 -0
- package/dist/styles/outline.js +55 -0
- package/dist/styles/outline.js.map +1 -0
- package/dist/styles/padding.d.ts +24 -0
- package/dist/styles/padding.js +32 -0
- package/dist/styles/padding.js.map +1 -0
- package/dist/styles/placement.d.ts +37 -0
- package/dist/styles/placement.js +74 -0
- package/dist/styles/placement.js.map +1 -0
- package/dist/styles/predefined.d.ts +71 -0
- package/dist/styles/predefined.js +237 -0
- package/dist/styles/predefined.js.map +1 -0
- package/dist/styles/preset.d.ts +52 -0
- package/dist/styles/preset.js +127 -0
- package/dist/styles/preset.js.map +1 -0
- package/dist/styles/radius.d.ts +12 -0
- package/dist/styles/radius.js +83 -0
- package/dist/styles/radius.js.map +1 -0
- package/dist/styles/scrollMargin.d.ts +24 -0
- package/dist/styles/scrollMargin.js +32 -0
- package/dist/styles/scrollMargin.js.map +1 -0
- package/dist/styles/scrollbar.d.ts +25 -0
- package/dist/styles/scrollbar.js +51 -0
- package/dist/styles/scrollbar.js.map +1 -0
- package/dist/styles/shadow.d.ts +14 -0
- package/dist/styles/shadow.js +25 -0
- package/dist/styles/shadow.js.map +1 -0
- package/dist/styles/shared.js +17 -0
- package/dist/styles/shared.js.map +1 -0
- package/dist/styles/transition.d.ts +14 -0
- package/dist/styles/transition.js +159 -0
- package/dist/styles/transition.js.map +1 -0
- package/dist/styles/types.d.ts +564 -0
- package/dist/styles/width.d.ts +17 -0
- package/dist/styles/width.js +19 -0
- package/dist/styles/width.js.map +1 -0
- package/dist/tasty.d.ts +134 -0
- package/dist/tasty.js +248 -0
- package/dist/tasty.js.map +1 -0
- package/dist/types.d.ts +184 -0
- package/dist/utils/cache-wrapper.js +21 -0
- package/dist/utils/cache-wrapper.js.map +1 -0
- package/dist/utils/case-converter.js +8 -0
- package/dist/utils/case-converter.js.map +1 -0
- package/dist/utils/color-math.d.ts +46 -0
- package/dist/utils/color-math.js +749 -0
- package/dist/utils/color-math.js.map +1 -0
- package/dist/utils/color-space.d.ts +5 -0
- package/dist/utils/color-space.js +228 -0
- package/dist/utils/color-space.js.map +1 -0
- package/dist/utils/colors.d.ts +5 -0
- package/dist/utils/colors.js +10 -0
- package/dist/utils/colors.js.map +1 -0
- package/dist/utils/css-types.d.ts +7 -0
- package/dist/utils/deps-equal.js +15 -0
- package/dist/utils/deps-equal.js.map +1 -0
- package/dist/utils/dotize.d.ts +26 -0
- package/dist/utils/dotize.js +122 -0
- package/dist/utils/dotize.js.map +1 -0
- package/dist/utils/filter-base-props.d.ts +15 -0
- package/dist/utils/filter-base-props.js +45 -0
- package/dist/utils/filter-base-props.js.map +1 -0
- package/dist/utils/get-display-name.d.ts +7 -0
- package/dist/utils/get-display-name.js +10 -0
- package/dist/utils/get-display-name.js.map +1 -0
- package/dist/utils/has-keys.js +13 -0
- package/dist/utils/has-keys.js.map +1 -0
- package/dist/utils/hash.js +14 -0
- package/dist/utils/hash.js.map +1 -0
- package/dist/utils/is-dev-env.js +19 -0
- package/dist/utils/is-dev-env.js.map +1 -0
- package/dist/utils/is-valid-element-type.js +15 -0
- package/dist/utils/is-valid-element-type.js.map +1 -0
- package/dist/utils/merge-styles.d.ts +7 -0
- package/dist/utils/merge-styles.js +145 -0
- package/dist/utils/merge-styles.js.map +1 -0
- package/dist/utils/mod-attrs.d.ts +6 -0
- package/dist/utils/mod-attrs.js +20 -0
- package/dist/utils/mod-attrs.js.map +1 -0
- package/dist/utils/process-tokens.d.ts +17 -0
- package/dist/utils/process-tokens.js +83 -0
- package/dist/utils/process-tokens.js.map +1 -0
- package/dist/utils/resolve-recipes.d.ts +17 -0
- package/dist/utils/resolve-recipes.js +146 -0
- package/dist/utils/resolve-recipes.js.map +1 -0
- package/dist/utils/selector-transform.js +32 -0
- package/dist/utils/selector-transform.js.map +1 -0
- package/dist/utils/string.js +8 -0
- package/dist/utils/string.js.map +1 -0
- package/dist/utils/styles.d.ts +99 -0
- package/dist/utils/styles.js +220 -0
- package/dist/utils/styles.js.map +1 -0
- package/dist/utils/typography.d.ts +58 -0
- package/dist/utils/typography.js +51 -0
- package/dist/utils/typography.js.map +1 -0
- package/dist/utils/warnings.d.ts +16 -0
- package/dist/utils/warnings.js +16 -0
- package/dist/utils/warnings.js.map +1 -0
- package/dist/zero/babel.d.ts +81 -0
- package/dist/zero/babel.js +462 -0
- package/dist/zero/babel.js.map +1 -0
- package/dist/zero/css-writer.d.ts +45 -0
- package/dist/zero/css-writer.js +73 -0
- package/dist/zero/css-writer.js.map +1 -0
- package/dist/zero/extractor.d.ts +24 -0
- package/dist/zero/extractor.js +266 -0
- package/dist/zero/extractor.js.map +1 -0
- package/dist/zero/index.d.ts +3 -0
- package/dist/zero/index.js +3 -0
- package/dist/zero/next.d.ts +86 -0
- package/dist/zero/next.js +143 -0
- package/dist/zero/next.js.map +1 -0
- package/docs/PIPELINE.md +519 -0
- package/docs/README.md +31 -0
- package/docs/adoption.md +298 -0
- package/docs/comparison.md +419 -0
- package/docs/configuration.md +394 -0
- package/docs/debug.md +318 -0
- package/docs/design-system.md +436 -0
- package/docs/dsl.md +688 -0
- package/docs/getting-started.md +217 -0
- package/docs/injector.md +544 -0
- package/docs/methodology.md +616 -0
- package/docs/react-api.md +557 -0
- package/docs/ssr.md +442 -0
- package/docs/styles.md +596 -0
- package/docs/tasty-static.md +532 -0
- package/package.json +221 -0
- package/tasty.config.ts +14 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
//#region src/utils/typography.ts
|
|
2
|
+
const RESERVED_PRESET_NAMES = new Set([
|
|
3
|
+
"strong",
|
|
4
|
+
"bold",
|
|
5
|
+
"italic",
|
|
6
|
+
"icon",
|
|
7
|
+
"tight"
|
|
8
|
+
]);
|
|
9
|
+
/**
|
|
10
|
+
* Generate typography tokens with $ prefix for CSS custom properties.
|
|
11
|
+
*
|
|
12
|
+
* Each preset generates the following CSS custom properties:
|
|
13
|
+
* - `${name}-font-size`
|
|
14
|
+
* - `${name}-line-height`
|
|
15
|
+
* - `${name}-letter-spacing`
|
|
16
|
+
* - `${name}-font-weight`
|
|
17
|
+
* - `${name}-bold-font-weight` (if defined)
|
|
18
|
+
* - `${name}-icon-size` (if defined)
|
|
19
|
+
* - `${name}-text-transform` (if defined)
|
|
20
|
+
* - `${name}-font-family` (if defined)
|
|
21
|
+
* - `${name}-font-style` (if defined)
|
|
22
|
+
*
|
|
23
|
+
* @param presets - Typography presets object
|
|
24
|
+
* @returns ConfigTokens object with $ prefixed keys
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* const customTokens = generateTypographyTokens({
|
|
28
|
+
* myHeading: { fontSize: '24px', lineHeight: '32px', fontWeight: '700' },
|
|
29
|
+
* body: { fontSize: '16px', lineHeight: '24px', fontWeight: '400' },
|
|
30
|
+
* });
|
|
31
|
+
*/
|
|
32
|
+
function generateTypographyTokens(presets) {
|
|
33
|
+
const tokens = {};
|
|
34
|
+
for (const [name, preset] of Object.entries(presets)) {
|
|
35
|
+
if (RESERVED_PRESET_NAMES.has(name)) throw new Error(`Invalid typography preset name "${name}". This name is reserved as a preset modifier.`);
|
|
36
|
+
tokens[`$${name}-font-size`] = preset.fontSize;
|
|
37
|
+
tokens[`$${name}-line-height`] = preset.lineHeight;
|
|
38
|
+
tokens[`$${name}-letter-spacing`] = preset.letterSpacing ?? "normal";
|
|
39
|
+
tokens[`$${name}-font-weight`] = preset.fontWeight;
|
|
40
|
+
if (preset.boldFontWeight !== void 0) tokens[`$${name}-bold-font-weight`] = preset.boldFontWeight;
|
|
41
|
+
if (preset.iconSize !== void 0) tokens[`$${name}-icon-size`] = preset.iconSize;
|
|
42
|
+
if (preset.textTransform !== void 0) tokens[`$${name}-text-transform`] = preset.textTransform;
|
|
43
|
+
if (preset.fontFamily !== void 0) tokens[`$${name}-font-family`] = preset.fontFamily;
|
|
44
|
+
if (preset.fontStyle !== void 0) tokens[`$${name}-font-style`] = preset.fontStyle;
|
|
45
|
+
}
|
|
46
|
+
return tokens;
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
export { generateTypographyTokens };
|
|
50
|
+
|
|
51
|
+
//# sourceMappingURL=typography.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typography.js","names":[],"sources":["../../src/utils/typography.ts"],"sourcesContent":["import type { ConfigTokens } from '../styles/types';\n\nconst RESERVED_PRESET_NAMES = new Set([\n 'strong',\n 'bold',\n 'italic',\n 'icon',\n 'tight',\n]);\n\n/**\n * A typography token value: plain value or a state map for responsive/theme-aware presets.\n *\n * @example\n * // Plain value\n * fontWeight: '400'\n * // State map\n * fontWeight: { '': '400', '@dark': '300' }\n */\nexport type TypographyTokenValue =\n | string\n | number\n | Record<string, string | number | undefined | null | '@inherit'>;\n\n/**\n * Typography preset configuration.\n * Each preset defines font properties that get expanded into CSS custom properties.\n * All fields accept plain values or state maps for responsive/theme-aware tokens.\n *\n * Use with `generateTypographyTokens()` to create typography tokens for your design system.\n */\nexport interface TypographyPreset {\n fontSize: TypographyTokenValue;\n lineHeight: TypographyTokenValue;\n letterSpacing?: TypographyTokenValue;\n fontWeight: TypographyTokenValue;\n boldFontWeight?: TypographyTokenValue;\n iconSize?: TypographyTokenValue;\n textTransform?: TypographyTokenValue;\n fontFamily?: TypographyTokenValue;\n fontStyle?: TypographyTokenValue;\n}\n\n/**\n * Generate typography tokens with $ prefix for CSS custom properties.\n *\n * Each preset generates the following CSS custom properties:\n * - `${name}-font-size`\n * - `${name}-line-height`\n * - `${name}-letter-spacing`\n * - `${name}-font-weight`\n * - `${name}-bold-font-weight` (if defined)\n * - `${name}-icon-size` (if defined)\n * - `${name}-text-transform` (if defined)\n * - `${name}-font-family` (if defined)\n * - `${name}-font-style` (if defined)\n *\n * @param presets - Typography presets object\n * @returns ConfigTokens object with $ prefixed keys\n *\n * @example\n * const customTokens = generateTypographyTokens({\n * myHeading: { fontSize: '24px', lineHeight: '32px', fontWeight: '700' },\n * body: { fontSize: '16px', lineHeight: '24px', fontWeight: '400' },\n * });\n */\nexport function generateTypographyTokens(\n presets: Record<string, TypographyPreset>,\n): ConfigTokens {\n const tokens: ConfigTokens = {} as ConfigTokens;\n\n for (const [name, preset] of Object.entries(presets)) {\n if (RESERVED_PRESET_NAMES.has(name)) {\n throw new Error(\n `Invalid typography preset name \"${name}\". This name is reserved as a preset modifier.`,\n );\n }\n\n tokens[`$${name}-font-size`] = preset.fontSize;\n tokens[`$${name}-line-height`] = preset.lineHeight;\n tokens[`$${name}-letter-spacing`] = preset.letterSpacing ?? 'normal';\n tokens[`$${name}-font-weight`] = preset.fontWeight;\n\n if (preset.boldFontWeight !== undefined) {\n tokens[`$${name}-bold-font-weight`] = preset.boldFontWeight;\n }\n\n if (preset.iconSize !== undefined) {\n tokens[`$${name}-icon-size`] = preset.iconSize;\n }\n\n if (preset.textTransform !== undefined) {\n tokens[`$${name}-text-transform`] = preset.textTransform;\n }\n\n if (preset.fontFamily !== undefined) {\n tokens[`$${name}-font-family`] = preset.fontFamily;\n }\n\n if (preset.fontStyle !== undefined) {\n tokens[`$${name}-font-style`] = preset.fontStyle;\n }\n }\n\n return tokens;\n}\n"],"mappings":";AAEA,MAAM,wBAAwB,IAAI,IAAI;CACpC;CACA;CACA;CACA;CACA;CACD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;AA0DF,SAAgB,yBACd,SACc;CACd,MAAM,SAAuB,EAAE;AAE/B,MAAK,MAAM,CAAC,MAAM,WAAW,OAAO,QAAQ,QAAQ,EAAE;AACpD,MAAI,sBAAsB,IAAI,KAAK,CACjC,OAAM,IAAI,MACR,mCAAmC,KAAK,gDACzC;AAGH,SAAO,IAAI,KAAK,eAAe,OAAO;AACtC,SAAO,IAAI,KAAK,iBAAiB,OAAO;AACxC,SAAO,IAAI,KAAK,oBAAoB,OAAO,iBAAiB;AAC5D,SAAO,IAAI,KAAK,iBAAiB,OAAO;AAExC,MAAI,OAAO,mBAAmB,KAAA,EAC5B,QAAO,IAAI,KAAK,sBAAsB,OAAO;AAG/C,MAAI,OAAO,aAAa,KAAA,EACtB,QAAO,IAAI,KAAK,eAAe,OAAO;AAGxC,MAAI,OAAO,kBAAkB,KAAA,EAC3B,QAAO,IAAI,KAAK,oBAAoB,OAAO;AAG7C,MAAI,OAAO,eAAe,KAAA,EACxB,QAAO,IAAI,KAAK,iBAAiB,OAAO;AAG1C,MAAI,OAAO,cAAc,KAAA,EACvB,QAAO,IAAI,KAAK,gBAAgB,OAAO;;AAI3C,QAAO"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/utils/warnings.d.ts
|
|
2
|
+
declare function warn(...args: unknown[]): void;
|
|
3
|
+
declare function deprecationWarning(condition: unknown, {
|
|
4
|
+
property,
|
|
5
|
+
name,
|
|
6
|
+
betterAlternative,
|
|
7
|
+
reason
|
|
8
|
+
}: {
|
|
9
|
+
property: string;
|
|
10
|
+
name: string;
|
|
11
|
+
betterAlternative: (() => string) | string;
|
|
12
|
+
reason?: (() => string) | string;
|
|
13
|
+
}): void;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { deprecationWarning, warn };
|
|
16
|
+
//# sourceMappingURL=warnings.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/utils/warnings.ts
|
|
2
|
+
const PREFIX = "Tasty";
|
|
3
|
+
function warn(...args) {
|
|
4
|
+
console.warn(`${PREFIX}:`, ...args);
|
|
5
|
+
}
|
|
6
|
+
function deprecationWarning(condition, { property, name, betterAlternative, reason }) {
|
|
7
|
+
if (condition) return;
|
|
8
|
+
console.group(`⚠️ ${PREFIX}: Deprecation in ${name}`);
|
|
9
|
+
warn(`"${property}" is deprecated, consider better alternative: ${typeof betterAlternative === "function" ? betterAlternative() : betterAlternative}`);
|
|
10
|
+
if (reason) warn(`Reason: ${typeof reason === "function" ? reason() : reason}`);
|
|
11
|
+
console.groupEnd();
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { deprecationWarning, warn };
|
|
15
|
+
|
|
16
|
+
//# sourceMappingURL=warnings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"warnings.js","names":[],"sources":["../../src/utils/warnings.ts"],"sourcesContent":["/* eslint-disable no-console */\nconst PREFIX = 'Tasty';\n\nexport function warn(...args: unknown[]) {\n console.warn(`${PREFIX}:`, ...args);\n}\n\nexport function deprecationWarning(\n condition: unknown,\n {\n property,\n name,\n betterAlternative,\n reason,\n }: {\n property: string;\n name: string;\n betterAlternative: (() => string) | string;\n reason?: (() => string) | string;\n },\n) {\n if (condition) return;\n\n if (process.env.NODE_ENV === 'production') {\n return warn(\n `DEPRECATION ${name} \"${property}\" -> ${\n typeof betterAlternative === 'function'\n ? betterAlternative()\n : betterAlternative\n }`,\n );\n }\n\n // we can make deprecations even better if we add the md syntax in the console.\n // anyway, everything down below will be stripped in the production build\n console.group(`⚠️ ${PREFIX}: Deprecation in ${name}`);\n warn(\n `\"${property}\" is deprecated, consider better alternative: ${\n typeof betterAlternative === 'function'\n ? betterAlternative()\n : betterAlternative\n }`,\n );\n if (reason) {\n warn(`Reason: ${typeof reason === 'function' ? reason() : reason}`);\n }\n console.groupEnd();\n}\n"],"mappings":";AACA,MAAM,SAAS;AAEf,SAAgB,KAAK,GAAG,MAAiB;AACvC,SAAQ,KAAK,GAAG,OAAO,IAAI,GAAG,KAAK;;AAGrC,SAAgB,mBACd,WACA,EACE,UACA,MACA,mBACA,UAOF;AACA,KAAI,UAAW;AAcf,SAAQ,MAAM,MAAM,OAAO,mBAAmB,OAAO;AACrD,MACE,IAAI,SAAS,gDACX,OAAO,sBAAsB,aACzB,mBAAmB,GACnB,oBAEP;AACD,KAAI,OACF,MAAK,WAAW,OAAO,WAAW,aAAa,QAAQ,GAAG,SAAS;AAErE,SAAQ,UAAU"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { TastyConfig } from "../config.js";
|
|
2
|
+
import * as _$_babel_core0 from "@babel/core";
|
|
3
|
+
import { PluginPass } from "@babel/core";
|
|
4
|
+
|
|
5
|
+
//#region src/zero/babel.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Build-time configuration for zero-runtime mode.
|
|
8
|
+
* Subset of TastyConfig excluding runtime-only DOM options
|
|
9
|
+
* (`nonce`, `maxRulesPerSheet`, `forceTextInjection`, `gc`)
|
|
10
|
+
* and overriding `devMode` default to `false`.
|
|
11
|
+
*/
|
|
12
|
+
type TastyZeroConfig = Omit<TastyConfig, 'nonce' | 'maxRulesPerSheet' | 'forceTextInjection' | 'gc' | 'devMode'> & {
|
|
13
|
+
/**
|
|
14
|
+
* Enable development mode features: source comments in generated CSS.
|
|
15
|
+
* @default false
|
|
16
|
+
*/
|
|
17
|
+
devMode?: boolean;
|
|
18
|
+
};
|
|
19
|
+
interface TastyZeroBabelOptions {
|
|
20
|
+
/** Output path for generated CSS (default: 'tasty.css') */
|
|
21
|
+
output?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Tasty configuration for build-time processing.
|
|
24
|
+
* Can be a static object or a factory function that returns fresh config.
|
|
25
|
+
* A factory is called on each plugin invocation, enabling hot reload
|
|
26
|
+
* of config values that depend on external files (e.g. theme tokens).
|
|
27
|
+
*/
|
|
28
|
+
config?: TastyZeroConfig | (() => TastyZeroConfig);
|
|
29
|
+
/**
|
|
30
|
+
* Absolute path to a TypeScript/JavaScript module that default-exports
|
|
31
|
+
* a `TastyZeroConfig` object. The module is loaded via jiti on each
|
|
32
|
+
* plugin invocation, enabling hot reload when the file changes.
|
|
33
|
+
*
|
|
34
|
+
* This option is JSON-serializable and is the primary way Turbopack
|
|
35
|
+
* passes config to the Babel plugin (since Turbopack loader options
|
|
36
|
+
* must be plain primitives/objects/arrays).
|
|
37
|
+
*
|
|
38
|
+
* When both `config` and `configFile` are set, `config` takes precedence.
|
|
39
|
+
*
|
|
40
|
+
* @example '/absolute/path/to/tasty-zero.config.ts'
|
|
41
|
+
*/
|
|
42
|
+
configFile?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Absolute file paths whose content affects the generated CSS.
|
|
45
|
+
* When any of these files change, babel-loader invalidates its cache
|
|
46
|
+
* and re-runs the plugin with fresh config values.
|
|
47
|
+
*
|
|
48
|
+
* Typically includes theme files that define Glaze palettes or token values.
|
|
49
|
+
* Paths must be absolute (resolved by the Next.js wrapper).
|
|
50
|
+
*/
|
|
51
|
+
configDeps?: string[];
|
|
52
|
+
/**
|
|
53
|
+
* Automatically replace `@tenphi/tasty/static` imports with an import
|
|
54
|
+
* of the generated CSS file. This eliminates the need for users to
|
|
55
|
+
* manually import the CSS in their app entry point.
|
|
56
|
+
*
|
|
57
|
+
* @default true
|
|
58
|
+
*/
|
|
59
|
+
injectImport?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Output mode for extracted CSS.
|
|
62
|
+
*
|
|
63
|
+
* - `'file'` (default): CSS is written to a single output file and
|
|
64
|
+
* the `@tenphi/tasty/static` import is rewritten to import that file.
|
|
65
|
+
* - `'inject'`: CSS is embedded inline in the JS output and injected
|
|
66
|
+
* at runtime via a tiny injector from `@tenphi/tasty/static/inject`.
|
|
67
|
+
* No CSS file is written. Each `tastyStatic` call becomes
|
|
68
|
+
* self-contained. Best for reusable components and extensions.
|
|
69
|
+
*
|
|
70
|
+
* When `mode` is `'inject'`, `output` and `injectImport` are ignored.
|
|
71
|
+
*
|
|
72
|
+
* @default 'file'
|
|
73
|
+
*/
|
|
74
|
+
mode?: 'file' | 'inject';
|
|
75
|
+
}
|
|
76
|
+
/** Clear the shared CSSWriter cache. Exposed for testing. */
|
|
77
|
+
declare function clearWriterCache(): void;
|
|
78
|
+
declare const _default: (api: object, options: TastyZeroBabelOptions | null | undefined, dirname: string) => _$_babel_core0.PluginObj<PluginPass>;
|
|
79
|
+
//#endregion
|
|
80
|
+
export { TastyZeroBabelOptions, TastyZeroConfig, clearWriterCache, _default as default };
|
|
81
|
+
//# sourceMappingURL=babel.d.ts.map
|
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
import { __require } from "../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { configure, getGlobalConfigTokens, getGlobalStyles, resetConfig } from "../config.js";
|
|
3
|
+
import { mergeStyles } from "../utils/merge-styles.js";
|
|
4
|
+
import { resolveRecipes } from "../utils/resolve-recipes.js";
|
|
5
|
+
import { extractCounterStyleFromStyles, extractFontFaceFromStyles, extractKeyframesFromStyles, extractPropertiesFromStyles, extractStylesForSelector, extractStylesWithChunks } from "./extractor.js";
|
|
6
|
+
import { CSSWriter } from "./css-writer.js";
|
|
7
|
+
import * as fs from "fs";
|
|
8
|
+
import * as path from "path";
|
|
9
|
+
import { declare } from "@babel/helper-plugin-utils";
|
|
10
|
+
import * as t from "@babel/types";
|
|
11
|
+
import { createJiti } from "jiti";
|
|
12
|
+
//#region src/zero/babel.ts
|
|
13
|
+
/**
|
|
14
|
+
* Babel plugin for zero-runtime tasty static site generation.
|
|
15
|
+
*
|
|
16
|
+
* Transforms:
|
|
17
|
+
* - `tastyStatic(styles)` → StaticStyle object { className, styles, toString() }
|
|
18
|
+
* - `tastyStatic(base, styles)` → StaticStyle object with merged styles
|
|
19
|
+
* - `tastyStatic(selector, styles)` → removed entirely
|
|
20
|
+
*
|
|
21
|
+
* Usage:
|
|
22
|
+
* ```javascript
|
|
23
|
+
* // babel.config.js
|
|
24
|
+
* module.exports = {
|
|
25
|
+
* plugins: [
|
|
26
|
+
* ['@tenphi/tasty/babel-plugin', { output: 'public/tasty.css' }]
|
|
27
|
+
* ]
|
|
28
|
+
* };
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
function mtime(filePath) {
|
|
32
|
+
try {
|
|
33
|
+
return fs.statSync(filePath).mtimeMs;
|
|
34
|
+
} catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function clearRequireCacheTree(filePath) {
|
|
39
|
+
let resolved;
|
|
40
|
+
try {
|
|
41
|
+
resolved = __require.resolve(filePath);
|
|
42
|
+
} catch {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const mod = __require.cache[resolved];
|
|
46
|
+
if (!mod) return;
|
|
47
|
+
const dir = resolved.substring(0, resolved.lastIndexOf("/"));
|
|
48
|
+
if (mod.children) {
|
|
49
|
+
for (const child of mod.children) if (child.id.startsWith(dir) && !child.id.includes("node_modules")) clearRequireCacheTree(child.id);
|
|
50
|
+
}
|
|
51
|
+
delete __require.cache[resolved];
|
|
52
|
+
}
|
|
53
|
+
const writerCache = /* @__PURE__ */ new Map();
|
|
54
|
+
/** Clear the shared CSSWriter cache. Exposed for testing. */
|
|
55
|
+
function clearWriterCache() {
|
|
56
|
+
writerCache.clear();
|
|
57
|
+
}
|
|
58
|
+
var babel_default = declare((api, options) => {
|
|
59
|
+
api.assertVersion(7);
|
|
60
|
+
const mode = options.mode ?? "file";
|
|
61
|
+
const outputPath = options.output || "tasty.css";
|
|
62
|
+
const resolvedOutputPath = path.resolve(outputPath);
|
|
63
|
+
const injectImport = options.injectImport ?? true;
|
|
64
|
+
if (mode === "file" && injectImport) {
|
|
65
|
+
const dir = path.dirname(resolvedOutputPath);
|
|
66
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
67
|
+
if (!fs.existsSync(resolvedOutputPath)) fs.writeFileSync(resolvedOutputPath, "/* Generated by @tenphi/tasty/zero - DO NOT EDIT */\n");
|
|
68
|
+
}
|
|
69
|
+
const configDeps = [...options.configFile ? [options.configFile] : [], ...options.configDeps || []];
|
|
70
|
+
const configKey = configDeps.length > 0 ? configDeps.map(mtime).join(",") : "";
|
|
71
|
+
if (configDeps.length > 0) {
|
|
72
|
+
api.cache.using(() => configKey);
|
|
73
|
+
for (const dep of configDeps) try {
|
|
74
|
+
api.addExternalDependency(dep);
|
|
75
|
+
} catch {}
|
|
76
|
+
} else api.cache.forever();
|
|
77
|
+
if (configDeps.length > 0) for (const dep of configDeps) clearRequireCacheTree(dep);
|
|
78
|
+
const cached = writerCache.get(resolvedOutputPath);
|
|
79
|
+
if (!cached || cached.configKey !== configKey) {
|
|
80
|
+
const configOption = options.config;
|
|
81
|
+
let resolvedConfig;
|
|
82
|
+
if (configOption) resolvedConfig = typeof configOption === "function" ? configOption() : configOption;
|
|
83
|
+
else if (options.configFile) resolvedConfig = createJiti(path.dirname(options.configFile), { moduleCache: false })(options.configFile);
|
|
84
|
+
else resolvedConfig = {};
|
|
85
|
+
const devMode = resolvedConfig.devMode ?? false;
|
|
86
|
+
if (cached) resetConfig();
|
|
87
|
+
configure(resolvedConfig);
|
|
88
|
+
const newWriter = new CSSWriter(outputPath, { devMode });
|
|
89
|
+
if (mode !== "inject") {
|
|
90
|
+
const tokenCSS = extractCSSFromStyles(":root", getGlobalConfigTokens());
|
|
91
|
+
if (tokenCSS) newWriter.add(":root:tokens", tokenCSS);
|
|
92
|
+
const globalStyles = getGlobalStyles();
|
|
93
|
+
if (globalStyles) for (const [selector, styles] of Object.entries(globalStyles)) {
|
|
94
|
+
const css = extractCSSFromStyles(selector, styles);
|
|
95
|
+
if (css) newWriter.add(`global:${selector}`, css);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
writerCache.set(resolvedOutputPath, {
|
|
99
|
+
writer: newWriter,
|
|
100
|
+
configKey,
|
|
101
|
+
registry: {},
|
|
102
|
+
config: resolvedConfig
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
const entry = writerCache.get(resolvedOutputPath);
|
|
106
|
+
const cssWriter = entry.writer;
|
|
107
|
+
const globalRegistry = entry.registry;
|
|
108
|
+
const config = entry.config;
|
|
109
|
+
const devMode = config.devMode ?? false;
|
|
110
|
+
let tokenCSS;
|
|
111
|
+
let globalStylesCSS;
|
|
112
|
+
if (mode === "inject") {
|
|
113
|
+
tokenCSS = extractCSSFromStyles(":root", getGlobalConfigTokens());
|
|
114
|
+
const gs = getGlobalStyles();
|
|
115
|
+
if (gs) {
|
|
116
|
+
globalStylesCSS = /* @__PURE__ */ new Map();
|
|
117
|
+
for (const [selector, styles] of Object.entries(gs)) {
|
|
118
|
+
const css = extractCSSFromStyles(selector, styles);
|
|
119
|
+
if (css) globalStylesCSS.set(selector, css);
|
|
120
|
+
}
|
|
121
|
+
if (globalStylesCSS.size === 0) globalStylesCSS = void 0;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
name: "tasty-zero",
|
|
126
|
+
pre() {
|
|
127
|
+
this.staticStyleRegistry = {};
|
|
128
|
+
this._fileAddedCSS = false;
|
|
129
|
+
if (devMode && this.filename) this.sourceFile = this.filename.split("/").pop() || this.filename;
|
|
130
|
+
},
|
|
131
|
+
visitor: {
|
|
132
|
+
ImportDeclaration(nodePath, state) {
|
|
133
|
+
const source = nodePath.node.source.value;
|
|
134
|
+
if (source === "@tenphi/tasty/static" || source.endsWith("/tasty/static")) if (mode === "inject") nodePath.replaceWith(t.importDeclaration([t.importSpecifier(t.identifier("_$i"), t.identifier("injectCSS"))], t.stringLiteral("@tenphi/tasty/static/inject")));
|
|
135
|
+
else if (injectImport) {
|
|
136
|
+
let importPath = resolvedOutputPath;
|
|
137
|
+
if (state.filename) {
|
|
138
|
+
const sourceDir = path.dirname(state.filename);
|
|
139
|
+
importPath = path.relative(sourceDir, resolvedOutputPath);
|
|
140
|
+
if (!importPath.startsWith(".")) importPath = "./" + importPath;
|
|
141
|
+
}
|
|
142
|
+
nodePath.replaceWith(t.importDeclaration([], t.stringLiteral(importPath)));
|
|
143
|
+
} else nodePath.remove();
|
|
144
|
+
},
|
|
145
|
+
CallExpression(path, state) {
|
|
146
|
+
const callee = path.node.callee;
|
|
147
|
+
if (!t.isIdentifier(callee, { name: "tastyStatic" })) return;
|
|
148
|
+
state._fileAddedCSS = true;
|
|
149
|
+
const args = path.node.arguments;
|
|
150
|
+
if (args.length === 0) throw path.buildCodeFrameError("tastyStatic() requires at least one argument");
|
|
151
|
+
const firstArg = args[0];
|
|
152
|
+
if (t.isStringLiteral(firstArg)) handleSelectorMode(path, args, cssWriter, mode, state.sourceFile, config.keyframes, config.autoPropertyTypes, config.fontFace, config.counterStyle);
|
|
153
|
+
else if (t.isObjectExpression(firstArg)) handleStylesMode(path, args, cssWriter, state, globalRegistry, mode, config.keyframes, config.autoPropertyTypes, config.fontFace, config.counterStyle);
|
|
154
|
+
else if (t.isIdentifier(firstArg)) handleExtensionMode(path, args, cssWriter, state, globalRegistry, mode, config.keyframes, config.autoPropertyTypes, config.fontFace, config.counterStyle);
|
|
155
|
+
else throw path.buildCodeFrameError("tastyStatic() first argument must be an object (styles), identifier (base StaticStyle), or string (selector)");
|
|
156
|
+
},
|
|
157
|
+
VariableDeclarator(path, state) {
|
|
158
|
+
const init = path.node.init;
|
|
159
|
+
const id = path.node.id;
|
|
160
|
+
if (t.isIdentifier(id) && t.isObjectExpression(init) && isStaticStyleObject(init)) {
|
|
161
|
+
const variableName = id.name;
|
|
162
|
+
const styles = extractStylesFromStaticStyleObject(init, path);
|
|
163
|
+
const className = extractClassNameFromStaticStyleObject(init);
|
|
164
|
+
if (styles && className) {
|
|
165
|
+
state.staticStyleRegistry[variableName] = {
|
|
166
|
+
styles,
|
|
167
|
+
className
|
|
168
|
+
};
|
|
169
|
+
globalRegistry[variableName] = {
|
|
170
|
+
styles,
|
|
171
|
+
className
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
post() {
|
|
178
|
+
if (mode === "inject") {
|
|
179
|
+
if (this._fileAddedCSS && (tokenCSS || globalStylesCSS)) {
|
|
180
|
+
const program = this.file.ast.program;
|
|
181
|
+
let insertIndex = 0;
|
|
182
|
+
for (let i = 0; i < program.body.length; i++) if (t.isImportDeclaration(program.body[i])) insertIndex = i + 1;
|
|
183
|
+
if (tokenCSS) {
|
|
184
|
+
const injectCall = createInjectCallAST(":root", tokenCSS);
|
|
185
|
+
program.body.splice(insertIndex, 0, t.expressionStatement(injectCall));
|
|
186
|
+
insertIndex++;
|
|
187
|
+
}
|
|
188
|
+
if (globalStylesCSS) for (const [selector, css] of globalStylesCSS) {
|
|
189
|
+
const injectCall = createInjectCallAST(selector, css);
|
|
190
|
+
program.body.splice(insertIndex, 0, t.expressionStatement(injectCall));
|
|
191
|
+
insertIndex++;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (this._fileAddedCSS && cssWriter.size > 0) cssWriter.write();
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
});
|
|
200
|
+
/**
|
|
201
|
+
* Check if an object expression looks like a StaticStyle object
|
|
202
|
+
*/
|
|
203
|
+
function isStaticStyleObject(node) {
|
|
204
|
+
const hasClassName = node.properties.some((p) => t.isObjectProperty(p) && t.isIdentifier(p.key, { name: "className" }));
|
|
205
|
+
const hasStyles = node.properties.some((p) => t.isObjectProperty(p) && t.isIdentifier(p.key, { name: "styles" }));
|
|
206
|
+
return hasClassName && hasStyles;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Extract styles object from a StaticStyle object expression
|
|
210
|
+
*/
|
|
211
|
+
function extractStylesFromStaticStyleObject(node, path) {
|
|
212
|
+
for (const prop of node.properties) if (t.isObjectProperty(prop) && t.isIdentifier(prop.key, { name: "styles" }) && t.isObjectExpression(prop.value)) return evaluateObjectExpression(prop.value, path);
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Extract className from a StaticStyle object expression
|
|
217
|
+
*/
|
|
218
|
+
function extractClassNameFromStaticStyleObject(node) {
|
|
219
|
+
for (const prop of node.properties) if (t.isObjectProperty(prop) && t.isIdentifier(prop.key, { name: "className" }) && t.isStringLiteral(prop.value)) return prop.value.value;
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Handle tastyStatic(styles) - returns StaticStyle object
|
|
224
|
+
*/
|
|
225
|
+
function handleStylesMode(path, args, cssWriter, state, globalRegistry, mode, globalKeyframes, autoPropertyTypes, globalFontFace, globalCounterStyle) {
|
|
226
|
+
const stylesArg = args[0];
|
|
227
|
+
if (!t.isObjectExpression(stylesArg)) throw path.buildCodeFrameError("tastyStatic(styles) argument must be a static object literal");
|
|
228
|
+
const styles = resolveRecipes(evaluateObjectExpression(stylesArg, path));
|
|
229
|
+
const { keyframes, nameMap } = extractKeyframesFromStyles(styles, globalKeyframes);
|
|
230
|
+
const properties = extractPropertiesFromStyles(styles, { autoPropertyTypes });
|
|
231
|
+
const fontFaces = extractFontFaceFromStyles(styles, globalFontFace);
|
|
232
|
+
const counterStyles = extractCounterStyleFromStyles(styles, globalCounterStyle);
|
|
233
|
+
const chunks = extractStylesWithChunks(styles);
|
|
234
|
+
const className = chunks.length > 0 ? chunks.map((c) => c.className).join(" ") : "";
|
|
235
|
+
const staticStyleObject = createStaticStyleAST(className, styles);
|
|
236
|
+
if (mode === "inject") {
|
|
237
|
+
const injectCall = createInjectCallAST(className, collectAllCSS(keyframes, properties, fontFaces, counterStyles, chunks, nameMap));
|
|
238
|
+
path.replaceWith(t.sequenceExpression([injectCall, staticStyleObject]));
|
|
239
|
+
} else {
|
|
240
|
+
writeCSSToWriter(cssWriter, keyframes, properties, fontFaces, counterStyles, chunks, nameMap, state.sourceFile);
|
|
241
|
+
path.replaceWith(staticStyleObject);
|
|
242
|
+
}
|
|
243
|
+
registerIfVariableDeclaration(path, className, styles, state, globalRegistry);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Handle tastyStatic(base, styles) - extends base with additional styles
|
|
247
|
+
*/
|
|
248
|
+
function handleExtensionMode(path, args, cssWriter, state, globalRegistry, mode, globalKeyframes, autoPropertyTypes, globalFontFace, globalCounterStyle) {
|
|
249
|
+
if (args.length < 2) throw path.buildCodeFrameError("tastyStatic(base, styles) requires two arguments");
|
|
250
|
+
const baseArg = args[0];
|
|
251
|
+
const stylesArg = args[1];
|
|
252
|
+
if (!t.isIdentifier(baseArg)) throw path.buildCodeFrameError("tastyStatic(base, styles) first argument must be an identifier");
|
|
253
|
+
if (!t.isObjectExpression(stylesArg)) throw path.buildCodeFrameError("tastyStatic(base, styles) second argument must be a static object literal");
|
|
254
|
+
const baseName = baseArg.name;
|
|
255
|
+
const baseEntry = state.staticStyleRegistry[baseName] || globalRegistry[baseName];
|
|
256
|
+
if (!baseEntry) throw path.buildCodeFrameError(`Cannot find base StaticStyle '${baseName}'. Make sure it is defined before being extended.`);
|
|
257
|
+
const overrideStyles = evaluateObjectExpression(stylesArg, path);
|
|
258
|
+
const mergedStyles = resolveRecipes(mergeStyles(baseEntry.styles, overrideStyles));
|
|
259
|
+
const { keyframes, nameMap } = extractKeyframesFromStyles(mergedStyles, globalKeyframes);
|
|
260
|
+
const properties = extractPropertiesFromStyles(mergedStyles, { autoPropertyTypes });
|
|
261
|
+
const fontFaces = extractFontFaceFromStyles(mergedStyles, globalFontFace);
|
|
262
|
+
const counterStyles = extractCounterStyleFromStyles(mergedStyles, globalCounterStyle);
|
|
263
|
+
const chunks = extractStylesWithChunks(mergedStyles);
|
|
264
|
+
const className = chunks.length > 0 ? chunks.map((c) => c.className).join(" ") : "";
|
|
265
|
+
const staticStyleObject = createStaticStyleAST(className, mergedStyles);
|
|
266
|
+
if (mode === "inject") {
|
|
267
|
+
const injectCall = createInjectCallAST(className, collectAllCSS(keyframes, properties, fontFaces, counterStyles, chunks, nameMap));
|
|
268
|
+
path.replaceWith(t.sequenceExpression([injectCall, staticStyleObject]));
|
|
269
|
+
} else {
|
|
270
|
+
writeCSSToWriter(cssWriter, keyframes, properties, fontFaces, counterStyles, chunks, nameMap, state.sourceFile);
|
|
271
|
+
path.replaceWith(staticStyleObject);
|
|
272
|
+
}
|
|
273
|
+
registerIfVariableDeclaration(path, className, mergedStyles, state, globalRegistry);
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Handle tastyStatic(selector, styles) - removes the call entirely
|
|
277
|
+
*/
|
|
278
|
+
function handleSelectorMode(path, args, cssWriter, mode, sourceFile, globalKeyframes, autoPropertyTypes, globalFontFace, globalCounterStyle) {
|
|
279
|
+
if (args.length < 2) throw path.buildCodeFrameError("tastyStatic(selector, styles) requires two arguments");
|
|
280
|
+
const selectorArg = args[0];
|
|
281
|
+
const stylesArg = args[1];
|
|
282
|
+
if (!t.isStringLiteral(selectorArg)) throw path.buildCodeFrameError("tastyStatic(selector, styles) first argument must be a string literal");
|
|
283
|
+
if (!t.isObjectExpression(stylesArg)) throw path.buildCodeFrameError("tastyStatic(selector, styles) second argument must be a static object literal");
|
|
284
|
+
const selector = selectorArg.value;
|
|
285
|
+
const styles = resolveRecipes(evaluateObjectExpression(stylesArg, path));
|
|
286
|
+
const { keyframes, nameMap } = extractKeyframesFromStyles(styles, globalKeyframes);
|
|
287
|
+
const properties = extractPropertiesFromStyles(styles, { autoPropertyTypes });
|
|
288
|
+
const fontFaces = extractFontFaceFromStyles(styles, globalFontFace);
|
|
289
|
+
const counterStyles = extractCounterStyleFromStyles(styles, globalCounterStyle);
|
|
290
|
+
const result = extractStylesForSelector(selector, styles);
|
|
291
|
+
const selectorCSS = nameMap.size > 0 ? replaceAnimationNamesInCSS(result.css, nameMap) : result.css;
|
|
292
|
+
if (mode === "inject") {
|
|
293
|
+
const cssParts = [];
|
|
294
|
+
for (const kf of keyframes) cssParts.push(kf.css);
|
|
295
|
+
for (const prop of properties) cssParts.push(prop.css);
|
|
296
|
+
for (const ff of fontFaces) cssParts.push(ff.css);
|
|
297
|
+
for (const cs of counterStyles) cssParts.push(cs.css);
|
|
298
|
+
cssParts.push(selectorCSS);
|
|
299
|
+
const injectCall = createInjectCallAST(selector, cssParts.join("\n"));
|
|
300
|
+
const parent = path.parentPath;
|
|
301
|
+
if (parent && t.isExpressionStatement(parent.node)) parent.replaceWith(t.expressionStatement(injectCall));
|
|
302
|
+
else path.replaceWith(injectCall);
|
|
303
|
+
} else {
|
|
304
|
+
writeCSSToWriter(cssWriter, keyframes, properties, fontFaces, counterStyles, [], nameMap, sourceFile);
|
|
305
|
+
cssWriter.add(selector, selectorCSS, sourceFile);
|
|
306
|
+
const parent = path.parentPath;
|
|
307
|
+
if (parent && t.isExpressionStatement(parent.node)) parent.remove();
|
|
308
|
+
else path.replaceWith(t.identifier("undefined"));
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Collect all extracted CSS parts into a single string (for inject mode).
|
|
313
|
+
*/
|
|
314
|
+
function collectAllCSS(keyframes, properties, fontFaces, counterStyles, chunks, nameMap) {
|
|
315
|
+
const parts = [];
|
|
316
|
+
for (const kf of keyframes) parts.push(kf.css);
|
|
317
|
+
for (const prop of properties) parts.push(prop.css);
|
|
318
|
+
for (const ff of fontFaces) parts.push(ff.css);
|
|
319
|
+
for (const cs of counterStyles) parts.push(cs.css);
|
|
320
|
+
for (const chunk of chunks) parts.push(nameMap.size > 0 ? replaceAnimationNamesInCSS(chunk.css, nameMap) : chunk.css);
|
|
321
|
+
return parts.join("\n");
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Write all extracted CSS parts to a CSSWriter (for file mode).
|
|
325
|
+
*/
|
|
326
|
+
function writeCSSToWriter(cssWriter, keyframes, properties, fontFaces, counterStyles, chunks, nameMap, sourceFile) {
|
|
327
|
+
for (const kf of keyframes) cssWriter.add(kf.css, kf.css, sourceFile);
|
|
328
|
+
for (const prop of properties) cssWriter.add(prop.css, prop.css, sourceFile);
|
|
329
|
+
for (const ff of fontFaces) cssWriter.add(ff.css, ff.css, sourceFile);
|
|
330
|
+
for (const cs of counterStyles) cssWriter.add(cs.css, cs.css, sourceFile);
|
|
331
|
+
for (const chunk of chunks) {
|
|
332
|
+
const css = nameMap.size > 0 ? replaceAnimationNamesInCSS(chunk.css, nameMap) : chunk.css;
|
|
333
|
+
cssWriter.add(chunk.className, css, sourceFile);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Extract CSS for a selector from a styles/tokens object.
|
|
338
|
+
* Returns undefined when there are no styles or no CSS output.
|
|
339
|
+
*/
|
|
340
|
+
function extractCSSFromStyles(selector, styles) {
|
|
341
|
+
if (!styles || Object.keys(styles).length === 0) return void 0;
|
|
342
|
+
return extractStylesForSelector(selector, styles).css || void 0;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Create an `_$i(id, css)` call expression AST node for inject mode.
|
|
346
|
+
*/
|
|
347
|
+
function createInjectCallAST(id, css) {
|
|
348
|
+
return t.callExpression(t.identifier("_$i"), [t.stringLiteral(id), t.stringLiteral(css)]);
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Create a StaticStyle object AST node
|
|
352
|
+
*/
|
|
353
|
+
function createStaticStyleAST(className, styles) {
|
|
354
|
+
return t.objectExpression([
|
|
355
|
+
t.objectProperty(t.identifier("className"), t.stringLiteral(className)),
|
|
356
|
+
t.objectProperty(t.identifier("styles"), valueToAST(styles)),
|
|
357
|
+
t.objectMethod("method", t.identifier("toString"), [], t.blockStatement([t.returnStatement(t.memberExpression(t.thisExpression(), t.identifier("className")))]))
|
|
358
|
+
]);
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Register a StaticStyle in the registry if it's being assigned to a variable
|
|
362
|
+
*/
|
|
363
|
+
function registerIfVariableDeclaration(path, className, styles, state, globalRegistry) {
|
|
364
|
+
const parent = path.parentPath;
|
|
365
|
+
if (parent && t.isVariableDeclarator(parent.node)) {
|
|
366
|
+
const id = parent.node.id;
|
|
367
|
+
if (t.isIdentifier(id)) {
|
|
368
|
+
const variableName = id.name;
|
|
369
|
+
state.staticStyleRegistry[variableName] = {
|
|
370
|
+
styles,
|
|
371
|
+
className
|
|
372
|
+
};
|
|
373
|
+
globalRegistry[variableName] = {
|
|
374
|
+
styles,
|
|
375
|
+
className
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Convert a JavaScript value to an AST node
|
|
382
|
+
*/
|
|
383
|
+
function valueToAST(value) {
|
|
384
|
+
if (value === null) return t.nullLiteral();
|
|
385
|
+
if (value === void 0) return t.identifier("undefined");
|
|
386
|
+
if (typeof value === "string") return t.stringLiteral(value);
|
|
387
|
+
if (typeof value === "number") return t.numericLiteral(value);
|
|
388
|
+
if (typeof value === "boolean") return t.booleanLiteral(value);
|
|
389
|
+
if (Array.isArray(value)) return t.arrayExpression(value.map(valueToAST));
|
|
390
|
+
if (typeof value === "object") {
|
|
391
|
+
const properties = Object.entries(value).map(([key, val]) => t.objectProperty(/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key) ? t.identifier(key) : t.stringLiteral(key), valueToAST(val)));
|
|
392
|
+
return t.objectExpression(properties);
|
|
393
|
+
}
|
|
394
|
+
return t.identifier("undefined");
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Evaluate an ObjectExpression to a plain JavaScript object.
|
|
398
|
+
* Only supports static values that can be determined at build time.
|
|
399
|
+
*/
|
|
400
|
+
function evaluateObjectExpression(node, path) {
|
|
401
|
+
const result = {};
|
|
402
|
+
for (const prop of node.properties) {
|
|
403
|
+
if (t.isSpreadElement(prop)) throw path.buildCodeFrameError("Spread elements are not supported in tastyStatic() - styles must be fully static");
|
|
404
|
+
if (!t.isObjectProperty(prop)) throw path.buildCodeFrameError("Only object properties are supported in tastyStatic()");
|
|
405
|
+
let key;
|
|
406
|
+
if (t.isIdentifier(prop.key)) key = prop.key.name;
|
|
407
|
+
else if (t.isStringLiteral(prop.key)) key = prop.key.value;
|
|
408
|
+
else throw path.buildCodeFrameError("Dynamic property keys are not supported in tastyStatic()");
|
|
409
|
+
result[key] = evaluateExpression(prop.value, path);
|
|
410
|
+
}
|
|
411
|
+
return result;
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Evaluate an expression to a JavaScript value.
|
|
415
|
+
*/
|
|
416
|
+
function evaluateExpression(node, path) {
|
|
417
|
+
if (t.isStringLiteral(node)) return node.value;
|
|
418
|
+
if (t.isNumericLiteral(node)) return node.value;
|
|
419
|
+
if (t.isBooleanLiteral(node)) return node.value;
|
|
420
|
+
if (t.isNullLiteral(node)) return null;
|
|
421
|
+
if (t.isIdentifier(node, { name: "undefined" })) return;
|
|
422
|
+
if (t.isArrayExpression(node)) return node.elements.map((el) => {
|
|
423
|
+
if (el === null) return null;
|
|
424
|
+
if (t.isSpreadElement(el)) throw path.buildCodeFrameError("Spread elements are not supported in tastyStatic()");
|
|
425
|
+
return evaluateExpression(el, path);
|
|
426
|
+
});
|
|
427
|
+
if (t.isObjectExpression(node)) return evaluateObjectExpression(node, path);
|
|
428
|
+
if (t.isTemplateLiteral(node)) {
|
|
429
|
+
if (node.expressions.length > 0) throw path.buildCodeFrameError("Template literals with expressions are not supported in tastyStatic()");
|
|
430
|
+
return node.quasis.map((q) => q.value.cooked).join("");
|
|
431
|
+
}
|
|
432
|
+
if (t.isUnaryExpression(node, { operator: "-" })) {
|
|
433
|
+
const arg = evaluateExpression(node.argument, path);
|
|
434
|
+
if (typeof arg === "number") return -arg;
|
|
435
|
+
}
|
|
436
|
+
throw path.buildCodeFrameError(`Dynamic expressions are not supported in tastyStatic() - got ${node.type}. All values must be static literals.`);
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Replace animation names in CSS string.
|
|
440
|
+
* Wraps the keyframes replaceAnimationNames to work on full CSS blocks.
|
|
441
|
+
*/
|
|
442
|
+
function replaceAnimationNamesInCSS(css, nameMap) {
|
|
443
|
+
if (nameMap.size === 0) return css;
|
|
444
|
+
return css.replace(/(animation(?:-name)?)\s*:\s*([^;}]+)/gi, (match, prop, value) => {
|
|
445
|
+
let newValue = value;
|
|
446
|
+
for (const [original, replacement] of nameMap) {
|
|
447
|
+
const pattern = new RegExp(`\\b${escapeRegex(original)}\\b`, "g");
|
|
448
|
+
newValue = newValue.replace(pattern, replacement);
|
|
449
|
+
}
|
|
450
|
+
return `${prop}: ${newValue}`;
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Escape special regex characters.
|
|
455
|
+
*/
|
|
456
|
+
function escapeRegex(str) {
|
|
457
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
458
|
+
}
|
|
459
|
+
//#endregion
|
|
460
|
+
export { clearWriterCache, babel_default as default };
|
|
461
|
+
|
|
462
|
+
//# sourceMappingURL=babel.js.map
|