@upstart.gg/vite-plugins 0.0.37

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.
Files changed (58) hide show
  1. package/dist/vite-plugin-upstart-attrs.d.ts +29 -0
  2. package/dist/vite-plugin-upstart-attrs.d.ts.map +1 -0
  3. package/dist/vite-plugin-upstart-attrs.js +323 -0
  4. package/dist/vite-plugin-upstart-attrs.js.map +1 -0
  5. package/dist/vite-plugin-upstart-editor/plugin.d.ts +15 -0
  6. package/dist/vite-plugin-upstart-editor/plugin.d.ts.map +1 -0
  7. package/dist/vite-plugin-upstart-editor/plugin.js +55 -0
  8. package/dist/vite-plugin-upstart-editor/plugin.js.map +1 -0
  9. package/dist/vite-plugin-upstart-editor/runtime/click-handler.d.ts +12 -0
  10. package/dist/vite-plugin-upstart-editor/runtime/click-handler.d.ts.map +1 -0
  11. package/dist/vite-plugin-upstart-editor/runtime/click-handler.js +57 -0
  12. package/dist/vite-plugin-upstart-editor/runtime/click-handler.js.map +1 -0
  13. package/dist/vite-plugin-upstart-editor/runtime/hover-overlay.d.ts +12 -0
  14. package/dist/vite-plugin-upstart-editor/runtime/hover-overlay.d.ts.map +1 -0
  15. package/dist/vite-plugin-upstart-editor/runtime/hover-overlay.js +91 -0
  16. package/dist/vite-plugin-upstart-editor/runtime/hover-overlay.js.map +1 -0
  17. package/dist/vite-plugin-upstart-editor/runtime/index.d.ts +22 -0
  18. package/dist/vite-plugin-upstart-editor/runtime/index.d.ts.map +1 -0
  19. package/dist/vite-plugin-upstart-editor/runtime/index.js +62 -0
  20. package/dist/vite-plugin-upstart-editor/runtime/index.js.map +1 -0
  21. package/dist/vite-plugin-upstart-editor/runtime/text-editor.d.ts +15 -0
  22. package/dist/vite-plugin-upstart-editor/runtime/text-editor.d.ts.map +1 -0
  23. package/dist/vite-plugin-upstart-editor/runtime/text-editor.js +292 -0
  24. package/dist/vite-plugin-upstart-editor/runtime/text-editor.js.map +1 -0
  25. package/dist/vite-plugin-upstart-editor/runtime/types.d.ts +126 -0
  26. package/dist/vite-plugin-upstart-editor/runtime/types.d.ts.map +1 -0
  27. package/dist/vite-plugin-upstart-editor/runtime/types.js +1 -0
  28. package/dist/vite-plugin-upstart-editor/runtime/utils.d.ts +15 -0
  29. package/dist/vite-plugin-upstart-editor/runtime/utils.d.ts.map +1 -0
  30. package/dist/vite-plugin-upstart-editor/runtime/utils.js +26 -0
  31. package/dist/vite-plugin-upstart-editor/runtime/utils.js.map +1 -0
  32. package/dist/vite-plugin-upstart-theme.d.ts +22 -0
  33. package/dist/vite-plugin-upstart-theme.d.ts.map +1 -0
  34. package/dist/vite-plugin-upstart-theme.js +179 -0
  35. package/dist/vite-plugin-upstart-theme.js.map +1 -0
  36. package/package.json +63 -0
  37. package/src/tests/fixtures/routes/default-layout.tsx +10 -0
  38. package/src/tests/fixtures/routes/dynamic-route.tsx +10 -0
  39. package/src/tests/fixtures/routes/missing-attributes.tsx +8 -0
  40. package/src/tests/fixtures/routes/missing-path.tsx +9 -0
  41. package/src/tests/fixtures/routes/valid-full.tsx +15 -0
  42. package/src/tests/fixtures/routes/valid-minimal.tsx +10 -0
  43. package/src/tests/fixtures/routes/with-comments.tsx +12 -0
  44. package/src/tests/fixtures/routes/with-nested-objects.tsx +15 -0
  45. package/src/tests/upstart-editor-api.test.ts +367 -0
  46. package/src/tests/vite-plugin-upstart-attrs.test.ts +1189 -0
  47. package/src/tests/vite-plugin-upstart-editor.test.ts +81 -0
  48. package/src/upstart-editor-api.ts +204 -0
  49. package/src/vite-plugin-upstart-attrs.ts +708 -0
  50. package/src/vite-plugin-upstart-editor/PLAN.md +1391 -0
  51. package/src/vite-plugin-upstart-editor/plugin.ts +73 -0
  52. package/src/vite-plugin-upstart-editor/runtime/click-handler.ts +80 -0
  53. package/src/vite-plugin-upstart-editor/runtime/hover-overlay.ts +135 -0
  54. package/src/vite-plugin-upstart-editor/runtime/index.ts +90 -0
  55. package/src/vite-plugin-upstart-editor/runtime/text-editor.ts +401 -0
  56. package/src/vite-plugin-upstart-editor/runtime/types.ts +120 -0
  57. package/src/vite-plugin-upstart-editor/runtime/utils.ts +34 -0
  58. package/src/vite-plugin-upstart-theme.ts +314 -0
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,15 @@
1
+ import { EditorMessage } from "./types.js";
2
+
3
+ //#region src/vite-plugin-upstart-editor/runtime/utils.d.ts
4
+
5
+ /**
6
+ * Send a message to the parent window.
7
+ */
8
+ declare function sendToParent(message: EditorMessage): void;
9
+ /**
10
+ * Check if running inside an iframe.
11
+ */
12
+ declare function isInIframe(): boolean;
13
+ //#endregion
14
+ export { isInIframe, sendToParent };
15
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","names":[],"sources":["../../../src/vite-plugin-upstart-editor/runtime/utils.ts"],"sourcesContent":[],"mappings":";;;;;;AAKA;AAsBgB,iBAtBA,YAAA,CAsBU,OAAA,EAtBY,aAsBZ,CAAA,EAAA,IAAA;;;;iBAAV,UAAA,CAAA"}
@@ -0,0 +1,26 @@
1
+ //#region src/vite-plugin-upstart-editor/runtime/utils.ts
2
+ /**
3
+ * Send a message to the parent window.
4
+ */
5
+ function sendToParent(message) {
6
+ if (typeof window === "undefined") return;
7
+ if (window.parent === window) {
8
+ console.warn("[Upstart Editor] Not running in iframe, cannot send message:", message);
9
+ return;
10
+ }
11
+ window.parent.postMessage({
12
+ source: "upstart-editor",
13
+ ...message
14
+ }, "*");
15
+ }
16
+ /**
17
+ * Check if running inside an iframe.
18
+ */
19
+ function isInIframe() {
20
+ if (typeof window === "undefined") return false;
21
+ return window.parent !== window;
22
+ }
23
+
24
+ //#endregion
25
+ export { isInIframe, sendToParent };
26
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","names":[],"sources":["../../../src/vite-plugin-upstart-editor/runtime/utils.ts"],"sourcesContent":["import type { EditorMessage } from \"./types\";\n\n/**\n * Send a message to the parent window.\n */\nexport function sendToParent(message: EditorMessage): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n if (window.parent === window) {\n console.warn(\"[Upstart Editor] Not running in iframe, cannot send message:\", message);\n return;\n }\n\n window.parent.postMessage(\n {\n source: \"upstart-editor\",\n ...message,\n },\n \"*\",\n );\n}\n\n/**\n * Check if running inside an iframe.\n */\nexport function isInIframe(): boolean {\n if (typeof window === \"undefined\") {\n return false;\n }\n\n return window.parent !== window;\n}\n"],"mappings":";;;;AAKA,SAAgB,aAAa,SAA8B;AACzD,KAAI,OAAO,WAAW,YACpB;AAGF,KAAI,OAAO,WAAW,QAAQ;AAC5B,UAAQ,KAAK,gEAAgE,QAAQ;AACrF;;AAGF,QAAO,OAAO,YACZ;EACE,QAAQ;EACR,GAAG;EACJ,EACD,IACD;;;;;AAMH,SAAgB,aAAsB;AACpC,KAAI,OAAO,WAAW,YACpB,QAAO;AAGT,QAAO,OAAO,WAAW"}
@@ -0,0 +1,22 @@
1
+ import * as unplugin0 from "unplugin";
2
+ import { Theme } from "@upstart.gg/sdk/themes/theme";
3
+
4
+ //#region src/vite-plugin-upstart-theme.d.ts
5
+ interface PluginOptions {
6
+ themes: {
7
+ light: Theme;
8
+ dark?: Theme;
9
+ default: "light" | "dark";
10
+ };
11
+ outputPath: string;
12
+ /** Google Fonts display parameter (default: 'swap') */
13
+ fontsDisplay?: "auto" | "block" | "swap" | "fallback" | "optional";
14
+ }
15
+ /**
16
+ * Unplugin-based theme generator
17
+ */
18
+ declare const upstartTheme: unplugin0.UnpluginInstance<PluginOptions, boolean>;
19
+ declare const _default: (options: PluginOptions) => unplugin0.VitePlugin<any> | unplugin0.VitePlugin<any>[];
20
+ //#endregion
21
+ export { _default as default, upstartTheme };
22
+ //# sourceMappingURL=vite-plugin-upstart-theme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite-plugin-upstart-theme.d.ts","names":[],"sources":["../src/vite-plugin-upstart-theme.ts"],"sourcesContent":[],"mappings":";;;;UAWU,aAAA;;WAEC;IAFD,IAAA,CAAA,EAGC,KAHY;IA2OV,OAAA,EAAA,OAiEX,GAAA,MAjEuB;EAiEtB,CAAA;;;;;;;;cAjEU,cAAY,SAAA,CAAA,iBAAA;cAiEtB"}
@@ -0,0 +1,179 @@
1
+ import { createUnplugin } from "unplugin";
2
+ import path from "node:path";
3
+ import { fontStacksFonts, processTheme } from "@upstart.gg/sdk/themes/theme";
4
+ import fs from "node:fs";
5
+
6
+ //#region src/vite-plugin-upstart-theme.ts
7
+ /**
8
+ * Collects Google Fonts from a theme's typography configuration
9
+ */
10
+ function collectGoogleFonts(theme) {
11
+ const { typography } = theme;
12
+ if (!typography) return [];
13
+ const googleFonts = [];
14
+ const seen = /* @__PURE__ */ new Set();
15
+ const addFont = (font) => {
16
+ if (font?.type === "google" && !seen.has(font.family)) {
17
+ seen.add(font.family);
18
+ googleFonts.push(font);
19
+ }
20
+ };
21
+ addFont(typography.sans);
22
+ addFont(typography.serif);
23
+ if (typography.others) Object.values(typography.others).forEach(addFont);
24
+ return googleFonts;
25
+ }
26
+ /**
27
+ * Generates the fonts.css file content with Google Fonts imports
28
+ */
29
+ function generateFontsCSS(lightTheme, darkTheme = null, display = "swap") {
30
+ const allFonts = /* @__PURE__ */ new Map();
31
+ for (const font of collectGoogleFonts(lightTheme)) allFonts.set(font.family, font);
32
+ if (darkTheme) for (const font of collectGoogleFonts(darkTheme)) allFonts.set(font.family, font);
33
+ if (allFonts.size === 0) return "/* No Google Fonts to import */\n";
34
+ return `/* Google Fonts - Auto-generated by vite-plugin-upstart-theme */\n@import url("${`https://fonts.googleapis.com/css2?${Array.from(allFonts.values()).map((font) => {
35
+ const name = font.family.replace(/ /g, "+");
36
+ if (font.weights && font.weights.length > 1 && font.weights[0] !== font.weights.at(-1)) return `family=${name}:wght@${font.weights[0]}..${font.weights.at(-1)}`;
37
+ return `family=${name}`;
38
+ }).join("&")}&display=${display}`}");\n`;
39
+ }
40
+ /**
41
+ * Converts a font definition to a CSS font-family string
42
+ */
43
+ function fontToCss(font) {
44
+ if (!font) return "";
45
+ if (font.type === "stack") return fontStacksFonts[font.family];
46
+ if (font.type === "google") return `"${font.family}", system-ui, sans-serif`;
47
+ return "";
48
+ }
49
+ /**
50
+ * Converts camelCase to kebab-case
51
+ */
52
+ function camelToKebab(str) {
53
+ return str.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
54
+ }
55
+ /**
56
+ * Generates @theme block with font definitions
57
+ */
58
+ function generateThemeBlock(lightTheme, darkTheme = null, defaultTheme = "light") {
59
+ const fontDefinitions = /* @__PURE__ */ new Map();
60
+ const lightTypography = lightTheme.typography;
61
+ if (lightTypography.sans) {
62
+ const fontCss = fontToCss(lightTypography.sans);
63
+ if (fontCss) fontDefinitions.set("sans", fontCss);
64
+ }
65
+ if (lightTypography.serif) {
66
+ const fontCss = fontToCss(lightTypography.serif);
67
+ if (fontCss) fontDefinitions.set("serif", fontCss);
68
+ }
69
+ if (lightTypography.others) for (const [name, font] of Object.entries(lightTypography.others)) {
70
+ const fontCss = fontToCss(font);
71
+ if (fontCss) fontDefinitions.set(name, fontCss);
72
+ }
73
+ if (darkTheme) {
74
+ const darkTypography = darkTheme.typography;
75
+ if (darkTypography.sans) {
76
+ const fontCss = fontToCss(darkTypography.sans);
77
+ if (fontCss) fontDefinitions.set("sans", fontCss);
78
+ }
79
+ if (darkTypography.serif) {
80
+ const fontCss = fontToCss(darkTypography.serif);
81
+ if (fontCss) fontDefinitions.set("serif", fontCss);
82
+ }
83
+ if (darkTypography.others) for (const [name, font] of Object.entries(darkTypography.others)) {
84
+ const fontCss = fontToCss(font);
85
+ if (fontCss) fontDefinitions.set(name, fontCss);
86
+ }
87
+ }
88
+ return `/* Fonts in the tailwind @theme block */
89
+ @theme {
90
+ ${Array.from(fontDefinitions.entries()).map(([name, value]) => ` --font-${name}: ${value};`).join("\n")}
91
+ }
92
+
93
+ /* Exclude properties since it produce warnings and is not important */
94
+ @plugin "daisyui" {
95
+ exclude: properties;
96
+ themes: ${lightTheme.id} ${defaultTheme === "light" || !darkTheme ? "--default" : ""}${darkTheme?.id && darkTheme?.id !== lightTheme.id ? `, ${darkTheme.id} ${defaultTheme === "dark" ? "--default" : "--prefersdark"}` : ""};
97
+ logs: true;
98
+ }
99
+ `;
100
+ }
101
+ /**
102
+ * Generates @theme block for a single theme with colors and layout variables
103
+ */
104
+ function generateThemeVariables(theme, type, defaultTheme) {
105
+ const processed = processTheme(theme);
106
+ const lines = [
107
+ ` name: "${processed.id}";`,
108
+ ` color-scheme: ${processed.browserColorScheme};`,
109
+ ...defaultTheme === "dark" && theme.browserColorScheme === "dark" || defaultTheme === "light" && theme.browserColorScheme === "light" ? [` default: true;`] : []
110
+ ];
111
+ for (const [colorKey, colorValue] of Object.entries(processed.colors)) {
112
+ const kebabKey = [
113
+ "base100",
114
+ "base200",
115
+ "base300"
116
+ ].includes(colorKey) ? colorKey.replace("base", "base-") : camelToKebab(colorKey);
117
+ lines.push(` --color-${kebabKey}: ${colorValue};`);
118
+ }
119
+ lines.push("");
120
+ lines.push(` --radius-selector: ${processed.radiusSelector};`);
121
+ lines.push(` --radius-field: ${processed.radiusField};`);
122
+ lines.push(` --radius-box: ${processed.radiusBox};`);
123
+ lines.push(` --size-selector: ${processed.sizeSelector};`);
124
+ lines.push(` --size-field: ${processed.sizeField};`);
125
+ lines.push(` --border: ${processed.border};`);
126
+ lines.push(` --depth: ${processed.depth ? 1 : 0};`);
127
+ lines.push(` --noise: 0;`);
128
+ return lines.join("\n");
129
+ }
130
+ /**
131
+ * Unplugin-based theme generator
132
+ */
133
+ const upstartTheme = createUnplugin((opts) => {
134
+ let generated = false;
135
+ return {
136
+ name: "unplugin-theme-generator",
137
+ apply: "serve",
138
+ vite: { configResolved() {
139
+ if (generated) return;
140
+ generated = true;
141
+ if (!opts?.themes?.light) {
142
+ console.warn("No light theme provided to unplugin-theme-generator. A light theme is required.");
143
+ return;
144
+ }
145
+ const outputDir = path.dirname(opts.outputPath);
146
+ if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true });
147
+ const { themes, fontsDisplay = "swap" } = opts;
148
+ const fontsCSS = generateFontsCSS(themes.light, themes.dark, fontsDisplay);
149
+ const fontsCSSPath = path.join(outputDir, "fonts.css");
150
+ fs.writeFileSync(fontsCSSPath, fontsCSS);
151
+ console.log(`✓ Generated fonts CSS: ${fontsCSSPath}`);
152
+ const output = [];
153
+ output.push(generateThemeBlock(themes.light, themes.dark));
154
+ output.push("");
155
+ if (themes.dark) {
156
+ output.push("/* Dark theme variables */");
157
+ output.push("@plugin \"daisyui/theme\" {");
158
+ output.push(generateThemeVariables(themes.dark, "dark", themes.default));
159
+ output.push("}");
160
+ output.push("");
161
+ }
162
+ if (themes.light?.id !== themes.dark?.id) {
163
+ output.push("/* Light theme variables */");
164
+ output.push("@plugin \"daisyui/theme\" {");
165
+ output.push(generateThemeVariables(themes.light, "light", themes.default));
166
+ output.push("}");
167
+ output.push("");
168
+ }
169
+ const cssContent = output.join("\n");
170
+ fs.writeFileSync(opts.outputPath, cssContent);
171
+ console.log(`✓ Generated theme CSS: ${opts.outputPath}`);
172
+ } }
173
+ };
174
+ });
175
+ var vite_plugin_upstart_theme_default = upstartTheme.vite;
176
+
177
+ //#endregion
178
+ export { vite_plugin_upstart_theme_default as default, upstartTheme };
179
+ //# sourceMappingURL=vite-plugin-upstart-theme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite-plugin-upstart-theme.js","names":["googleFonts: Array<GoogleFont>","lines: string[]","output: string[]"],"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 console.log(`✓ Generated fonts CSS: ${fontsCSSPath}`);\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 console.log(`✓ Generated theme CSS: ${opts.outputPath}`);\n },\n },\n };\n});\n\nexport default upstartTheme.vite;\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@upstart.gg/vite-plugins",
3
+ "version": "0.0.37",
4
+ "type": "module",
5
+ "files": [
6
+ "dist",
7
+ "src"
8
+ ],
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/upstart-gg/monorepo.git",
12
+ "directory": "packages/vite-plugins"
13
+ },
14
+ "sideEffects": false,
15
+ "dependencies": {
16
+ "@oxc-parser/binding-linux-arm64-gnu": "^0.101.0",
17
+ "@oxc-parser/binding-linux-x64-gnu": "^0.101.0",
18
+ "@tiptap/core": "^2.27.1",
19
+ "@tiptap/extension-bubble-menu": "^2.27.1",
20
+ "@tiptap/extension-placeholder": "^2.27.2",
21
+ "@tiptap/starter-kit": "^2.27.1",
22
+ "magic-string": "^0.30.21",
23
+ "oxc-parser": "^0.101.0",
24
+ "unplugin": "^2.3.11",
25
+ "zimmerframe": "^1.1.4",
26
+ "@upstart.gg/sdk": "^0.0.37"
27
+ },
28
+ "devDependencies": {
29
+ "@types/bun": "1.3.5",
30
+ "@types/estree": "^1.0.8",
31
+ "@types/estree-jsx": "1.0.5",
32
+ "@types/node": "^24.10.0",
33
+ "@types/react": "19.1.13",
34
+ "tsdown": "0.18.3",
35
+ "vitest": "4.0.16",
36
+ "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.53",
37
+ "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.53"
38
+ },
39
+ "exports": {
40
+ "./vite-plugin-upstart-attrs": "./dist/vite-plugin-upstart-attrs.js",
41
+ "./vite-plugin-upstart-editor/plugin": "./dist/vite-plugin-upstart-editor/plugin.js",
42
+ "./vite-plugin-upstart-editor/runtime": "./dist/vite-plugin-upstart-editor/runtime/index.js",
43
+ "./vite-plugin-upstart-editor/runtime/click-handler": "./dist/vite-plugin-upstart-editor/runtime/click-handler.js",
44
+ "./vite-plugin-upstart-editor/runtime/hover-overlay": "./dist/vite-plugin-upstart-editor/runtime/hover-overlay.js",
45
+ "./vite-plugin-upstart-editor/runtime/text-editor": "./dist/vite-plugin-upstart-editor/runtime/text-editor.js",
46
+ "./vite-plugin-upstart-editor/runtime/types": "./dist/vite-plugin-upstart-editor/runtime/types.js",
47
+ "./vite-plugin-upstart-editor/runtime/utils": "./dist/vite-plugin-upstart-editor/runtime/utils.js",
48
+ "./vite-plugin-upstart-theme": "./dist/vite-plugin-upstart-theme.js",
49
+ "./package.json": "./package.json"
50
+ },
51
+ "peerDependencies": {
52
+ "@upstart.gg/sdk": "^0.0.37"
53
+ },
54
+ "author": "Upstart",
55
+ "publishConfig": {
56
+ "access": "public"
57
+ },
58
+ "scripts": {
59
+ "test": "vitest --run",
60
+ "test:bun": "bun test",
61
+ "build": "tsdown"
62
+ }
63
+ }
@@ -0,0 +1,10 @@
1
+ // @ts-nocheck
2
+ /* biome-ignore lint: test fixture */
3
+ import { definePageAttributes } from "@upstart.gg/sdk";
4
+
5
+ export const attributes = definePageAttributes({
6
+ path: "/home",
7
+ label: "Home",
8
+ title: "Home Page",
9
+ layout: "default",
10
+ });
@@ -0,0 +1,10 @@
1
+ // @ts-nocheck
2
+ /* biome-ignore lint: test fixture */
3
+ import { definePageAttributes } from "@upstart.gg/sdk";
4
+
5
+ export const attributes = definePageAttributes({
6
+ path: "/posts/:id",
7
+ label: "Post Detail",
8
+ title: null,
9
+ layout: "default",
10
+ });
@@ -0,0 +1,8 @@
1
+ // @ts-nocheck
2
+ /* biome-ignore lint: test fixture */
3
+
4
+ // This file has no attributes export
5
+
6
+ export default function NoAttributesPage() {
7
+ return <div>No Attributes</div>;
8
+ }
@@ -0,0 +1,9 @@
1
+ // @ts-nocheck
2
+ /* biome-ignore lint: test fixture */
3
+ import { definePageAttributes } from "@upstart.gg/sdk";
4
+
5
+ export const attributes = definePageAttributes({
6
+ label: "Broken Page",
7
+ title: "This page is missing a path",
8
+ layout: "default",
9
+ } as any);
@@ -0,0 +1,15 @@
1
+ // @ts-nocheck
2
+ /* biome-ignore lint: test fixture */
3
+ import { definePageAttributes } from "@upstart.gg/sdk";
4
+
5
+ export const attributes = definePageAttributes({
6
+ path: "/contact",
7
+ label: "Contact Us",
8
+ title: "Contact Our Team",
9
+ description: "Get in touch with our team",
10
+ keywords: "contact, email, support",
11
+ layout: "sidebar",
12
+ tags: ["navbar", "important"],
13
+ robotsIndexing: true,
14
+ language: "en",
15
+ });
@@ -0,0 +1,10 @@
1
+ // @ts-nocheck
2
+ /* biome-ignore lint: test fixture */
3
+ import { definePageAttributes } from "@upstart.gg/sdk";
4
+
5
+ export const attributes = definePageAttributes({
6
+ path: "/about",
7
+ label: "About Page",
8
+ title: "About Us",
9
+ layout: "default",
10
+ });
@@ -0,0 +1,12 @@
1
+ // @ts-nocheck
2
+ /* biome-ignore lint: test fixture */
3
+ import { definePageAttributes } from "@upstart.gg/sdk";
4
+
5
+ export const attributes = definePageAttributes({
6
+ path: "/services",
7
+ label: "Services",
8
+ title: "Our Services",
9
+ layout: "default",
10
+ description: "Check out our services",
11
+ tags: ["navbar", "featured"],
12
+ });
@@ -0,0 +1,15 @@
1
+ // @ts-nocheck
2
+ /* biome-ignore lint: test fixture */
3
+ import { definePageAttributes } from "@upstart.gg/sdk";
4
+
5
+ export const attributes = definePageAttributes({
6
+ path: "/advanced",
7
+ label: "Advanced Page",
8
+ title: "Advanced Features",
9
+ layout: "default",
10
+ tags: ["admin", "advanced"],
11
+ additionalTags: {
12
+ headTags: "<meta name='custom' content='value' />",
13
+ bodyTags: "<script>console.log('test')</script>",
14
+ },
15
+ });