prev-cli 0.24.19 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +2006 -1703
- package/dist/previews/components/cart-item/index.d.ts +5 -0
- package/dist/previews/components/price-tag/index.d.ts +6 -0
- package/dist/previews/screens/cart/empty.d.ts +1 -0
- package/dist/previews/screens/cart/index.d.ts +1 -0
- package/dist/previews/screens/payment/error.d.ts +1 -0
- package/dist/previews/screens/payment/index.d.ts +1 -0
- package/dist/previews/screens/payment/processing.d.ts +1 -0
- package/dist/previews/screens/receipt/index.d.ts +1 -0
- package/dist/previews/shared/data.d.ts +30 -0
- package/dist/src/content/config-parser.d.ts +30 -0
- package/dist/src/content/flow-verifier.d.ts +21 -0
- package/dist/src/content/preview-types.d.ts +288 -0
- package/dist/{vite → src/content}/previews.d.ts +3 -11
- package/dist/{preview-runtime → src/preview-runtime}/build-optimized.d.ts +2 -0
- package/dist/{preview-runtime → src/preview-runtime}/build.d.ts +1 -1
- package/dist/src/preview-runtime/region-bridge.d.ts +1 -0
- package/dist/{preview-runtime → src/preview-runtime}/types.d.ts +18 -0
- package/dist/src/preview-runtime/vendors.d.ts +11 -0
- package/dist/{renderers → src/renderers}/index.d.ts +1 -1
- package/dist/{renderers → src/renderers}/types.d.ts +3 -31
- package/dist/src/server/build.d.ts +6 -0
- package/dist/src/server/dev.d.ts +13 -0
- package/dist/src/server/plugins/aliases.d.ts +5 -0
- package/dist/src/server/plugins/mdx.d.ts +5 -0
- package/dist/src/server/plugins/virtual-modules.d.ts +8 -0
- package/dist/src/server/preview.d.ts +10 -0
- package/dist/src/server/routes/component-bundle.d.ts +1 -0
- package/dist/src/server/routes/jsx-bundle.d.ts +3 -0
- package/dist/src/server/routes/og-image.d.ts +15 -0
- package/dist/src/server/routes/preview-bundle.d.ts +1 -0
- package/dist/src/server/routes/preview-config.d.ts +1 -0
- package/dist/src/server/routes/tokens.d.ts +1 -0
- package/dist/{vite → src/server}/start.d.ts +5 -2
- package/dist/{ui → src/ui}/button.d.ts +1 -1
- package/dist/{validators → src/validators}/index.d.ts +0 -5
- package/dist/{validators → src/validators}/semantic-validator.d.ts +2 -3
- package/package.json +8 -11
- package/src/jsx/CLAUDE.md +18 -0
- package/src/jsx/jsx-runtime.ts +1 -1
- package/src/preview-runtime/CLAUDE.md +21 -0
- package/src/preview-runtime/build-optimized.ts +189 -73
- package/src/preview-runtime/build.ts +75 -79
- package/src/preview-runtime/fast-template.html +5 -1
- package/src/preview-runtime/region-bridge.test.ts +41 -0
- package/src/preview-runtime/region-bridge.ts +101 -0
- package/src/preview-runtime/types.ts +6 -0
- package/src/preview-runtime/vendors.ts +215 -22
- package/src/primitives/CLAUDE.md +17 -0
- package/src/theme/CLAUDE.md +20 -0
- package/src/theme/Preview.tsx +10 -4
- package/src/theme/Toolbar.tsx +2 -2
- package/src/theme/entry.tsx +247 -121
- package/src/theme/hooks/useAnnotations.ts +77 -0
- package/src/theme/hooks/useApprovalStatus.ts +50 -0
- package/src/theme/hooks/useSnapshots.ts +147 -0
- package/src/theme/hooks/useStorage.ts +26 -0
- package/src/theme/hooks/useTokenOverrides.ts +56 -0
- package/src/theme/hooks/useViewport.ts +23 -0
- package/src/theme/icons.tsx +39 -1
- package/src/theme/index.html +18 -0
- package/src/theme/mdx-components.tsx +1 -1
- package/src/theme/previews/AnnotationLayer.tsx +285 -0
- package/src/theme/previews/AnnotationPin.tsx +61 -0
- package/src/theme/previews/AnnotationThread.tsx +257 -0
- package/src/theme/previews/CLAUDE.md +18 -0
- package/src/theme/previews/ComponentPreview.tsx +487 -107
- package/src/theme/previews/FlowDiagram.tsx +111 -0
- package/src/theme/previews/FlowPreview.tsx +938 -174
- package/src/theme/previews/PreviewRouter.tsx +1 -4
- package/src/theme/previews/ScreenPreview.tsx +515 -175
- package/src/theme/previews/SnapshotButton.tsx +68 -0
- package/src/theme/previews/SnapshotCompare.tsx +216 -0
- package/src/theme/previews/SnapshotPanel.tsx +274 -0
- package/src/theme/previews/StatusBadge.tsx +66 -0
- package/src/theme/previews/StatusDropdown.tsx +158 -0
- package/src/theme/previews/TokenPlayground.tsx +438 -0
- package/src/theme/previews/ViewportControls.tsx +67 -0
- package/src/theme/previews/flow-diagram.test.ts +141 -0
- package/src/theme/previews/flow-diagram.ts +109 -0
- package/src/theme/previews/flow-navigation.test.ts +90 -0
- package/src/theme/previews/flow-navigation.ts +47 -0
- package/src/theme/previews/machines/derived.test.ts +225 -0
- package/src/theme/previews/machines/derived.ts +73 -0
- package/src/theme/previews/machines/flow-machine.test.ts +379 -0
- package/src/theme/previews/machines/flow-machine.ts +207 -0
- package/src/theme/previews/machines/screen-machine.test.ts +149 -0
- package/src/theme/previews/machines/screen-machine.ts +76 -0
- package/src/theme/previews/stores/flow-store.test.ts +157 -0
- package/src/theme/previews/stores/flow-store.ts +49 -0
- package/src/theme/previews/stores/screen-store.test.ts +68 -0
- package/src/theme/previews/stores/screen-store.ts +33 -0
- package/src/theme/storage.test.ts +97 -0
- package/src/theme/storage.ts +71 -0
- package/src/theme/styles.css +296 -25
- package/src/theme/types.ts +64 -0
- package/src/tokens/CLAUDE.md +16 -0
- package/src/tokens/resolver.ts +1 -1
- package/dist/preview-runtime/vendors.d.ts +0 -6
- package/dist/vite/config-parser.d.ts +0 -13
- package/dist/vite/config.d.ts +0 -12
- package/dist/vite/plugins/config-plugin.d.ts +0 -3
- package/dist/vite/plugins/debug-plugin.d.ts +0 -3
- package/dist/vite/plugins/entry-plugin.d.ts +0 -2
- package/dist/vite/plugins/fumadocs-plugin.d.ts +0 -9
- package/dist/vite/plugins/pages-plugin.d.ts +0 -5
- package/dist/vite/plugins/previews-plugin.d.ts +0 -2
- package/dist/vite/plugins/tokens-plugin.d.ts +0 -2
- package/dist/vite/preview-types.d.ts +0 -70
- package/src/theme/previews/AtlasPreview.tsx +0 -528
- package/dist/{cli.d.ts → src/cli.d.ts} +0 -0
- package/dist/{config → src/config}/index.d.ts +0 -0
- package/dist/{config → src/config}/loader.d.ts +0 -0
- package/dist/{config → src/config}/schema.d.ts +0 -0
- package/dist/{vite → src/content}/pages.d.ts +0 -0
- package/dist/{jsx → src/jsx}/adapters/html.d.ts +0 -0
- package/dist/{jsx → src/jsx}/adapters/react.d.ts +0 -0
- package/dist/{jsx → src/jsx}/define-component.d.ts +0 -0
- package/dist/{jsx → src/jsx}/index.d.ts +0 -0
- package/dist/{jsx → src/jsx}/jsx-runtime.d.ts +0 -0
- package/dist/{jsx → src/jsx}/migrate.d.ts +0 -0
- package/dist/{jsx → src/jsx}/schemas/index.d.ts +0 -0
- package/dist/{jsx → src/jsx}/schemas/primitives.d.ts +10 -10
- package/dist/{jsx → src/jsx}/schemas/tokens.d.ts +3 -3
- /package/dist/{jsx → src/jsx}/validation.d.ts +0 -0
- /package/dist/{jsx → src/jsx}/vnode.d.ts +0 -0
- /package/dist/{migrate.d.ts → src/migrate.d.ts} +0 -0
- /package/dist/{preview-runtime → src/preview-runtime}/tailwind.d.ts +0 -0
- /package/dist/{primitives → src/primitives}/index.d.ts +0 -0
- /package/dist/{primitives → src/primitives}/migrate.d.ts +0 -0
- /package/dist/{primitives → src/primitives}/parser.d.ts +0 -0
- /package/dist/{primitives → src/primitives}/template-parser.d.ts +0 -0
- /package/dist/{primitives → src/primitives}/template-renderer.d.ts +0 -0
- /package/dist/{primitives → src/primitives}/types.d.ts +0 -0
- /package/dist/{renderers → src/renderers}/html/index.d.ts +0 -0
- /package/dist/{renderers → src/renderers}/react/index.d.ts +0 -0
- /package/dist/{renderers → src/renderers}/registry.d.ts +0 -0
- /package/dist/{renderers → src/renderers}/render.d.ts +0 -0
- /package/dist/{tokens → src/tokens}/defaults.d.ts +0 -0
- /package/dist/{tokens → src/tokens}/resolver.d.ts +0 -0
- /package/dist/{tokens → src/tokens}/utils.d.ts +0 -0
- /package/dist/{tokens → src/tokens}/validation.d.ts +0 -0
- /package/dist/{typecheck → src/typecheck}/index.d.ts +0 -0
- /package/dist/{ui → src/ui}/card.d.ts +0 -0
- /package/dist/{ui → src/ui}/index.d.ts +0 -0
- /package/dist/{ui → src/ui}/utils.d.ts +0 -0
- /package/dist/{utils → src/utils}/cache.d.ts +0 -0
- /package/dist/{utils → src/utils}/debug.d.ts +0 -0
- /package/dist/{utils → src/utils}/port.d.ts +0 -0
- /package/dist/{validators → src/validators}/schema-validator.d.ts +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function createTokensHandler(rootDir: string): (req: Request) => Promise<Response | null>;
|
|
@@ -8,6 +8,9 @@ export interface BuildOptions {
|
|
|
8
8
|
base?: string;
|
|
9
9
|
debug?: boolean;
|
|
10
10
|
}
|
|
11
|
-
export declare function startDev(rootDir: string, options?: DevOptions): Promise<
|
|
11
|
+
export declare function startDev(rootDir: string, options?: DevOptions): Promise<Bun.Server<undefined>>;
|
|
12
12
|
export declare function buildSite(rootDir: string, options?: BuildOptions): Promise<void>;
|
|
13
|
-
export declare function previewSite(rootDir: string, options?: DevOptions): Promise<
|
|
13
|
+
export declare function previewSite(rootDir: string, options?: DevOptions): Promise<{
|
|
14
|
+
url: string;
|
|
15
|
+
stop: () => Promise<void>;
|
|
16
|
+
}>;
|
|
@@ -3,7 +3,7 @@ import { type VariantProps } from 'class-variance-authority';
|
|
|
3
3
|
declare const buttonVariants: (props?: ({
|
|
4
4
|
variant?: "link" | "default" | "secondary" | "destructive" | "outline" | "ghost" | null | undefined;
|
|
5
5
|
size?: "default" | "sm" | "lg" | "icon" | null | undefined;
|
|
6
|
-
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
6
|
+
} & import("node_modules/class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
7
7
|
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
8
8
|
}
|
|
9
9
|
declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
@@ -14,7 +14,7 @@ export interface SemanticValidationWarning {
|
|
|
14
14
|
message: string;
|
|
15
15
|
code: SemanticWarningCode;
|
|
16
16
|
}
|
|
17
|
-
export type SemanticErrorCode = 'DUPLICATE_ID' | 'INVALID_REF' | 'INVALID_STATE_REF' | 'INVALID_STEP_REF' | '
|
|
17
|
+
export type SemanticErrorCode = 'DUPLICATE_ID' | 'INVALID_REF' | 'INVALID_STATE_REF' | 'INVALID_STEP_REF' | 'CIRCULAR_DEPENDENCY' | 'UNKNOWN_RENDERER' | 'INVALID_TEMPLATE' | 'INVALID_SLOT' | 'MISSING_SLOT_DEFINITION';
|
|
18
18
|
export type SemanticWarningCode = 'DEPRECATED_STATUS' | 'MISSING_DESCRIPTION';
|
|
19
19
|
export interface ValidationContext {
|
|
20
20
|
/** Root directory containing previews folder */
|
|
@@ -24,7 +24,6 @@ export interface ValidationContext {
|
|
|
24
24
|
components: Set<string>;
|
|
25
25
|
screens: Set<string>;
|
|
26
26
|
flows: Set<string>;
|
|
27
|
-
atlas: Set<string>;
|
|
28
27
|
};
|
|
29
28
|
/** Map of screen states by screen ID */
|
|
30
29
|
screenStates: Map<string, Set<string>>;
|
|
@@ -40,7 +39,7 @@ export declare function createValidationContext(rootDir: string): ValidationCont
|
|
|
40
39
|
/**
|
|
41
40
|
* Register a preview unit in the validation context
|
|
42
41
|
*/
|
|
43
|
-
export declare function registerPreviewUnit(context: ValidationContext, type: 'component' | 'screen' | 'flow'
|
|
42
|
+
export declare function registerPreviewUnit(context: ValidationContext, type: 'component' | 'screen' | 'flow', id: string, states?: string[]): void;
|
|
44
43
|
/**
|
|
45
44
|
* Check for duplicate IDs within a type
|
|
46
45
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prev-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "Transform MDX directories into beautiful documentation websites",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"markdown",
|
|
23
23
|
"cli",
|
|
24
24
|
"static-site",
|
|
25
|
-
"
|
|
25
|
+
"bun",
|
|
26
26
|
"react"
|
|
27
27
|
],
|
|
28
28
|
"repository": {
|
|
@@ -46,20 +46,17 @@
|
|
|
46
46
|
"test:all": "bun run test && bun run test:integration"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@
|
|
50
|
-
"@types/react-dom": "^19.0.0",
|
|
51
|
-
"@typescript/native-preview": "^7.0.0-dev",
|
|
49
|
+
"@mdx-js/mdx": "^3.1.0",
|
|
52
50
|
"@mdx-js/react": "^3.1.1",
|
|
53
|
-
"@mdx-js/rollup": "^3.0.0",
|
|
54
|
-
"@tailwindcss/vite": "^4.0.0",
|
|
55
51
|
"@tanstack/react-router": "^1.145.7",
|
|
56
52
|
"@terrastruct/d2": "^0.1.33",
|
|
57
|
-
"@
|
|
53
|
+
"@types/react": "^19.0.0",
|
|
54
|
+
"@types/react-dom": "^19.0.0",
|
|
55
|
+
"@typescript/native-preview": "^7.0.0-dev",
|
|
58
56
|
"ajv": "^8.17.1",
|
|
59
57
|
"ajv-formats": "^3.0.1",
|
|
60
58
|
"class-variance-authority": "^0.7.0",
|
|
61
59
|
"clsx": "^2.1.0",
|
|
62
|
-
"esbuild": "^0.27.2",
|
|
63
60
|
"fast-glob": "^3.3.0",
|
|
64
61
|
"fumadocs-core": "^16.4.3",
|
|
65
62
|
"fumadocs-ui": "^16.4.3",
|
|
@@ -73,8 +70,8 @@
|
|
|
73
70
|
"remark-gfm": "^4.0.0",
|
|
74
71
|
"tailwind-merge": "^2.5.0",
|
|
75
72
|
"tailwindcss": "3",
|
|
76
|
-
"
|
|
77
|
-
"
|
|
73
|
+
"zod": "^4.3.5",
|
|
74
|
+
"zustand": "^5.0.11"
|
|
78
75
|
},
|
|
79
76
|
"devDependencies": {
|
|
80
77
|
"@types/js-yaml": "^4.0.9",
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<!-- c3-generated: c3-501, c3-502, c3-503, c3-504 -->
|
|
2
|
+
# JSX Primitives (WIP)
|
|
3
|
+
|
|
4
|
+
Before modifying this code, read:
|
|
5
|
+
- `.c3/c3-5-jsx/c3-501-vnode.md` - Virtual node structure
|
|
6
|
+
- `.c3/c3-5-jsx/c3-502-jsx-runtime.md` - JSX transformation
|
|
7
|
+
- `.c3/c3-5-jsx/c3-503-define-component.md` - Component definition API
|
|
8
|
+
- `.c3/c3-5-jsx/c3-504-html-adapter.md` - HTML rendering
|
|
9
|
+
|
|
10
|
+
Primitive types: `col`, `row`, `box`, `spacer`, `slot`, `text`, `icon`, `image`, `fragment`
|
|
11
|
+
|
|
12
|
+
Key files:
|
|
13
|
+
- `vnode.ts` - VNode creation and normalization
|
|
14
|
+
- `jsx-runtime.ts` - JSX transformation runtime
|
|
15
|
+
- `define-component.ts` - Component definition
|
|
16
|
+
- `adapters/html.ts` - HTML output adapter
|
|
17
|
+
- `adapters/react.tsx` - React output adapter
|
|
18
|
+
<!-- end-c3-generated -->
|
package/src/jsx/jsx-runtime.ts
CHANGED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<!-- c3-generated: c3-207 -->
|
|
2
|
+
# c3-207: Preview Runtime
|
|
3
|
+
|
|
4
|
+
Before modifying this code, read:
|
|
5
|
+
- Component: `.c3/c3-2-build/c3-207-preview-runtime.md`
|
|
6
|
+
- Patterns: `ref-preview-types`
|
|
7
|
+
|
|
8
|
+
Key responsibilities:
|
|
9
|
+
- Build shared vendor bundle (React, ReactDOM)
|
|
10
|
+
- Compile individual preview bundles with Bun.build()
|
|
11
|
+
- Process Tailwind CSS v4 for production
|
|
12
|
+
- Generate standalone HTML files
|
|
13
|
+
|
|
14
|
+
Files:
|
|
15
|
+
- `build-optimized.ts` - Main preview building logic
|
|
16
|
+
- `vendors.ts` - Shared vendor bundle
|
|
17
|
+
- `tailwind.ts` - Tailwind CSS compilation
|
|
18
|
+
- `types.ts` - Type definitions
|
|
19
|
+
|
|
20
|
+
Full refs: `.c3/refs/ref-preview-types.md`
|
|
21
|
+
<!-- end-c3-generated -->
|
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
import { build } from 'esbuild'
|
|
2
1
|
import type { PreviewConfig } from './types'
|
|
3
2
|
import { compileTailwind } from './tailwind'
|
|
3
|
+
import { existsSync, readFileSync, mkdtempSync, writeFileSync, rmSync, mkdirSync, statSync } from 'fs'
|
|
4
|
+
import path from 'path'
|
|
5
|
+
import { tmpdir } from 'os'
|
|
6
|
+
|
|
7
|
+
function existsAsFile(p: string): boolean {
|
|
8
|
+
try { return statSync(p).isFile() } catch { return false }
|
|
9
|
+
}
|
|
4
10
|
|
|
5
11
|
export interface OptimizedBuildOptions {
|
|
6
12
|
vendorPath: string
|
|
13
|
+
jsxPath?: string
|
|
14
|
+
resolveDir?: string
|
|
7
15
|
}
|
|
8
16
|
|
|
9
17
|
export interface OptimizedBuildResult {
|
|
@@ -19,6 +27,9 @@ export async function buildOptimizedPreview(
|
|
|
19
27
|
): Promise<OptimizedBuildResult> {
|
|
20
28
|
try {
|
|
21
29
|
const virtualFs: Record<string, { contents: string; loader: string }> = {}
|
|
30
|
+
const resolveDir = options.resolveDir || '/'
|
|
31
|
+
|
|
32
|
+
// Index files by their path for quick lookup
|
|
22
33
|
for (const file of config.files) {
|
|
23
34
|
const ext = file.path.split('.').pop()?.toLowerCase()
|
|
24
35
|
const loader = ext === 'css' ? 'css' : ext === 'json' ? 'json' : ext || 'tsx'
|
|
@@ -42,99 +53,204 @@ export async function buildOptimizedPreview(
|
|
|
42
53
|
`
|
|
43
54
|
: `import './${config.entry}'`
|
|
44
55
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
// Write all virtual files to a temp directory for Bun.build
|
|
57
|
+
const tempDir = mkdtempSync(path.join(tmpdir(), 'prev-optimized-'))
|
|
58
|
+
const entryPath = path.join(tempDir, '__entry.tsx')
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
writeFileSync(entryPath, entryCode)
|
|
62
|
+
|
|
63
|
+
// Write virtual files to temp dir
|
|
64
|
+
for (const [filePath, file] of Object.entries(virtualFs)) {
|
|
65
|
+
const targetPath = path.join(tempDir, filePath)
|
|
66
|
+
const dir = path.dirname(targetPath)
|
|
67
|
+
if (!existsSync(dir)) {
|
|
68
|
+
mkdirSync(dir, { recursive: true })
|
|
69
|
+
}
|
|
70
|
+
writeFileSync(targetPath, file.contents)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const result = await Bun.build({
|
|
74
|
+
entrypoints: [entryPath],
|
|
75
|
+
format: 'esm',
|
|
76
|
+
target: 'browser',
|
|
77
|
+
minify: true,
|
|
78
|
+
jsx: { runtime: 'automatic', importSource: 'react' },
|
|
79
|
+
plugins: [
|
|
80
|
+
{
|
|
81
|
+
name: 'optimized-preview',
|
|
82
|
+
setup(build) {
|
|
83
|
+
// External: vendor runtime
|
|
84
|
+
build.onResolve(
|
|
85
|
+
{ filter: new RegExp(options.vendorPath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')) },
|
|
86
|
+
args => {
|
|
87
|
+
return { path: args.path, external: true }
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
// External: React (map to vendor bundle)
|
|
92
|
+
build.onResolve({ filter: /^react(-dom)?(\/.*)?$/ }, () => {
|
|
93
|
+
return { path: options.vendorPath, external: true }
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
// External: @prev/jsx (map to jsx bundle)
|
|
97
|
+
build.onResolve({ filter: /^@prev\/jsx$/ }, () => {
|
|
98
|
+
const jsxPath = options.jsxPath || options.vendorPath.replace('runtime.js', 'jsx.js')
|
|
99
|
+
return { path: jsxPath, external: true }
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
// External: @prev/components/* (not supported in static builds yet)
|
|
103
|
+
build.onResolve({ filter: /^@prev\/components\// }, args => {
|
|
104
|
+
console.warn(` Warning: @prev/components imports not supported in static builds: ${args.path}`)
|
|
62
105
|
return { path: args.path, external: true }
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
break
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
// Intercept CSS imports to collect them
|
|
109
|
+
build.onLoad({ filter: /\.css$/ }, args => {
|
|
110
|
+
// Read from temp dir or resolveDir
|
|
111
|
+
let content: string
|
|
112
|
+
const tempPath = args.path
|
|
113
|
+
if (existsSync(tempPath)) {
|
|
114
|
+
content = readFileSync(tempPath, 'utf-8')
|
|
115
|
+
} else {
|
|
116
|
+
const diskPath = path.resolve(resolveDir, path.relative(tempDir, tempPath))
|
|
117
|
+
if (existsSync(diskPath)) {
|
|
118
|
+
content = readFileSync(diskPath, 'utf-8')
|
|
119
|
+
} else {
|
|
120
|
+
return { contents: '', loader: 'js' }
|
|
79
121
|
}
|
|
80
122
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
123
|
+
userCssCollected.push(content)
|
|
124
|
+
return { contents: '', loader: 'js' }
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
// Resolve relative imports that might need to fall back to resolveDir
|
|
128
|
+
build.onResolve({ filter: /^\.\.?\// }, args => {
|
|
129
|
+
const resolved = path.resolve(path.dirname(args.importer), args.path)
|
|
130
|
+
// If it exists in temp dir as a file, let Bun handle it
|
|
131
|
+
const tryExts = ['.tsx', '.ts', '.jsx', '.js', '.css']
|
|
132
|
+
const tryIndex = ['/index.tsx', '/index.ts', '/index.jsx', '/index.js']
|
|
133
|
+
if (existsAsFile(resolved)) return undefined
|
|
134
|
+
for (const ext of tryExts) {
|
|
135
|
+
if (existsAsFile(resolved + ext)) return undefined
|
|
136
|
+
}
|
|
137
|
+
for (const idx of tryIndex) {
|
|
138
|
+
if (existsAsFile(resolved + idx)) return undefined
|
|
92
139
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
140
|
+
// Fall back: resolve using original directory structure
|
|
141
|
+
const importerRelative = path.relative(tempDir, args.importer)
|
|
142
|
+
const originalDir = path.resolve(resolveDir, path.dirname(importerRelative))
|
|
143
|
+
const diskPath = path.resolve(originalDir, args.path)
|
|
144
|
+
if (existsAsFile(diskPath)) return { path: diskPath }
|
|
145
|
+
for (const ext of tryExts) {
|
|
146
|
+
if (existsAsFile(diskPath + ext)) {
|
|
147
|
+
return { path: diskPath + ext }
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
for (const idx of tryIndex) {
|
|
151
|
+
if (existsAsFile(diskPath + idx)) {
|
|
152
|
+
return { path: diskPath + idx }
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return undefined
|
|
156
|
+
})
|
|
157
|
+
},
|
|
97
158
|
},
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
const jsFile = result.outputFiles?.find(f => f.path.endsWith('.js')) || result.outputFiles?.[0]
|
|
103
|
-
const jsCode = jsFile?.text || ''
|
|
104
|
-
|
|
105
|
-
let css = ''
|
|
106
|
-
if (config.tailwind) {
|
|
107
|
-
const tailwindResult = await compileTailwind(
|
|
108
|
-
config.files.map(f => ({ path: f.path, content: f.content }))
|
|
109
|
-
)
|
|
110
|
-
if (tailwindResult.success) css = tailwindResult.css
|
|
111
|
-
}
|
|
159
|
+
],
|
|
160
|
+
})
|
|
112
161
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
userCss = userCss.replace(/@import\s*["']tailwindcss["']\s*;?/g, '')
|
|
118
|
-
}
|
|
119
|
-
const allCss = css + '\n' + userCss
|
|
162
|
+
if (!result.success) {
|
|
163
|
+
const errors = result.logs.filter(l => l.level === 'error').map(l => l.message).join('; ')
|
|
164
|
+
return { success: false, html: '', css: '', error: errors || 'Build failed' }
|
|
165
|
+
}
|
|
120
166
|
|
|
121
|
-
|
|
167
|
+
const jsFile = result.outputs.find(f => f.path.endsWith('.js')) || result.outputs[0]
|
|
168
|
+
let jsCode = jsFile ? await jsFile.text() : ''
|
|
169
|
+
|
|
170
|
+
// Fix bare specifiers in output — Bun.build externalizes but keeps original specifiers
|
|
171
|
+
const jsxPath = options.jsxPath || options.vendorPath.replace('runtime.js', 'jsx.js')
|
|
172
|
+
jsCode = jsCode.replace(/from\s*["']react\/jsx(-dev)?-runtime["']/g, `from"${options.vendorPath}"`)
|
|
173
|
+
jsCode = jsCode.replace(/from\s*["']react-dom\/client["']/g, `from"${options.vendorPath}"`)
|
|
174
|
+
jsCode = jsCode.replace(/from\s*["']react-dom["']/g, `from"${options.vendorPath}"`)
|
|
175
|
+
jsCode = jsCode.replace(/from\s*["']react["']/g, `from"${options.vendorPath}"`)
|
|
176
|
+
jsCode = jsCode.replace(/from\s*["']@prev\/jsx["']/g, `from"${jsxPath}"`)
|
|
177
|
+
jsCode = jsCode.replace(/from\s*["']@prev\/components\/[^"']*["']/g, `from"${jsxPath}"`)
|
|
178
|
+
|
|
179
|
+
let css = ''
|
|
180
|
+
if (config.tailwind) {
|
|
181
|
+
const tailwindResult = await compileTailwind(
|
|
182
|
+
config.files.map(f => ({ path: f.path, content: f.content }))
|
|
183
|
+
)
|
|
184
|
+
if (tailwindResult.success) css = tailwindResult.css
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Strip @import "tailwindcss" from user CSS when Tailwind is compiled
|
|
188
|
+
let userCss = userCssCollected.join('\n')
|
|
189
|
+
if (config.tailwind) {
|
|
190
|
+
userCss = userCss.replace(/@import\s*["']tailwindcss["']\s*;?/g, '')
|
|
191
|
+
}
|
|
192
|
+
const allCss = css + '\n' + userCss
|
|
193
|
+
|
|
194
|
+
// Canvas styling for showcase presentation
|
|
195
|
+
const canvasStyles = `
|
|
196
|
+
html, body {
|
|
197
|
+
margin: 0;
|
|
198
|
+
min-height: 100vh;
|
|
199
|
+
}
|
|
200
|
+
body {
|
|
201
|
+
display: flex;
|
|
202
|
+
align-items: center;
|
|
203
|
+
justify-content: center;
|
|
204
|
+
background-color: #fafafa;
|
|
205
|
+
background-image:
|
|
206
|
+
radial-gradient(circle at center, #e5e5e5 1px, transparent 1px);
|
|
207
|
+
background-size: 16px 16px;
|
|
208
|
+
padding: 24px;
|
|
209
|
+
box-sizing: border-box;
|
|
210
|
+
}
|
|
211
|
+
@media (prefers-color-scheme: dark) {
|
|
212
|
+
body {
|
|
213
|
+
background-color: #171717;
|
|
214
|
+
background-image:
|
|
215
|
+
radial-gradient(circle at center, #262626 1px, transparent 1px);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
#root {
|
|
219
|
+
background: white;
|
|
220
|
+
border-radius: 12px;
|
|
221
|
+
padding: 32px;
|
|
222
|
+
box-shadow: 0 4px 24px -4px rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(0, 0, 0, 0.04);
|
|
223
|
+
max-width: 100%;
|
|
224
|
+
}
|
|
225
|
+
@media (prefers-color-scheme: dark) {
|
|
226
|
+
#root {
|
|
227
|
+
background: #1c1c1c;
|
|
228
|
+
box-shadow: 0 4px 24px -4px rgba(0, 0, 0, 0.3), 0 0 0 1px rgba(255, 255, 255, 0.06);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
`
|
|
232
|
+
|
|
233
|
+
const html = `<!DOCTYPE html>
|
|
122
234
|
<html lang="en">
|
|
123
235
|
<head>
|
|
124
236
|
<meta charset="UTF-8">
|
|
125
237
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
126
238
|
<title>Preview</title>
|
|
127
239
|
<style>${allCss}</style>
|
|
128
|
-
<style
|
|
240
|
+
<style>${canvasStyles}</style>
|
|
129
241
|
</head>
|
|
130
242
|
<body>
|
|
131
243
|
<div id="root"></div>
|
|
132
244
|
<script type="module" src="${options.vendorPath}"></script>
|
|
245
|
+
<script type="module" src="${jsxPath}"></script>
|
|
133
246
|
<script type="module">${jsCode}</script>
|
|
134
247
|
</body>
|
|
135
248
|
</html>`
|
|
136
249
|
|
|
137
|
-
|
|
250
|
+
return { success: true, html, css: allCss }
|
|
251
|
+
} finally {
|
|
252
|
+
rmSync(tempDir, { recursive: true, force: true })
|
|
253
|
+
}
|
|
138
254
|
} catch (err) {
|
|
139
255
|
return { success: false, html: '', css: '', error: err instanceof Error ? err.message : String(err) }
|
|
140
256
|
}
|