@upstart.gg/vite-plugins 0.1.27 → 0.1.29
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.
|
@@ -11,6 +11,8 @@ interface PluginOptions {
|
|
|
11
11
|
outputPath: string;
|
|
12
12
|
/** Google Fonts display parameter (default: 'swap') */
|
|
13
13
|
fontsDisplay?: "auto" | "block" | "swap" | "fallback" | "optional";
|
|
14
|
+
/** CSS framework to target (default: 'daisy-ui') */
|
|
15
|
+
cssFramework?: "daisy-ui" | "shadcn-ui";
|
|
14
16
|
}
|
|
15
17
|
/**
|
|
16
18
|
* Unplugin-based theme generator
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite-plugin-upstart-theme.d.ts","names":[],"sources":["../src/vite-plugin-upstart-theme.ts"],"mappings":";;;;UAWU,aAAA;EACR,MAAA;IACE,KAAA,EAAO,KAAA;IACP,IAAA,GAAO,KAAA;IACP,OAAA;EAAA;EAEF,UAAA;EALA;EAOA,YAAA;AAAA;;;;
|
|
1
|
+
{"version":3,"file":"vite-plugin-upstart-theme.d.ts","names":[],"sources":["../src/vite-plugin-upstart-theme.ts"],"mappings":";;;;UAWU,aAAA;EACR,MAAA;IACE,KAAA,EAAO,KAAA;IACP,IAAA,GAAO,KAAA;IACP,OAAA;EAAA;EAEF,UAAA;EALA;EAOA,YAAA;EANS;EAQT,YAAA;AAAA;;;;cA4VW,YAAA,EAAY,QAAA,CAAA,gBAAA,CAAA,aAAA;AAAA,cAoEtB,QAAA"}
|
|
@@ -100,7 +100,7 @@ function generateThemeBlock(lightTheme, darkTheme = null, defaultTheme = "light"
|
|
|
100
100
|
/**
|
|
101
101
|
* Generates @theme block for a single theme with colors and layout variables
|
|
102
102
|
*/
|
|
103
|
-
function generateThemeVariables(theme,
|
|
103
|
+
function generateThemeVariables(theme, defaultTheme) {
|
|
104
104
|
const processed = processTheme(theme);
|
|
105
105
|
const lines = [
|
|
106
106
|
` name: "${processed.id}";`,
|
|
@@ -127,6 +127,112 @@ function generateThemeVariables(theme, type, defaultTheme) {
|
|
|
127
127
|
return lines.join("\n");
|
|
128
128
|
}
|
|
129
129
|
/**
|
|
130
|
+
* Builds the CSS variable block for a single shadcn theme (`:root` or `.dark`)
|
|
131
|
+
*/
|
|
132
|
+
function buildShadcnVars(theme) {
|
|
133
|
+
const processed = processTheme(theme);
|
|
134
|
+
const { colors } = processed;
|
|
135
|
+
const monoFont = theme.typography?.others?.mono;
|
|
136
|
+
const monoFamilyValue = monoFont ? fontToCss(monoFont) : "ui-monospace, monospace";
|
|
137
|
+
const sansFamilyValue = theme.typography?.sans ? fontToCss(theme.typography.sans) : "ui-sans-serif, system-ui, sans-serif";
|
|
138
|
+
return [
|
|
139
|
+
["--radius", processed.radiusField],
|
|
140
|
+
["--background", colors.base100],
|
|
141
|
+
["--foreground", colors.baseContent],
|
|
142
|
+
["--card", colors.base200],
|
|
143
|
+
["--card-foreground", colors.baseContent],
|
|
144
|
+
["--popover", colors.base200],
|
|
145
|
+
["--popover-foreground", colors.baseContent],
|
|
146
|
+
["--primary", colors.primary],
|
|
147
|
+
["--primary-foreground", colors.primaryContent],
|
|
148
|
+
["--secondary", colors.secondary],
|
|
149
|
+
["--secondary-foreground", colors.secondaryContent],
|
|
150
|
+
["--muted", colors.neutral],
|
|
151
|
+
["--muted-foreground", colors.neutralContent],
|
|
152
|
+
["--accent", colors.base300],
|
|
153
|
+
["--accent-foreground", colors.baseContent],
|
|
154
|
+
["--destructive", colors.error],
|
|
155
|
+
["--border", colors.base300],
|
|
156
|
+
["--input", colors.base300],
|
|
157
|
+
["--ring", colors.primary],
|
|
158
|
+
["--chart-1", colors.primary],
|
|
159
|
+
["--chart-2", colors.secondary],
|
|
160
|
+
["--chart-3", colors.accent],
|
|
161
|
+
["--chart-4", colors.success],
|
|
162
|
+
["--chart-5", colors.warning],
|
|
163
|
+
["--sidebar", colors.base200],
|
|
164
|
+
["--sidebar-foreground", colors.baseContent],
|
|
165
|
+
["--sidebar-primary", colors.primary],
|
|
166
|
+
["--sidebar-primary-foreground", colors.primaryContent],
|
|
167
|
+
["--sidebar-accent", colors.base300],
|
|
168
|
+
["--sidebar-accent-foreground", colors.baseContent],
|
|
169
|
+
["--sidebar-border", colors.base300],
|
|
170
|
+
["--sidebar-ring", colors.primary],
|
|
171
|
+
["--font-sans", sansFamilyValue],
|
|
172
|
+
["--font-mono", monoFamilyValue]
|
|
173
|
+
].map(([k, v]) => ` ${k}: ${v};`).join("\n");
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Generates the full shadcn-compatible CSS output (no DaisyUI, no @plugin blocks).
|
|
177
|
+
* Uses :root for light theme and .dark for dark theme.
|
|
178
|
+
*/
|
|
179
|
+
function generateShadcnThemeCSS(lightTheme, darkTheme = null) {
|
|
180
|
+
const output = [];
|
|
181
|
+
output.push(`@theme inline {
|
|
182
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
183
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
184
|
+
--radius-lg: var(--radius);
|
|
185
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
186
|
+
--color-background: var(--background);
|
|
187
|
+
--color-foreground: var(--foreground);
|
|
188
|
+
--color-card: var(--card);
|
|
189
|
+
--color-card-foreground: var(--card-foreground);
|
|
190
|
+
--color-popover: var(--popover);
|
|
191
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
192
|
+
--color-primary: var(--primary);
|
|
193
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
194
|
+
--color-secondary: var(--secondary);
|
|
195
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
196
|
+
--color-muted: var(--muted);
|
|
197
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
198
|
+
--color-accent: var(--accent);
|
|
199
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
200
|
+
--color-destructive: var(--destructive);
|
|
201
|
+
--color-border: var(--border);
|
|
202
|
+
--color-input: var(--input);
|
|
203
|
+
--color-ring: var(--ring);
|
|
204
|
+
--color-chart-1: var(--chart-1);
|
|
205
|
+
--color-chart-2: var(--chart-2);
|
|
206
|
+
--color-chart-3: var(--chart-3);
|
|
207
|
+
--color-chart-4: var(--chart-4);
|
|
208
|
+
--color-chart-5: var(--chart-5);
|
|
209
|
+
--color-sidebar: var(--sidebar);
|
|
210
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
211
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
212
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
213
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
214
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
215
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
216
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
217
|
+
--font-sans: var(--font-sans);
|
|
218
|
+
--font-mono: var(--font-mono);
|
|
219
|
+
}`);
|
|
220
|
+
output.push("");
|
|
221
|
+
const lightSelector = !darkTheme && lightTheme.browserColorScheme === "dark" ? ":root, .dark" : ":root";
|
|
222
|
+
output.push(`/* ${lightTheme.name} theme */`);
|
|
223
|
+
output.push(`${lightSelector} {`);
|
|
224
|
+
output.push(buildShadcnVars(lightTheme));
|
|
225
|
+
output.push("}");
|
|
226
|
+
if (darkTheme && darkTheme.id !== lightTheme.id) {
|
|
227
|
+
output.push("");
|
|
228
|
+
output.push(`/* ${darkTheme.name} theme (dark) */`);
|
|
229
|
+
output.push(".dark {");
|
|
230
|
+
output.push(buildShadcnVars(darkTheme));
|
|
231
|
+
output.push("}");
|
|
232
|
+
}
|
|
233
|
+
return output.join("\n");
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
130
236
|
* Unplugin-based theme generator
|
|
131
237
|
*/
|
|
132
238
|
const upstartTheme = createUnplugin((opts) => {
|
|
@@ -143,28 +249,32 @@ const upstartTheme = createUnplugin((opts) => {
|
|
|
143
249
|
}
|
|
144
250
|
const outputDir = path.dirname(opts.outputPath);
|
|
145
251
|
if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true });
|
|
146
|
-
const { themes, fontsDisplay = "swap" } = opts;
|
|
252
|
+
const { themes, fontsDisplay = "swap", cssFramework = "daisy-ui" } = opts;
|
|
147
253
|
const fontsCSS = generateFontsCSS(themes.light, themes.dark, fontsDisplay);
|
|
148
254
|
const fontsCSSPath = path.join(outputDir, "fonts.css");
|
|
149
255
|
fs.writeFileSync(fontsCSSPath, fontsCSS);
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
output.push(
|
|
155
|
-
output.push("@plugin \"daisyui/theme\" {");
|
|
156
|
-
output.push(generateThemeVariables(themes.dark, "dark", themes.default));
|
|
157
|
-
output.push("}");
|
|
158
|
-
output.push("");
|
|
159
|
-
}
|
|
160
|
-
if (themes.light?.id !== themes.dark?.id) {
|
|
161
|
-
output.push("/* Light theme variables */");
|
|
162
|
-
output.push("@plugin \"daisyui/theme\" {");
|
|
163
|
-
output.push(generateThemeVariables(themes.light, "light", themes.default));
|
|
164
|
-
output.push("}");
|
|
256
|
+
let cssContent;
|
|
257
|
+
if (cssFramework === "shadcn-ui") cssContent = generateShadcnThemeCSS(themes.light, themes.dark ?? null);
|
|
258
|
+
else {
|
|
259
|
+
const output = [];
|
|
260
|
+
output.push(generateThemeBlock(themes.light, themes.dark));
|
|
165
261
|
output.push("");
|
|
262
|
+
if (themes.dark) {
|
|
263
|
+
output.push("/* Dark theme variables */");
|
|
264
|
+
output.push("@plugin \"daisyui/theme\" {");
|
|
265
|
+
output.push(generateThemeVariables(themes.dark, themes.default));
|
|
266
|
+
output.push("}");
|
|
267
|
+
output.push("");
|
|
268
|
+
}
|
|
269
|
+
if (themes.light?.id !== themes.dark?.id) {
|
|
270
|
+
output.push("/* Light theme variables */");
|
|
271
|
+
output.push("@plugin \"daisyui/theme\" {");
|
|
272
|
+
output.push(generateThemeVariables(themes.light, themes.default));
|
|
273
|
+
output.push("}");
|
|
274
|
+
output.push("");
|
|
275
|
+
}
|
|
276
|
+
cssContent = output.join("\n");
|
|
166
277
|
}
|
|
167
|
-
const cssContent = output.join("\n");
|
|
168
278
|
fs.writeFileSync(opts.outputPath, cssContent);
|
|
169
279
|
} }
|
|
170
280
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite-plugin-upstart-theme.js","names":[],"sources":["../src/vite-plugin-upstart-theme.ts"],"sourcesContent":["import { createUnplugin } from \"unplugin\";\nimport {\n GenericFont,\n GoogleFont,\n type Theme,\n fontStacksFonts,\n processTheme,\n} from \"@upstart.gg/sdk/themes/theme\";\nimport fs from \"fs\";\nimport path from \"path\";\n\ninterface PluginOptions {\n themes: {\n light: Theme;\n dark?: Theme;\n default: \"light\" | \"dark\";\n };\n outputPath: string;\n /** Google Fonts display parameter (default: 'swap') */\n fontsDisplay?: \"auto\" | \"block\" | \"swap\" | \"fallback\" | \"optional\";\n}\n\n/**\n * Collects Google Fonts from a theme's typography configuration\n */\nfunction collectGoogleFonts(theme: Theme) {\n const { typography } = theme;\n if (!typography) return [];\n\n const googleFonts: Array<GoogleFont> = [];\n const seen = new Set<string>();\n\n const addFont = (font?: GenericFont) => {\n if (font?.type === \"google\" && !seen.has(font.family)) {\n seen.add(font.family);\n googleFonts.push(font);\n }\n };\n\n addFont(typography.sans);\n addFont(typography.serif);\n if (typography.others) {\n Object.values(typography.others).forEach(addFont);\n }\n\n return googleFonts;\n}\n\n/**\n * Generates the fonts.css file content with Google Fonts imports\n */\nfunction generateFontsCSS(\n lightTheme: Theme,\n darkTheme: Theme | null = null,\n display: \"auto\" | \"block\" | \"swap\" | \"fallback\" | \"optional\" = \"swap\",\n): string {\n // Collect fonts from both themes\n const allFonts = new Map<string, GoogleFont>();\n\n for (const font of collectGoogleFonts(lightTheme)) {\n allFonts.set(font.family, font);\n }\n\n if (darkTheme) {\n for (const font of collectGoogleFonts(darkTheme)) {\n allFonts.set(font.family, font);\n }\n }\n\n if (allFonts.size === 0) {\n return \"/* No Google Fonts to import */\\n\";\n }\n\n // Build the Google Fonts URL\n const families = Array.from(allFonts.values()).map((font) => {\n const name = font.family.replace(/ /g, \"+\");\n if (font.weights && font.weights.length > 1 && font.weights[0] !== font.weights.at(-1)) {\n return `family=${name}:wght@${font.weights[0]}..${font.weights.at(-1)}`;\n }\n return `family=${name}`;\n });\n\n const url = `https://fonts.googleapis.com/css2?${families.join(\"&\")}&display=${display}`;\n\n return `/* Google Fonts - Auto-generated by vite-plugin-upstart-theme */\\n@import url(\"${url}\");\\n`;\n}\n\n/**\n * Converts a font definition to a CSS font-family string\n */\nfunction fontToCss(font: Theme[\"typography\"][\"sans\"]): string {\n if (!font) return \"\";\n\n if (font.type === \"stack\") {\n return fontStacksFonts[font.family];\n }\n\n if (font.type === \"google\") {\n // For Google fonts, we just use the family name\n // The actual font loading will be handled separately\n return `\"${font.family}\", system-ui, sans-serif`;\n }\n\n return \"\";\n}\n\n/**\n * Converts camelCase to kebab-case\n */\nfunction camelToKebab(str: string): string {\n return str.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\n}\n\n/**\n * Generates @theme block with font definitions\n */\nfunction generateThemeBlock(\n lightTheme: Theme,\n darkTheme: Theme | null = null,\n defaultTheme: \"light\" | \"dark\" = \"light\",\n): string {\n const fontDefinitions = new Map<string, string>();\n\n // Process light theme fonts\n const lightTypography = lightTheme.typography;\n\n // Add sans font\n if (lightTypography.sans) {\n const fontCss = fontToCss(lightTypography.sans);\n if (fontCss) {\n fontDefinitions.set(\"sans\", fontCss);\n }\n }\n\n // Add serif font\n if (lightTypography.serif) {\n const fontCss = fontToCss(lightTypography.serif);\n if (fontCss) {\n fontDefinitions.set(\"serif\", fontCss);\n }\n }\n\n // Add other fonts\n if (lightTypography.others) {\n for (const [name, font] of Object.entries(lightTypography.others)) {\n const fontCss = fontToCss(font);\n if (fontCss) {\n fontDefinitions.set(name, fontCss);\n }\n }\n }\n\n // Process dark theme fonts if provided\n if (darkTheme) {\n const darkTypography = darkTheme.typography;\n\n if (darkTypography.sans) {\n const fontCss = fontToCss(darkTypography.sans);\n if (fontCss) {\n fontDefinitions.set(\"sans\", fontCss);\n }\n }\n\n if (darkTypography.serif) {\n const fontCss = fontToCss(darkTypography.serif);\n if (fontCss) {\n fontDefinitions.set(\"serif\", fontCss);\n }\n }\n\n if (darkTypography.others) {\n for (const [name, font] of Object.entries(darkTypography.others)) {\n const fontCss = fontToCss(font);\n if (fontCss) {\n fontDefinitions.set(name, fontCss);\n }\n }\n }\n }\n\n const fontLines = Array.from(fontDefinitions.entries())\n .map(([name, value]) => ` --font-${name}: ${value};`)\n .join(\"\\n\");\n\n return `/* Fonts in the tailwind @theme block */\n@theme {\n ${fontLines}\n}\n\n/* Exclude properties since it produce warnings and is not important */\n@plugin \"daisyui\" {\n exclude: properties;\n themes: ${lightTheme.id} ${defaultTheme === \"light\" || !darkTheme ? \"--default\" : \"\"}${darkTheme?.id && darkTheme?.id !== lightTheme.id ? `, ${darkTheme.id} ${defaultTheme === \"dark\" ? \"--default\" : \"--prefersdark\"}` : \"\"};\n logs: true;\n}\n`;\n}\n\n//\n\n/**\n * Generates @theme block for a single theme with colors and layout variables\n */\nfunction generateThemeVariables(\n theme: Theme,\n type: \"light\" | \"dark\",\n defaultTheme: \"light\" | \"dark\",\n): string {\n const processed = processTheme(theme);\n const lines: string[] = [\n ` name: \"${processed.id}\";`,\n ` color-scheme: ${processed.browserColorScheme};`,\n ...((defaultTheme === \"dark\" && theme.browserColorScheme === \"dark\") ||\n (defaultTheme === \"light\" && theme.browserColorScheme === \"light\")\n ? [` default: true;`]\n : []),\n // ...(type === \"dark\" && defaultTheme !== \"dark\" ? [` prefersdark: true;`] : [` prefersdark: false;`]),\n ];\n\n // Color variables\n for (const [colorKey, colorValue] of Object.entries(processed.colors)) {\n const kebabKey = [\"base100\", \"base200\", \"base300\"].includes(colorKey)\n ? colorKey.replace(\"base\", \"base-\")\n : camelToKebab(colorKey);\n lines.push(` --color-${kebabKey}: ${colorValue};`);\n }\n\n lines.push(\"\");\n\n // Layout variables\n lines.push(` --radius-selector: ${processed.radiusSelector};`);\n lines.push(` --radius-field: ${processed.radiusField};`);\n lines.push(` --radius-box: ${processed.radiusBox};`);\n lines.push(` --size-selector: ${processed.sizeSelector};`);\n lines.push(` --size-field: ${processed.sizeField};`);\n lines.push(` --border: ${processed.border};`);\n lines.push(` --depth: ${processed.depth ? 1 : 0};`);\n lines.push(` --noise: 0;`);\n\n // return the generated lines\n return lines.join(\"\\n\");\n}\n\n/**\n * Unplugin-based theme generator\n */\nexport const upstartTheme = createUnplugin<PluginOptions>((opts) => {\n let generated = false;\n\n return {\n name: \"unplugin-theme-generator\",\n apply: \"serve\",\n\n vite: {\n configResolved() {\n // Generate the CSS file once when config is resolved\n if (generated) return;\n generated = true;\n\n if (!opts?.themes?.light) {\n console.warn(\"No light theme provided to unplugin-theme-generator. A light theme is required.\");\n return;\n }\n\n const outputDir = path.dirname(opts.outputPath);\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n\n const { themes, fontsDisplay = \"swap\" } = opts;\n\n // Generate fonts.css file\n const fontsCSS = generateFontsCSS(themes.light, themes.dark, fontsDisplay);\n const fontsCSSPath = path.join(outputDir, \"fonts.css\");\n fs.writeFileSync(fontsCSSPath, fontsCSS);\n\n const output: string[] = [];\n\n // Generate @theme block with fonts from both themes\n output.push(generateThemeBlock(themes.light, themes.dark));\n output.push(\"\");\n\n // IMPORTANT; Place dark theme first OTHERWISE daisyUI will not apply it correctly\n // @see https://github.com/saadeghi/daisyui/issues/3921#issuecomment-3059524563\n // Generate @theme block for dark theme if present\n if (themes.dark) {\n output.push(\"/* Dark theme variables */\");\n output.push('@plugin \"daisyui/theme\" {');\n output.push(generateThemeVariables(themes.dark, \"dark\", themes.default));\n output.push(\"}\");\n output.push(\"\");\n }\n\n // Generate @theme block for light theme\n if (themes.light?.id !== themes.dark?.id) {\n output.push(\"/* Light theme variables */\");\n output.push('@plugin \"daisyui/theme\" {');\n output.push(generateThemeVariables(themes.light, \"light\", themes.default));\n output.push(\"}\");\n output.push(\"\");\n }\n\n // Write the generated CSS file\n const cssContent = output.join(\"\\n\");\n fs.writeFileSync(opts.outputPath, cssContent);\n },\n },\n };\n});\n\nexport default upstartTheme.vite;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"vite-plugin-upstart-theme.js","names":[],"sources":["../src/vite-plugin-upstart-theme.ts"],"sourcesContent":["import { createUnplugin } from \"unplugin\";\nimport {\n GenericFont,\n GoogleFont,\n type Theme,\n fontStacksFonts,\n processTheme,\n} from \"@upstart.gg/sdk/themes/theme\";\nimport fs from \"fs\";\nimport path from \"path\";\n\ninterface PluginOptions {\n themes: {\n light: Theme;\n dark?: Theme;\n default: \"light\" | \"dark\";\n };\n outputPath: string;\n /** Google Fonts display parameter (default: 'swap') */\n fontsDisplay?: \"auto\" | \"block\" | \"swap\" | \"fallback\" | \"optional\";\n /** CSS framework to target (default: 'daisy-ui') */\n cssFramework?: \"daisy-ui\" | \"shadcn-ui\";\n}\n\n/**\n * Collects Google Fonts from a theme's typography configuration\n */\nfunction collectGoogleFonts(theme: Theme) {\n const { typography } = theme;\n if (!typography) return [];\n\n const googleFonts: Array<GoogleFont> = [];\n const seen = new Set<string>();\n\n const addFont = (font?: GenericFont) => {\n if (font?.type === \"google\" && !seen.has(font.family)) {\n seen.add(font.family);\n googleFonts.push(font);\n }\n };\n\n addFont(typography.sans);\n addFont(typography.serif);\n if (typography.others) {\n Object.values(typography.others).forEach(addFont);\n }\n\n return googleFonts;\n}\n\n/**\n * Generates the fonts.css file content with Google Fonts imports\n */\nfunction generateFontsCSS(\n lightTheme: Theme,\n darkTheme: Theme | null = null,\n display: \"auto\" | \"block\" | \"swap\" | \"fallback\" | \"optional\" = \"swap\",\n): string {\n // Collect fonts from both themes\n const allFonts = new Map<string, GoogleFont>();\n\n for (const font of collectGoogleFonts(lightTheme)) {\n allFonts.set(font.family, font);\n }\n\n if (darkTheme) {\n for (const font of collectGoogleFonts(darkTheme)) {\n allFonts.set(font.family, font);\n }\n }\n\n if (allFonts.size === 0) {\n return \"/* No Google Fonts to import */\\n\";\n }\n\n // Build the Google Fonts URL\n const families = Array.from(allFonts.values()).map((font) => {\n const name = font.family.replace(/ /g, \"+\");\n if (font.weights && font.weights.length > 1 && font.weights[0] !== font.weights.at(-1)) {\n return `family=${name}:wght@${font.weights[0]}..${font.weights.at(-1)}`;\n }\n return `family=${name}`;\n });\n\n const url = `https://fonts.googleapis.com/css2?${families.join(\"&\")}&display=${display}`;\n\n return `/* Google Fonts - Auto-generated by vite-plugin-upstart-theme */\\n@import url(\"${url}\");\\n`;\n}\n\n/**\n * Converts a font definition to a CSS font-family string\n */\nfunction fontToCss(font: Theme[\"typography\"][\"sans\"]): string {\n if (!font) return \"\";\n\n if (font.type === \"stack\") {\n return fontStacksFonts[font.family];\n }\n\n if (font.type === \"google\") {\n // For Google fonts, we just use the family name\n // The actual font loading will be handled separately\n return `\"${font.family}\", system-ui, sans-serif`;\n }\n\n return \"\";\n}\n\n/**\n * Converts camelCase to kebab-case\n */\nfunction camelToKebab(str: string): string {\n return str.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\n}\n\n/**\n * Generates @theme block with font definitions\n */\nfunction generateThemeBlock(\n lightTheme: Theme,\n darkTheme: Theme | null = null,\n defaultTheme: \"light\" | \"dark\" = \"light\",\n): string {\n const fontDefinitions = new Map<string, string>();\n\n // Process light theme fonts\n const lightTypography = lightTheme.typography;\n\n // Add sans font\n if (lightTypography.sans) {\n const fontCss = fontToCss(lightTypography.sans);\n if (fontCss) {\n fontDefinitions.set(\"sans\", fontCss);\n }\n }\n\n // Add serif font\n if (lightTypography.serif) {\n const fontCss = fontToCss(lightTypography.serif);\n if (fontCss) {\n fontDefinitions.set(\"serif\", fontCss);\n }\n }\n\n // Add other fonts\n if (lightTypography.others) {\n for (const [name, font] of Object.entries(lightTypography.others)) {\n const fontCss = fontToCss(font);\n if (fontCss) {\n fontDefinitions.set(name, fontCss);\n }\n }\n }\n\n // Process dark theme fonts if provided\n if (darkTheme) {\n const darkTypography = darkTheme.typography;\n\n if (darkTypography.sans) {\n const fontCss = fontToCss(darkTypography.sans);\n if (fontCss) {\n fontDefinitions.set(\"sans\", fontCss);\n }\n }\n\n if (darkTypography.serif) {\n const fontCss = fontToCss(darkTypography.serif);\n if (fontCss) {\n fontDefinitions.set(\"serif\", fontCss);\n }\n }\n\n if (darkTypography.others) {\n for (const [name, font] of Object.entries(darkTypography.others)) {\n const fontCss = fontToCss(font);\n if (fontCss) {\n fontDefinitions.set(name, fontCss);\n }\n }\n }\n }\n\n const fontLines = Array.from(fontDefinitions.entries())\n .map(([name, value]) => ` --font-${name}: ${value};`)\n .join(\"\\n\");\n\n return `/* Fonts in the tailwind @theme block */\n@theme {\n ${fontLines}\n}\n\n/* Exclude properties since it produce warnings and is not important */\n@plugin \"daisyui\" {\n exclude: properties;\n themes: ${lightTheme.id} ${defaultTheme === \"light\" || !darkTheme ? \"--default\" : \"\"}${darkTheme?.id && darkTheme?.id !== lightTheme.id ? `, ${darkTheme.id} ${defaultTheme === \"dark\" ? \"--default\" : \"--prefersdark\"}` : \"\"};\n logs: true;\n}\n`;\n}\n\n/**\n * Generates @theme block for a single theme with colors and layout variables\n */\nfunction generateThemeVariables(theme: Theme, defaultTheme: \"light\" | \"dark\"): string {\n const processed = processTheme(theme);\n const lines: string[] = [\n ` name: \"${processed.id}\";`,\n ` color-scheme: ${processed.browserColorScheme};`,\n ...((defaultTheme === \"dark\" && theme.browserColorScheme === \"dark\") ||\n (defaultTheme === \"light\" && theme.browserColorScheme === \"light\")\n ? [` default: true;`]\n : []),\n // ...(type === \"dark\" && defaultTheme !== \"dark\" ? [` prefersdark: true;`] : [` prefersdark: false;`]),\n ];\n\n // Color variables\n for (const [colorKey, colorValue] of Object.entries(processed.colors)) {\n const kebabKey = [\"base100\", \"base200\", \"base300\"].includes(colorKey)\n ? colorKey.replace(\"base\", \"base-\")\n : camelToKebab(colorKey);\n lines.push(` --color-${kebabKey}: ${colorValue};`);\n }\n\n lines.push(\"\");\n\n // Layout variables\n lines.push(` --radius-selector: ${processed.radiusSelector};`);\n lines.push(` --radius-field: ${processed.radiusField};`);\n lines.push(` --radius-box: ${processed.radiusBox};`);\n lines.push(` --size-selector: ${processed.sizeSelector};`);\n lines.push(` --size-field: ${processed.sizeField};`);\n lines.push(` --border: ${processed.border};`);\n lines.push(` --depth: ${processed.depth ? 1 : 0};`);\n lines.push(` --noise: 0;`);\n\n // return the generated lines\n return lines.join(\"\\n\");\n}\n\n/**\n * Builds the CSS variable block for a single shadcn theme (`:root` or `.dark`)\n */\nfunction buildShadcnVars(theme: Theme): string {\n const processed = processTheme(theme);\n const { colors } = processed;\n\n const monoFont = theme.typography?.others?.mono;\n const monoFamilyValue = monoFont ? fontToCss(monoFont) : \"ui-monospace, monospace\";\n const sansFamilyValue = theme.typography?.sans\n ? fontToCss(theme.typography.sans)\n : \"ui-sans-serif, system-ui, sans-serif\";\n\n const vars: [string, string][] = [\n [\"--radius\", processed.radiusField],\n [\"--background\", colors.base100],\n [\"--foreground\", colors.baseContent],\n [\"--card\", colors.base200],\n [\"--card-foreground\", colors.baseContent],\n [\"--popover\", colors.base200],\n [\"--popover-foreground\", colors.baseContent],\n [\"--primary\", colors.primary],\n [\"--primary-foreground\", colors.primaryContent],\n [\"--secondary\", colors.secondary],\n [\"--secondary-foreground\", colors.secondaryContent],\n [\"--muted\", colors.neutral],\n [\"--muted-foreground\", colors.neutralContent],\n // shadcn --accent = hover surface, NOT the vibrant accent color\n [\"--accent\", colors.base300],\n [\"--accent-foreground\", colors.baseContent],\n [\"--destructive\", colors.error],\n [\"--border\", colors.base300],\n [\"--input\", colors.base300],\n [\"--ring\", colors.primary],\n [\"--chart-1\", colors.primary],\n [\"--chart-2\", colors.secondary],\n // vibrant accent goes in chart-3\n [\"--chart-3\", colors.accent],\n [\"--chart-4\", colors.success],\n [\"--chart-5\", colors.warning],\n [\"--sidebar\", colors.base200],\n [\"--sidebar-foreground\", colors.baseContent],\n [\"--sidebar-primary\", colors.primary],\n [\"--sidebar-primary-foreground\", colors.primaryContent],\n [\"--sidebar-accent\", colors.base300],\n [\"--sidebar-accent-foreground\", colors.baseContent],\n [\"--sidebar-border\", colors.base300],\n [\"--sidebar-ring\", colors.primary],\n [\"--font-sans\", sansFamilyValue],\n [\"--font-mono\", monoFamilyValue],\n ];\n\n return vars.map(([k, v]) => ` ${k}: ${v};`).join(\"\\n\");\n}\n\n/**\n * Generates the full shadcn-compatible CSS output (no DaisyUI, no @plugin blocks).\n * Uses :root for light theme and .dark for dark theme.\n */\nfunction generateShadcnThemeCSS(lightTheme: Theme, darkTheme: Theme | null = null): string {\n const output: string[] = [];\n\n // Tailwind v4 @theme inline — wires CSS vars to Tailwind utility classes\n output.push(`@theme inline {\n --radius-sm: calc(var(--radius) - 4px);\n --radius-md: calc(var(--radius) - 2px);\n --radius-lg: var(--radius);\n --radius-xl: calc(var(--radius) + 4px);\n --color-background: var(--background);\n --color-foreground: var(--foreground);\n --color-card: var(--card);\n --color-card-foreground: var(--card-foreground);\n --color-popover: var(--popover);\n --color-popover-foreground: var(--popover-foreground);\n --color-primary: var(--primary);\n --color-primary-foreground: var(--primary-foreground);\n --color-secondary: var(--secondary);\n --color-secondary-foreground: var(--secondary-foreground);\n --color-muted: var(--muted);\n --color-muted-foreground: var(--muted-foreground);\n --color-accent: var(--accent);\n --color-accent-foreground: var(--accent-foreground);\n --color-destructive: var(--destructive);\n --color-border: var(--border);\n --color-input: var(--input);\n --color-ring: var(--ring);\n --color-chart-1: var(--chart-1);\n --color-chart-2: var(--chart-2);\n --color-chart-3: var(--chart-3);\n --color-chart-4: var(--chart-4);\n --color-chart-5: var(--chart-5);\n --color-sidebar: var(--sidebar);\n --color-sidebar-foreground: var(--sidebar-foreground);\n --color-sidebar-primary: var(--sidebar-primary);\n --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);\n --color-sidebar-accent: var(--sidebar-accent);\n --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);\n --color-sidebar-border: var(--sidebar-border);\n --color-sidebar-ring: var(--sidebar-ring);\n --font-sans: var(--font-sans);\n --font-mono: var(--font-mono);\n}`);\n\n output.push(\"\");\n\n // Light theme — always :root\n // If only a dark theme is provided (no separate light), use :root, .dark\n const isDarkOnly = !darkTheme && lightTheme.browserColorScheme === \"dark\";\n const lightSelector = isDarkOnly ? \":root, .dark\" : \":root\";\n\n output.push(`/* ${lightTheme.name} theme */`);\n output.push(`${lightSelector} {`);\n output.push(buildShadcnVars(lightTheme));\n output.push(\"}\");\n\n // Dark theme — .dark selector\n if (darkTheme && darkTheme.id !== lightTheme.id) {\n output.push(\"\");\n output.push(`/* ${darkTheme.name} theme (dark) */`);\n output.push(\".dark {\");\n output.push(buildShadcnVars(darkTheme));\n output.push(\"}\");\n }\n\n return output.join(\"\\n\");\n}\n\n/**\n * Unplugin-based theme generator\n */\nexport const upstartTheme = createUnplugin<PluginOptions>((opts) => {\n let generated = false;\n\n return {\n name: \"unplugin-theme-generator\",\n apply: \"serve\",\n\n vite: {\n configResolved() {\n // Generate the CSS file once when config is resolved\n if (generated) return;\n generated = true;\n\n if (!opts?.themes?.light) {\n console.warn(\"No light theme provided to unplugin-theme-generator. A light theme is required.\");\n return;\n }\n\n const outputDir = path.dirname(opts.outputPath);\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n\n const { themes, fontsDisplay = \"swap\", cssFramework = \"daisy-ui\" } = opts;\n\n // Generate fonts.css file (shared by both frameworks)\n const fontsCSS = generateFontsCSS(themes.light, themes.dark, fontsDisplay);\n const fontsCSSPath = path.join(outputDir, \"fonts.css\");\n fs.writeFileSync(fontsCSSPath, fontsCSS);\n\n let cssContent: string;\n\n if (cssFramework === \"shadcn-ui\") {\n cssContent = generateShadcnThemeCSS(themes.light, themes.dark ?? null);\n } else {\n const output: string[] = [];\n\n // Generate @theme block with fonts from both themes\n output.push(generateThemeBlock(themes.light, themes.dark));\n output.push(\"\");\n\n // IMPORTANT; Place dark theme first OTHERWISE daisyUI will not apply it correctly\n // @see https://github.com/saadeghi/daisyui/issues/3921#issuecomment-3059524563\n // Generate @theme block for dark theme if present\n if (themes.dark) {\n output.push(\"/* Dark theme variables */\");\n output.push('@plugin \"daisyui/theme\" {');\n output.push(generateThemeVariables(themes.dark, themes.default));\n output.push(\"}\");\n output.push(\"\");\n }\n\n // Generate @theme block for light theme\n if (themes.light?.id !== themes.dark?.id) {\n output.push(\"/* Light theme variables */\");\n output.push('@plugin \"daisyui/theme\" {');\n output.push(generateThemeVariables(themes.light, themes.default));\n output.push(\"}\");\n output.push(\"\");\n }\n\n cssContent = output.join(\"\\n\");\n }\n\n fs.writeFileSync(opts.outputPath, cssContent);\n },\n },\n };\n});\n\nexport default upstartTheme.vite;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@upstart.gg/vite-plugins",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.29",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"oxc-parser": "0.101.0",
|
|
24
24
|
"unplugin": "^2.3.11",
|
|
25
25
|
"zimmerframe": "^1.1.4",
|
|
26
|
-
"@upstart.gg/sdk": "^0.1.
|
|
26
|
+
"@upstart.gg/sdk": "^0.1.29"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.9",
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
},
|
|
114
114
|
"peerDependencies": {
|
|
115
115
|
"zod": "4.3.6",
|
|
116
|
-
"@upstart.gg/sdk": "^0.1.
|
|
116
|
+
"@upstart.gg/sdk": "^0.1.29"
|
|
117
117
|
},
|
|
118
118
|
"author": "Upstart",
|
|
119
119
|
"publishConfig": {
|
|
@@ -18,6 +18,8 @@ interface PluginOptions {
|
|
|
18
18
|
outputPath: string;
|
|
19
19
|
/** Google Fonts display parameter (default: 'swap') */
|
|
20
20
|
fontsDisplay?: "auto" | "block" | "swap" | "fallback" | "optional";
|
|
21
|
+
/** CSS framework to target (default: 'daisy-ui') */
|
|
22
|
+
cssFramework?: "daisy-ui" | "shadcn-ui";
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
/**
|
|
@@ -196,16 +198,10 @@ function generateThemeBlock(
|
|
|
196
198
|
`;
|
|
197
199
|
}
|
|
198
200
|
|
|
199
|
-
//
|
|
200
|
-
|
|
201
201
|
/**
|
|
202
202
|
* Generates @theme block for a single theme with colors and layout variables
|
|
203
203
|
*/
|
|
204
|
-
function generateThemeVariables(
|
|
205
|
-
theme: Theme,
|
|
206
|
-
type: "light" | "dark",
|
|
207
|
-
defaultTheme: "light" | "dark",
|
|
208
|
-
): string {
|
|
204
|
+
function generateThemeVariables(theme: Theme, defaultTheme: "light" | "dark"): string {
|
|
209
205
|
const processed = processTheme(theme);
|
|
210
206
|
const lines: string[] = [
|
|
211
207
|
` name: "${processed.id}";`,
|
|
@@ -241,6 +237,133 @@ function generateThemeVariables(
|
|
|
241
237
|
return lines.join("\n");
|
|
242
238
|
}
|
|
243
239
|
|
|
240
|
+
/**
|
|
241
|
+
* Builds the CSS variable block for a single shadcn theme (`:root` or `.dark`)
|
|
242
|
+
*/
|
|
243
|
+
function buildShadcnVars(theme: Theme): string {
|
|
244
|
+
const processed = processTheme(theme);
|
|
245
|
+
const { colors } = processed;
|
|
246
|
+
|
|
247
|
+
const monoFont = theme.typography?.others?.mono;
|
|
248
|
+
const monoFamilyValue = monoFont ? fontToCss(monoFont) : "ui-monospace, monospace";
|
|
249
|
+
const sansFamilyValue = theme.typography?.sans
|
|
250
|
+
? fontToCss(theme.typography.sans)
|
|
251
|
+
: "ui-sans-serif, system-ui, sans-serif";
|
|
252
|
+
|
|
253
|
+
const vars: [string, string][] = [
|
|
254
|
+
["--radius", processed.radiusField],
|
|
255
|
+
["--background", colors.base100],
|
|
256
|
+
["--foreground", colors.baseContent],
|
|
257
|
+
["--card", colors.base200],
|
|
258
|
+
["--card-foreground", colors.baseContent],
|
|
259
|
+
["--popover", colors.base200],
|
|
260
|
+
["--popover-foreground", colors.baseContent],
|
|
261
|
+
["--primary", colors.primary],
|
|
262
|
+
["--primary-foreground", colors.primaryContent],
|
|
263
|
+
["--secondary", colors.secondary],
|
|
264
|
+
["--secondary-foreground", colors.secondaryContent],
|
|
265
|
+
["--muted", colors.neutral],
|
|
266
|
+
["--muted-foreground", colors.neutralContent],
|
|
267
|
+
// shadcn --accent = hover surface, NOT the vibrant accent color
|
|
268
|
+
["--accent", colors.base300],
|
|
269
|
+
["--accent-foreground", colors.baseContent],
|
|
270
|
+
["--destructive", colors.error],
|
|
271
|
+
["--border", colors.base300],
|
|
272
|
+
["--input", colors.base300],
|
|
273
|
+
["--ring", colors.primary],
|
|
274
|
+
["--chart-1", colors.primary],
|
|
275
|
+
["--chart-2", colors.secondary],
|
|
276
|
+
// vibrant accent goes in chart-3
|
|
277
|
+
["--chart-3", colors.accent],
|
|
278
|
+
["--chart-4", colors.success],
|
|
279
|
+
["--chart-5", colors.warning],
|
|
280
|
+
["--sidebar", colors.base200],
|
|
281
|
+
["--sidebar-foreground", colors.baseContent],
|
|
282
|
+
["--sidebar-primary", colors.primary],
|
|
283
|
+
["--sidebar-primary-foreground", colors.primaryContent],
|
|
284
|
+
["--sidebar-accent", colors.base300],
|
|
285
|
+
["--sidebar-accent-foreground", colors.baseContent],
|
|
286
|
+
["--sidebar-border", colors.base300],
|
|
287
|
+
["--sidebar-ring", colors.primary],
|
|
288
|
+
["--font-sans", sansFamilyValue],
|
|
289
|
+
["--font-mono", monoFamilyValue],
|
|
290
|
+
];
|
|
291
|
+
|
|
292
|
+
return vars.map(([k, v]) => ` ${k}: ${v};`).join("\n");
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Generates the full shadcn-compatible CSS output (no DaisyUI, no @plugin blocks).
|
|
297
|
+
* Uses :root for light theme and .dark for dark theme.
|
|
298
|
+
*/
|
|
299
|
+
function generateShadcnThemeCSS(lightTheme: Theme, darkTheme: Theme | null = null): string {
|
|
300
|
+
const output: string[] = [];
|
|
301
|
+
|
|
302
|
+
// Tailwind v4 @theme inline — wires CSS vars to Tailwind utility classes
|
|
303
|
+
output.push(`@theme inline {
|
|
304
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
305
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
306
|
+
--radius-lg: var(--radius);
|
|
307
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
308
|
+
--color-background: var(--background);
|
|
309
|
+
--color-foreground: var(--foreground);
|
|
310
|
+
--color-card: var(--card);
|
|
311
|
+
--color-card-foreground: var(--card-foreground);
|
|
312
|
+
--color-popover: var(--popover);
|
|
313
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
314
|
+
--color-primary: var(--primary);
|
|
315
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
316
|
+
--color-secondary: var(--secondary);
|
|
317
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
318
|
+
--color-muted: var(--muted);
|
|
319
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
320
|
+
--color-accent: var(--accent);
|
|
321
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
322
|
+
--color-destructive: var(--destructive);
|
|
323
|
+
--color-border: var(--border);
|
|
324
|
+
--color-input: var(--input);
|
|
325
|
+
--color-ring: var(--ring);
|
|
326
|
+
--color-chart-1: var(--chart-1);
|
|
327
|
+
--color-chart-2: var(--chart-2);
|
|
328
|
+
--color-chart-3: var(--chart-3);
|
|
329
|
+
--color-chart-4: var(--chart-4);
|
|
330
|
+
--color-chart-5: var(--chart-5);
|
|
331
|
+
--color-sidebar: var(--sidebar);
|
|
332
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
333
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
334
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
335
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
336
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
337
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
338
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
339
|
+
--font-sans: var(--font-sans);
|
|
340
|
+
--font-mono: var(--font-mono);
|
|
341
|
+
}`);
|
|
342
|
+
|
|
343
|
+
output.push("");
|
|
344
|
+
|
|
345
|
+
// Light theme — always :root
|
|
346
|
+
// If only a dark theme is provided (no separate light), use :root, .dark
|
|
347
|
+
const isDarkOnly = !darkTheme && lightTheme.browserColorScheme === "dark";
|
|
348
|
+
const lightSelector = isDarkOnly ? ":root, .dark" : ":root";
|
|
349
|
+
|
|
350
|
+
output.push(`/* ${lightTheme.name} theme */`);
|
|
351
|
+
output.push(`${lightSelector} {`);
|
|
352
|
+
output.push(buildShadcnVars(lightTheme));
|
|
353
|
+
output.push("}");
|
|
354
|
+
|
|
355
|
+
// Dark theme — .dark selector
|
|
356
|
+
if (darkTheme && darkTheme.id !== lightTheme.id) {
|
|
357
|
+
output.push("");
|
|
358
|
+
output.push(`/* ${darkTheme.name} theme (dark) */`);
|
|
359
|
+
output.push(".dark {");
|
|
360
|
+
output.push(buildShadcnVars(darkTheme));
|
|
361
|
+
output.push("}");
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return output.join("\n");
|
|
365
|
+
}
|
|
366
|
+
|
|
244
367
|
/**
|
|
245
368
|
* Unplugin-based theme generator
|
|
246
369
|
*/
|
|
@@ -267,41 +390,47 @@ export const upstartTheme = createUnplugin<PluginOptions>((opts) => {
|
|
|
267
390
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
268
391
|
}
|
|
269
392
|
|
|
270
|
-
const { themes, fontsDisplay = "swap" } = opts;
|
|
393
|
+
const { themes, fontsDisplay = "swap", cssFramework = "daisy-ui" } = opts;
|
|
271
394
|
|
|
272
|
-
// Generate fonts.css file
|
|
395
|
+
// Generate fonts.css file (shared by both frameworks)
|
|
273
396
|
const fontsCSS = generateFontsCSS(themes.light, themes.dark, fontsDisplay);
|
|
274
397
|
const fontsCSSPath = path.join(outputDir, "fonts.css");
|
|
275
398
|
fs.writeFileSync(fontsCSSPath, fontsCSS);
|
|
276
399
|
|
|
277
|
-
|
|
400
|
+
let cssContent: string;
|
|
278
401
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
402
|
+
if (cssFramework === "shadcn-ui") {
|
|
403
|
+
cssContent = generateShadcnThemeCSS(themes.light, themes.dark ?? null);
|
|
404
|
+
} else {
|
|
405
|
+
const output: string[] = [];
|
|
282
406
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
// Generate @theme block for dark theme if present
|
|
286
|
-
if (themes.dark) {
|
|
287
|
-
output.push("/* Dark theme variables */");
|
|
288
|
-
output.push('@plugin "daisyui/theme" {');
|
|
289
|
-
output.push(generateThemeVariables(themes.dark, "dark", themes.default));
|
|
290
|
-
output.push("}");
|
|
407
|
+
// Generate @theme block with fonts from both themes
|
|
408
|
+
output.push(generateThemeBlock(themes.light, themes.dark));
|
|
291
409
|
output.push("");
|
|
292
|
-
}
|
|
293
410
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
411
|
+
// IMPORTANT; Place dark theme first OTHERWISE daisyUI will not apply it correctly
|
|
412
|
+
// @see https://github.com/saadeghi/daisyui/issues/3921#issuecomment-3059524563
|
|
413
|
+
// Generate @theme block for dark theme if present
|
|
414
|
+
if (themes.dark) {
|
|
415
|
+
output.push("/* Dark theme variables */");
|
|
416
|
+
output.push('@plugin "daisyui/theme" {');
|
|
417
|
+
output.push(generateThemeVariables(themes.dark, themes.default));
|
|
418
|
+
output.push("}");
|
|
419
|
+
output.push("");
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// Generate @theme block for light theme
|
|
423
|
+
if (themes.light?.id !== themes.dark?.id) {
|
|
424
|
+
output.push("/* Light theme variables */");
|
|
425
|
+
output.push('@plugin "daisyui/theme" {');
|
|
426
|
+
output.push(generateThemeVariables(themes.light, themes.default));
|
|
427
|
+
output.push("}");
|
|
428
|
+
output.push("");
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
cssContent = output.join("\n");
|
|
301
432
|
}
|
|
302
433
|
|
|
303
|
-
// Write the generated CSS file
|
|
304
|
-
const cssContent = output.join("\n");
|
|
305
434
|
fs.writeFileSync(opts.outputPath, cssContent);
|
|
306
435
|
},
|
|
307
436
|
},
|