@upstart.gg/vite-plugins 0.0.139
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/vite-plugin-upstart-attrs.d.ts +29 -0
- package/dist/vite-plugin-upstart-attrs.d.ts.map +1 -0
- package/dist/vite-plugin-upstart-attrs.js +286 -0
- package/dist/vite-plugin-upstart-attrs.js.map +1 -0
- package/dist/vite-plugin-upstart-editor/plugin.d.ts +15 -0
- package/dist/vite-plugin-upstart-editor/plugin.d.ts.map +1 -0
- package/dist/vite-plugin-upstart-editor/plugin.js +55 -0
- package/dist/vite-plugin-upstart-editor/plugin.js.map +1 -0
- package/dist/vite-plugin-upstart-editor/runtime/click-handler.d.ts +12 -0
- package/dist/vite-plugin-upstart-editor/runtime/click-handler.d.ts.map +1 -0
- package/dist/vite-plugin-upstart-editor/runtime/click-handler.js +57 -0
- package/dist/vite-plugin-upstart-editor/runtime/click-handler.js.map +1 -0
- package/dist/vite-plugin-upstart-editor/runtime/hover-overlay.d.ts +12 -0
- package/dist/vite-plugin-upstart-editor/runtime/hover-overlay.d.ts.map +1 -0
- package/dist/vite-plugin-upstart-editor/runtime/hover-overlay.js +91 -0
- package/dist/vite-plugin-upstart-editor/runtime/hover-overlay.js.map +1 -0
- package/dist/vite-plugin-upstart-editor/runtime/index.d.ts +22 -0
- package/dist/vite-plugin-upstart-editor/runtime/index.d.ts.map +1 -0
- package/dist/vite-plugin-upstart-editor/runtime/index.js +62 -0
- package/dist/vite-plugin-upstart-editor/runtime/index.js.map +1 -0
- package/dist/vite-plugin-upstart-editor/runtime/text-editor.d.ts +15 -0
- package/dist/vite-plugin-upstart-editor/runtime/text-editor.d.ts.map +1 -0
- package/dist/vite-plugin-upstart-editor/runtime/text-editor.js +292 -0
- package/dist/vite-plugin-upstart-editor/runtime/text-editor.js.map +1 -0
- package/dist/vite-plugin-upstart-editor/runtime/types.d.ts +126 -0
- package/dist/vite-plugin-upstart-editor/runtime/types.d.ts.map +1 -0
- package/dist/vite-plugin-upstart-editor/runtime/types.js +1 -0
- package/dist/vite-plugin-upstart-editor/runtime/utils.d.ts +15 -0
- package/dist/vite-plugin-upstart-editor/runtime/utils.d.ts.map +1 -0
- package/dist/vite-plugin-upstart-editor/runtime/utils.js +26 -0
- package/dist/vite-plugin-upstart-editor/runtime/utils.js.map +1 -0
- package/dist/vite-plugin-upstart-routes.d.ts +20 -0
- package/dist/vite-plugin-upstart-routes.d.ts.map +1 -0
- package/dist/vite-plugin-upstart-routes.js +143 -0
- package/dist/vite-plugin-upstart-routes.js.map +1 -0
- package/dist/vite-plugin-upstart-theme.d.ts +22 -0
- package/dist/vite-plugin-upstart-theme.d.ts.map +1 -0
- package/dist/vite-plugin-upstart-theme.js +180 -0
- package/dist/vite-plugin-upstart-theme.js.map +1 -0
- package/package.json +63 -0
- package/src/tests/fixtures/routes/default-layout.tsx +10 -0
- package/src/tests/fixtures/routes/dynamic-route.tsx +10 -0
- package/src/tests/fixtures/routes/missing-attributes.tsx +8 -0
- package/src/tests/fixtures/routes/missing-path.tsx +9 -0
- package/src/tests/fixtures/routes/valid-full.tsx +15 -0
- package/src/tests/fixtures/routes/valid-minimal.tsx +10 -0
- package/src/tests/fixtures/routes/with-comments.tsx +12 -0
- package/src/tests/fixtures/routes/with-nested-objects.tsx +15 -0
- package/src/tests/upstart-editor-api.test.ts +367 -0
- package/src/tests/vite-plugin-upstart-attrs.test.ts +957 -0
- package/src/tests/vite-plugin-upstart-editor.test.ts +81 -0
- package/src/tests/vite-plugin-upstart-routes.test.ts +220 -0
- package/src/upstart-editor-api.ts +204 -0
- package/src/vite-plugin-upstart-attrs.ts +616 -0
- package/src/vite-plugin-upstart-editor/PLAN.md +1391 -0
- package/src/vite-plugin-upstart-editor/plugin.ts +73 -0
- package/src/vite-plugin-upstart-editor/runtime/click-handler.ts +80 -0
- package/src/vite-plugin-upstart-editor/runtime/hover-overlay.ts +135 -0
- package/src/vite-plugin-upstart-editor/runtime/index.ts +90 -0
- package/src/vite-plugin-upstart-editor/runtime/text-editor.ts +401 -0
- package/src/vite-plugin-upstart-editor/runtime/types.ts +120 -0
- package/src/vite-plugin-upstart-editor/runtime/utils.ts +34 -0
- package/src/vite-plugin-upstart-theme.ts +321 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { createUnplugin } from "unplugin";
|
|
2
|
+
import { basename, join, relative } from "node:path";
|
|
3
|
+
import { globSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
|
+
|
|
5
|
+
//#region src/vite-plugin-upstart-routes.ts
|
|
6
|
+
/**
|
|
7
|
+
* Extract the attributes export from source code using regex
|
|
8
|
+
* This avoids importing the module and triggering asset loading errors
|
|
9
|
+
* Requires: export const attributes = definePageAttributes({ ... })
|
|
10
|
+
*/
|
|
11
|
+
function extractAttributesFromSource(code) {
|
|
12
|
+
const match = code.match(/export\s+const\s+attributes\s*=\s*definePageAttributes\s*\(\s*(\{[\s\S]*?\})\s*\)\s*;?/);
|
|
13
|
+
if (!match) throw new Error("attributes export not found in source code");
|
|
14
|
+
const objectStr = match[1];
|
|
15
|
+
try {
|
|
16
|
+
return new Function(`return ${objectStr}`)();
|
|
17
|
+
} catch (error) {
|
|
18
|
+
throw new Error(`Failed to parse attributes object: ${error instanceof Error ? error.message : String(error)}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Extract page attributes from a TypeScript file
|
|
23
|
+
* Tries ssrLoadModule if available (dev/ssr context), falls back to source parsing
|
|
24
|
+
*/
|
|
25
|
+
async function extractPageAttributes(filePath, ssrLoadModule) {
|
|
26
|
+
if (ssrLoadModule) try {
|
|
27
|
+
const attributes = (await ssrLoadModule(filePath)).attributes;
|
|
28
|
+
if (!attributes || typeof attributes !== "object" || !("path" in attributes)) throw new Error("attributes export not found");
|
|
29
|
+
return {
|
|
30
|
+
filename: filePath,
|
|
31
|
+
path: attributes.path,
|
|
32
|
+
layout: attributes.layout ?? "default",
|
|
33
|
+
attributes
|
|
34
|
+
};
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.debug(`[upstart-routes] ssrLoadModule failed for ${filePath}, trying source parsing`);
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const attributes = extractAttributesFromSource(readFileSync(filePath, "utf-8"));
|
|
40
|
+
if (!attributes || typeof attributes !== "object" || !("path" in attributes)) throw new Error("attributes export not found");
|
|
41
|
+
return {
|
|
42
|
+
filename: filePath,
|
|
43
|
+
path: attributes.path,
|
|
44
|
+
layout: attributes.layout ?? "default",
|
|
45
|
+
attributes
|
|
46
|
+
};
|
|
47
|
+
} catch (error) {
|
|
48
|
+
const fullError = error instanceof Error ? error.message : String(error);
|
|
49
|
+
console.error(`[upstart-routes] Import error for ${filePath}:\n${fullError}`);
|
|
50
|
+
throw new Error("Page attributes not found or invalid. Make sure to use `export const attributes = definePageAttributes(...)`");
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Generate routes.ts content
|
|
55
|
+
*/
|
|
56
|
+
function generateRoutesFile(pages, layouts, appDir) {
|
|
57
|
+
const routesMap = /* @__PURE__ */ new Map();
|
|
58
|
+
for (const page of pages) {
|
|
59
|
+
const layoutPages = routesMap.get(page.layout) || [];
|
|
60
|
+
layoutPages.push(page);
|
|
61
|
+
routesMap.set(page.layout, layoutPages);
|
|
62
|
+
}
|
|
63
|
+
const imports = [
|
|
64
|
+
`import {`,
|
|
65
|
+
` type RouteConfig,`,
|
|
66
|
+
` type RouteConfigEntry,`,
|
|
67
|
+
` index,`,
|
|
68
|
+
` layout,`,
|
|
69
|
+
` route,`,
|
|
70
|
+
`} from "@react-router/dev/routes";`,
|
|
71
|
+
``
|
|
72
|
+
].join("\n");
|
|
73
|
+
const routeEntries = [];
|
|
74
|
+
for (const layoutPath of layouts) {
|
|
75
|
+
const layoutName = basename(layoutPath, ".tsx");
|
|
76
|
+
const pagesForLayout = routesMap.get(layoutName) || [];
|
|
77
|
+
if (pagesForLayout.length > 0) {
|
|
78
|
+
const relativeLayoutPath = `./${relative(appDir, layoutPath)}`;
|
|
79
|
+
const pageRoutes = pagesForLayout.map((page) => {
|
|
80
|
+
const relativePagePath = `./${relative(appDir, page.filename)}`;
|
|
81
|
+
if (page.path.trim() === "/") return ` index("${relativePagePath}")`;
|
|
82
|
+
return ` route("${page.path.trim()}", "${relativePagePath}")`;
|
|
83
|
+
}).join(",\n");
|
|
84
|
+
routeEntries.push(` layout("${relativeLayoutPath.trim()}", [\n${pageRoutes}\n ])`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const routesArray = `const routes: RouteConfigEntry[] = [\n${routeEntries.join(",\n")}\n];\n`;
|
|
88
|
+
return [
|
|
89
|
+
`/*`,
|
|
90
|
+
` * THIS FILE IS AUTO-GENERATED BY vite-plugin-upstart-routes`,
|
|
91
|
+
` * DO NOT MODIFY THIS FILE DIRECTLY - IT WILL BE OVERWRITTEN`,
|
|
92
|
+
` * `,
|
|
93
|
+
` * To modify routes, edit pages in the app/pages/ directory`,
|
|
94
|
+
` * Each page must export: export const attributes = definePageAttributes({ path: "/your-path", layout: "layoutName", ... })`,
|
|
95
|
+
` */`,
|
|
96
|
+
``
|
|
97
|
+
].join("\n") + imports + routesArray + `\nexport default routes satisfies RouteConfig;\n`;
|
|
98
|
+
}
|
|
99
|
+
const upstartRoutes = createUnplugin((options = {}) => {
|
|
100
|
+
let appDir;
|
|
101
|
+
let outputFile;
|
|
102
|
+
let ssrLoadModule;
|
|
103
|
+
return {
|
|
104
|
+
name: "upstart-routes",
|
|
105
|
+
enforce: "pre",
|
|
106
|
+
async buildStart() {
|
|
107
|
+
try {
|
|
108
|
+
const pageFiles = globSync(join(appDir, "pages/**/*.tsx"));
|
|
109
|
+
if (pageFiles.length === 0) {
|
|
110
|
+
console.warn(`[upstart-routes] No pages found in ${appDir}/pages`);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const pages = [];
|
|
114
|
+
for (const filePath of pageFiles) try {
|
|
115
|
+
const pageInfo = await extractPageAttributes(filePath, ssrLoadModule);
|
|
116
|
+
pages.push(pageInfo);
|
|
117
|
+
} catch (error) {
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
const layouts = globSync(join(appDir, "layouts/**/*.tsx"));
|
|
121
|
+
const errors = [];
|
|
122
|
+
if (layouts.length === 0) errors.push(`- No layouts found in ${appDir}/layouts`);
|
|
123
|
+
if (pages.length === 0) errors.push(`- No pages found in ${appDir}/pages`);
|
|
124
|
+
if (errors.length > 0) throw new Error(errors.join("\n"));
|
|
125
|
+
const routesContent = generateRoutesFile(pages, layouts, appDir);
|
|
126
|
+
writeFileSync(outputFile, routesContent, "utf-8");
|
|
127
|
+
} catch (error) {
|
|
128
|
+
console.error("[upstart-routes] Failed to generate routes:\n", error);
|
|
129
|
+
throw error;
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
vite: { configResolved(resolvedConfig) {
|
|
133
|
+
appDir = options.appDir || join(resolvedConfig.root, "app");
|
|
134
|
+
outputFile = options.outputFile || join(appDir, "routes.ts");
|
|
135
|
+
if (resolvedConfig.environment?.ssrLoadModule) ssrLoadModule = resolvedConfig.environment.ssrLoadModule;
|
|
136
|
+
} }
|
|
137
|
+
};
|
|
138
|
+
});
|
|
139
|
+
var vite_plugin_upstart_routes_default = upstartRoutes.vite;
|
|
140
|
+
|
|
141
|
+
//#endregion
|
|
142
|
+
export { vite_plugin_upstart_routes_default as default, upstartRoutes };
|
|
143
|
+
//# sourceMappingURL=vite-plugin-upstart-routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vite-plugin-upstart-routes.js","names":["routeEntries: string[]","appDir: string","outputFile: string","ssrLoadModule: ((id: string) => Promise<Record<string, any>>) | undefined","pages: PageInfo[]","errors: string[]"],"sources":["../src/vite-plugin-upstart-routes.ts"],"sourcesContent":["import { createUnplugin } from \"unplugin\";\nimport { globSync } from \"node:fs\";\nimport { writeFileSync, readFileSync } from \"node:fs\";\nimport { join, relative, basename } from \"node:path\";\n\ninterface Options {\n /**\n * Root directory containing the app (with pages/ and layouts/)\n * Defaults to resolvedConfig.root + '/app'\n */\n appDir?: string;\n /**\n * Output file path for generated routes\n * Defaults to appDir + '/routes.ts'\n */\n outputFile?: string;\n}\n\ninterface PageAttributes {\n path?: string;\n layout?: string;\n [key: string]: unknown;\n}\n\ninterface PageInfo {\n filename: string;\n path: string;\n layout: string;\n attributes: PageAttributes;\n}\n\n/**\n * Extract the attributes export from source code using regex\n * This avoids importing the module and triggering asset loading errors\n * Requires: export const attributes = definePageAttributes({ ... })\n */\nfunction extractAttributesFromSource(code: string): Partial<PageAttributes> {\n // Match: export const attributes = definePageAttributes({ ... })\n // definePageAttributes() is mandatory, with or without semicolon\n const match = code.match(\n /export\\s+const\\s+attributes\\s*=\\s*definePageAttributes\\s*\\(\\s*(\\{[\\s\\S]*?\\})\\s*\\)\\s*;?/,\n );\n\n if (!match) {\n throw new Error(\"attributes export not found in source code\");\n }\n\n // Get the matching group (the object literal from definePageAttributes call)\n const objectStr = match[1];\n\n // Use Function constructor to safely evaluate the object literal\n // This is safer than eval and handles object syntax\n try {\n // eslint-disable-next-line no-new-func\n const obj = new Function(`return ${objectStr}`)() as Partial<PageAttributes>;\n return obj;\n } catch (error) {\n throw new Error(\n `Failed to parse attributes object: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n}\n\n/**\n * Extract page attributes from a TypeScript file\n * Tries ssrLoadModule if available (dev/ssr context), falls back to source parsing\n */\nasync function extractPageAttributes(\n filePath: string,\n ssrLoadModule?: (id: string) => Promise<Record<string, any>>,\n): Promise<PageInfo> {\n // Try ssrLoadModule first (handles assets through Vite's pipeline)\n if (ssrLoadModule) {\n try {\n const module = await ssrLoadModule(filePath);\n const attributes = module.attributes as Partial<PageAttributes>;\n\n if (!attributes || typeof attributes !== \"object\" || !(\"path\" in attributes)) {\n throw new Error(\"attributes export not found\");\n }\n\n const path = attributes.path as string;\n const layout = (attributes.layout as string) ?? \"default\";\n\n return {\n filename: filePath,\n path,\n layout,\n attributes: attributes as PageAttributes,\n };\n } catch (error) {\n // If ssrLoadModule fails, fall through to source parsing\n console.debug(`[upstart-routes] ssrLoadModule failed for ${filePath}, trying source parsing`);\n }\n }\n\n // Fallback: extract from source code\n try {\n const code = readFileSync(filePath, \"utf-8\");\n const attributes = extractAttributesFromSource(code);\n\n if (!attributes || typeof attributes !== \"object\" || !(\"path\" in attributes)) {\n throw new Error(\"attributes export not found\");\n }\n\n const path = attributes.path as string;\n const layout = (attributes.layout as string) ?? \"default\";\n\n return {\n filename: filePath,\n path,\n layout,\n attributes: attributes as PageAttributes,\n };\n } catch (error) {\n const fullError = error instanceof Error ? error.message : String(error);\n console.error(`[upstart-routes] Import error for ${filePath}:\\n${fullError}`);\n\n throw new Error(\n \"Page attributes not found or invalid. \" +\n \"Make sure to use `export const attributes = definePageAttributes(...)`\",\n );\n }\n}\n\n/**\n * Generate routes.ts content\n */\nfunction generateRoutesFile(pages: PageInfo[], layouts: string[], appDir: string): string {\n const routesMap = new Map<string, PageInfo[]>();\n\n // Group pages by layout\n for (const page of pages) {\n const layoutPages = routesMap.get(page.layout) || [];\n layoutPages.push(page);\n routesMap.set(page.layout, layoutPages);\n }\n\n // Generate imports\n const imports = [\n `import {`,\n ` type RouteConfig,`,\n ` type RouteConfigEntry,`,\n ` index,`,\n ` layout,`,\n ` route,`,\n `} from \"@react-router/dev/routes\";`,\n ``,\n ].join(\"\\n\");\n\n // Generate routes array\n const routeEntries: string[] = [];\n\n for (const layoutPath of layouts) {\n const layoutName = basename(layoutPath, \".tsx\");\n const pagesForLayout = routesMap.get(layoutName) || [];\n\n if (pagesForLayout.length > 0) {\n const relativeLayoutPath = `./${relative(appDir, layoutPath)}`;\n\n const pageRoutes = pagesForLayout\n .map((page) => {\n const relativePagePath = `./${relative(appDir, page.filename)}`;\n // Use index() for root path, route() for others (more idiomatic)\n if (page.path.trim() === \"/\") {\n return ` index(\"${relativePagePath}\")`;\n }\n return ` route(\"${page.path.trim()}\", \"${relativePagePath}\")`;\n })\n .join(\",\\n\");\n\n routeEntries.push(` layout(\"${relativeLayoutPath.trim()}\", [\\n${pageRoutes}\\n ])`);\n }\n }\n\n const routesArray = `const routes: RouteConfigEntry[] = [\\n${routeEntries.join(\",\\n\")}\\n];\\n`;\n\n const exports = `\\nexport default routes satisfies RouteConfig;\\n`;\n\n const header = [\n `/*`,\n ` * THIS FILE IS AUTO-GENERATED BY vite-plugin-upstart-routes`,\n ` * DO NOT MODIFY THIS FILE DIRECTLY - IT WILL BE OVERWRITTEN`,\n ` * `,\n ` * To modify routes, edit pages in the app/pages/ directory`,\n ` * Each page must export: export const attributes = definePageAttributes({ path: \"/your-path\", layout: \"layoutName\", ... })`,\n ` */`,\n ``,\n ].join(\"\\n\");\n\n return header + imports + routesArray + exports;\n}\n\nexport const upstartRoutes = createUnplugin<Options>((options = {}) => {\n let appDir: string;\n let outputFile: string;\n let ssrLoadModule: ((id: string) => Promise<Record<string, any>>) | undefined;\n\n return {\n name: \"upstart-routes\",\n enforce: \"pre\",\n\n async buildStart() {\n try {\n // Scan for pages\n const pagesGlob = join(appDir, \"pages/**/*.tsx\");\n const pageFiles = globSync(pagesGlob);\n\n if (pageFiles.length === 0) {\n console.warn(`[upstart-routes] No pages found in ${appDir}/pages`);\n return;\n }\n\n // Extract attributes from all pages\n const pages: PageInfo[] = [];\n for (const filePath of pageFiles) {\n try {\n const pageInfo = await extractPageAttributes(filePath, ssrLoadModule);\n pages.push(pageInfo);\n } catch (error) {\n throw error; // Fail fast\n }\n }\n\n // Scan for layouts\n const layoutsGlob = join(appDir, \"layouts/**/*.tsx\");\n const layouts = globSync(layoutsGlob);\n const errors: string[] = [];\n\n if (layouts.length === 0) {\n errors.push(`- No layouts found in ${appDir}/layouts`);\n }\n if (pages.length === 0) {\n errors.push(`- No pages found in ${appDir}/pages`);\n }\n\n if (errors.length > 0) {\n throw new Error(errors.join(\"\\n\"));\n }\n\n // Generate routes.ts content\n const routesContent = generateRoutesFile(pages, layouts, appDir);\n\n // Write to output file\n writeFileSync(outputFile, routesContent, \"utf-8\");\n } catch (error) {\n console.error(\"[upstart-routes] Failed to generate routes:\\n\", error);\n throw error;\n }\n },\n\n vite: {\n configResolved(resolvedConfig: any) {\n appDir = options.appDir || join(resolvedConfig.root, \"app\");\n outputFile = options.outputFile || join(appDir, \"routes.ts\");\n\n // Try to get ssrLoadModule from the environment\n // This is available in dev server and SSR contexts\n if (resolvedConfig.environment?.ssrLoadModule) {\n ssrLoadModule = resolvedConfig.environment.ssrLoadModule;\n }\n },\n },\n };\n});\n\nexport default upstartRoutes.vite;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as unplugin5 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: unplugin5.UnpluginInstance<PluginOptions, boolean>;
|
|
19
|
+
declare const _default: (options: PluginOptions) => unplugin5.VitePlugin<any> | unplugin5.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;IAkPV,OAAA,EAAA,OAiEX,GAAA,MAjEuB;EAiEtB,CAAA;;;;;;;;cAjEU,cAAY,SAAA,CAAA,iBAAA;cAiEtB"}
|
|
@@ -0,0 +1,180 @@
|
|
|
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
|
+
console.log("generateThemeVariables: generating variables for theme", theme.id, "of type", type, "defaultTheme:", defaultTheme);
|
|
106
|
+
const processed = processTheme(theme);
|
|
107
|
+
const lines = [
|
|
108
|
+
` name: "${processed.id}";`,
|
|
109
|
+
` color-scheme: ${processed.browserColorScheme};`,
|
|
110
|
+
...defaultTheme === "dark" && theme.browserColorScheme === "dark" || defaultTheme === "light" && theme.browserColorScheme === "light" ? [` default: true;`] : []
|
|
111
|
+
];
|
|
112
|
+
for (const [colorKey, colorValue] of Object.entries(processed.colors)) {
|
|
113
|
+
const kebabKey = [
|
|
114
|
+
"base100",
|
|
115
|
+
"base200",
|
|
116
|
+
"base300"
|
|
117
|
+
].includes(colorKey) ? colorKey.replace("base", "base-") : camelToKebab(colorKey);
|
|
118
|
+
lines.push(` --color-${kebabKey}: ${colorValue};`);
|
|
119
|
+
}
|
|
120
|
+
lines.push("");
|
|
121
|
+
lines.push(` --radius-selector: ${processed.radiusSelector};`);
|
|
122
|
+
lines.push(` --radius-field: ${processed.radiusField};`);
|
|
123
|
+
lines.push(` --radius-box: ${processed.radiusBox};`);
|
|
124
|
+
lines.push(` --size-selector: ${processed.sizeSelector};`);
|
|
125
|
+
lines.push(` --size-field: ${processed.sizeField};`);
|
|
126
|
+
lines.push(` --border: ${processed.border};`);
|
|
127
|
+
lines.push(` --depth: ${processed.depth ? 1 : 0};`);
|
|
128
|
+
lines.push(` --noise: 0;`);
|
|
129
|
+
return lines.join("\n");
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Unplugin-based theme generator
|
|
133
|
+
*/
|
|
134
|
+
const upstartTheme = createUnplugin((opts) => {
|
|
135
|
+
let generated = false;
|
|
136
|
+
return {
|
|
137
|
+
name: "unplugin-theme-generator",
|
|
138
|
+
apply: "serve",
|
|
139
|
+
vite: { configResolved() {
|
|
140
|
+
if (generated) return;
|
|
141
|
+
generated = true;
|
|
142
|
+
if (!opts?.themes?.light) {
|
|
143
|
+
console.warn("No light theme provided to unplugin-theme-generator. A light theme is required.");
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const outputDir = path.dirname(opts.outputPath);
|
|
147
|
+
if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true });
|
|
148
|
+
const { themes, fontsDisplay = "swap" } = opts;
|
|
149
|
+
const fontsCSS = generateFontsCSS(themes.light, themes.dark, fontsDisplay);
|
|
150
|
+
const fontsCSSPath = path.join(outputDir, "fonts.css");
|
|
151
|
+
fs.writeFileSync(fontsCSSPath, fontsCSS);
|
|
152
|
+
console.log(`✓ Generated fonts CSS: ${fontsCSSPath}`);
|
|
153
|
+
const output = [];
|
|
154
|
+
output.push(generateThemeBlock(themes.light, themes.dark));
|
|
155
|
+
output.push("");
|
|
156
|
+
if (themes.dark) {
|
|
157
|
+
output.push("/* Dark theme variables */");
|
|
158
|
+
output.push("@plugin \"daisyui/theme\" {");
|
|
159
|
+
output.push(generateThemeVariables(themes.dark, "dark", themes.default));
|
|
160
|
+
output.push("}");
|
|
161
|
+
output.push("");
|
|
162
|
+
}
|
|
163
|
+
if (themes.light?.id !== themes.dark?.id) {
|
|
164
|
+
output.push("/* Light theme variables */");
|
|
165
|
+
output.push("@plugin \"daisyui/theme\" {");
|
|
166
|
+
output.push(generateThemeVariables(themes.light, "light", themes.default));
|
|
167
|
+
output.push("}");
|
|
168
|
+
output.push("");
|
|
169
|
+
}
|
|
170
|
+
const cssContent = output.join("\n");
|
|
171
|
+
fs.writeFileSync(opts.outputPath, cssContent);
|
|
172
|
+
console.log(`✓ Generated theme CSS: ${opts.outputPath}`);
|
|
173
|
+
} }
|
|
174
|
+
};
|
|
175
|
+
});
|
|
176
|
+
var vite_plugin_upstart_theme_default = upstartTheme.vite;
|
|
177
|
+
|
|
178
|
+
//#endregion
|
|
179
|
+
export { vite_plugin_upstart_theme_default as default, upstartTheme };
|
|
180
|
+
//# 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 console.log(\n \"generateThemeVariables: generating variables for theme\",\n theme.id,\n \"of type\",\n type,\n \"defaultTheme:\",\n defaultTheme,\n );\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 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.139",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"files": [
|
|
6
|
+
"dist",
|
|
7
|
+
"src"
|
|
8
|
+
],
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "vitest --run",
|
|
11
|
+
"test:bun": "bun test",
|
|
12
|
+
"build": "tsdown"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/upstart-gg/monorepo.git",
|
|
17
|
+
"directory": "packages/vite-plugins"
|
|
18
|
+
},
|
|
19
|
+
"sideEffects": false,
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@oxc-parser/binding-linux-arm64-gnu": "^0.101.0",
|
|
22
|
+
"@oxc-parser/binding-linux-x64-gnu": "^0.101.0",
|
|
23
|
+
"@tiptap/core": "catalog:",
|
|
24
|
+
"@tiptap/extension-bubble-menu": "catalog:",
|
|
25
|
+
"@tiptap/extension-placeholder": "catalog:",
|
|
26
|
+
"@tiptap/starter-kit": "catalog:",
|
|
27
|
+
"@upstart.gg/sdk": "workspace:^",
|
|
28
|
+
"magic-string": "^0.30.21",
|
|
29
|
+
"oxc-parser": "^0.101.0",
|
|
30
|
+
"unplugin": "^2.3.11",
|
|
31
|
+
"zimmerframe": "^1.1.4"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/bun": "catalog:",
|
|
35
|
+
"@types/estree": "catalog:",
|
|
36
|
+
"@types/estree-jsx": "catalog:",
|
|
37
|
+
"@types/node": "catalog:",
|
|
38
|
+
"@types/react": "catalog:",
|
|
39
|
+
"tsdown": "catalog:",
|
|
40
|
+
"vitest": "catalog:",
|
|
41
|
+
"@rolldown/binding-linux-arm64-gnu": "catalog:",
|
|
42
|
+
"@rolldown/binding-linux-x64-gnu": "catalog:"
|
|
43
|
+
},
|
|
44
|
+
"exports": {
|
|
45
|
+
"./vite-plugin-upstart-attrs": "./dist/vite-plugin-upstart-attrs.js",
|
|
46
|
+
"./vite-plugin-upstart-editor/plugin": "./dist/vite-plugin-upstart-editor/plugin.js",
|
|
47
|
+
"./vite-plugin-upstart-editor/runtime": "./dist/vite-plugin-upstart-editor/runtime/index.js",
|
|
48
|
+
"./vite-plugin-upstart-editor/runtime/click-handler": "./dist/vite-plugin-upstart-editor/runtime/click-handler.js",
|
|
49
|
+
"./vite-plugin-upstart-editor/runtime/hover-overlay": "./dist/vite-plugin-upstart-editor/runtime/hover-overlay.js",
|
|
50
|
+
"./vite-plugin-upstart-editor/runtime/text-editor": "./dist/vite-plugin-upstart-editor/runtime/text-editor.js",
|
|
51
|
+
"./vite-plugin-upstart-editor/runtime/types": "./dist/vite-plugin-upstart-editor/runtime/types.js",
|
|
52
|
+
"./vite-plugin-upstart-editor/runtime/utils": "./dist/vite-plugin-upstart-editor/runtime/utils.js",
|
|
53
|
+
"./vite-plugin-upstart-theme": "./dist/vite-plugin-upstart-theme.js",
|
|
54
|
+
"./package.json": "./package.json"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"@upstart.gg/sdk": "workspace:^"
|
|
58
|
+
},
|
|
59
|
+
"author": "Upstart",
|
|
60
|
+
"publishConfig": {
|
|
61
|
+
"access": "public"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -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,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
|
+
});
|