@lukas_holdings/castdom 1.0.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/LICENSE +21 -0
- package/README.md +707 -0
- package/bin/castdom.js +2 -0
- package/dist/astro.cjs +86 -0
- package/dist/astro.cjs.map +1 -0
- package/dist/astro.d.cts +88 -0
- package/dist/astro.d.ts +88 -0
- package/dist/astro.js +80 -0
- package/dist/astro.js.map +1 -0
- package/dist/chunk-COLESJ66.js +57 -0
- package/dist/chunk-COLESJ66.js.map +1 -0
- package/dist/chunk-EJRNKHL5.js +31 -0
- package/dist/chunk-EJRNKHL5.js.map +1 -0
- package/dist/chunk-JRQ6EVQP.cjs +35 -0
- package/dist/chunk-JRQ6EVQP.cjs.map +1 -0
- package/dist/chunk-KGLTVTHU.js +73 -0
- package/dist/chunk-KGLTVTHU.js.map +1 -0
- package/dist/chunk-O4OOMGGM.cjs +198 -0
- package/dist/chunk-O4OOMGGM.cjs.map +1 -0
- package/dist/chunk-ONS533CQ.js +104 -0
- package/dist/chunk-ONS533CQ.js.map +1 -0
- package/dist/chunk-ORY4OMZ5.cjs +110 -0
- package/dist/chunk-ORY4OMZ5.cjs.map +1 -0
- package/dist/chunk-QLEBTZIB.cjs +64 -0
- package/dist/chunk-QLEBTZIB.cjs.map +1 -0
- package/dist/chunk-XS5HAU5E.cjs +109 -0
- package/dist/chunk-XS5HAU5E.cjs.map +1 -0
- package/dist/chunk-YDT4TPB7.cjs +84 -0
- package/dist/chunk-YDT4TPB7.cjs.map +1 -0
- package/dist/chunk-ZBJB7WVV.js +193 -0
- package/dist/chunk-ZBJB7WVV.js.map +1 -0
- package/dist/chunk-ZWZ5ZLJE.js +103 -0
- package/dist/chunk-ZWZ5ZLJE.js.map +1 -0
- package/dist/cli.js +135 -0
- package/dist/index.cjs +540 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +176 -0
- package/dist/index.d.ts +176 -0
- package/dist/index.js +440 -0
- package/dist/index.js.map +1 -0
- package/dist/next.cjs +65 -0
- package/dist/next.cjs.map +1 -0
- package/dist/next.d.cts +72 -0
- package/dist/next.d.ts +72 -0
- package/dist/next.js +48 -0
- package/dist/next.js.map +1 -0
- package/dist/react.cjs +30 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +70 -0
- package/dist/react.d.ts +70 -0
- package/dist/react.js +7 -0
- package/dist/react.js.map +1 -0
- package/dist/renderer-B1R7u2wm.d.ts +30 -0
- package/dist/renderer-Bfzjr6l9.d.cts +30 -0
- package/dist/ssr.cjs +46 -0
- package/dist/ssr.cjs.map +1 -0
- package/dist/ssr.d.cts +83 -0
- package/dist/ssr.d.ts +83 -0
- package/dist/ssr.js +5 -0
- package/dist/ssr.js.map +1 -0
- package/dist/types-ChD5jENU.d.cts +105 -0
- package/dist/types-ChD5jENU.d.ts +105 -0
- package/dist/vite.cjs +83 -0
- package/dist/vite.cjs.map +1 -0
- package/dist/vite.d.cts +81 -0
- package/dist/vite.d.ts +81 -0
- package/dist/vite.js +77 -0
- package/dist/vite.js.map +1 -0
- package/package.json +130 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/** A single bone — one rectangular skeleton element */
|
|
2
|
+
interface Bone {
|
|
3
|
+
/** X position relative to container (px) */
|
|
4
|
+
x: number;
|
|
5
|
+
/** Y position relative to container (px) */
|
|
6
|
+
y: number;
|
|
7
|
+
/** Width (px) */
|
|
8
|
+
w: number;
|
|
9
|
+
/** Height (px) */
|
|
10
|
+
h: number;
|
|
11
|
+
/** Border radius (px). 9999 = circle */
|
|
12
|
+
r: number;
|
|
13
|
+
/** Element type hint for content-aware rendering */
|
|
14
|
+
kind?: BoneKind;
|
|
15
|
+
}
|
|
16
|
+
type BoneKind = "text" | "heading" | "image" | "avatar" | "button" | "input" | "icon" | "divider" | "block";
|
|
17
|
+
/** Bone data for a single breakpoint */
|
|
18
|
+
interface BreakpointData {
|
|
19
|
+
/** Viewport width this was captured at */
|
|
20
|
+
viewport: number;
|
|
21
|
+
/** Container width at capture time */
|
|
22
|
+
containerWidth: number;
|
|
23
|
+
/** Container height at capture time */
|
|
24
|
+
containerHeight: number;
|
|
25
|
+
/** All bones at this breakpoint */
|
|
26
|
+
bones: Bone[];
|
|
27
|
+
}
|
|
28
|
+
/** Complete skeleton definition for a named component */
|
|
29
|
+
interface SkeletonData {
|
|
30
|
+
/** Unique name for this skeleton */
|
|
31
|
+
name: string;
|
|
32
|
+
/** Version hash for cache busting */
|
|
33
|
+
hash: string;
|
|
34
|
+
/** Breakpoint data, sorted ascending by viewport width */
|
|
35
|
+
breakpoints: BreakpointData[];
|
|
36
|
+
/** Timestamp of last extraction */
|
|
37
|
+
extractedAt: number;
|
|
38
|
+
}
|
|
39
|
+
/** Configuration for CastDOM */
|
|
40
|
+
interface CastDOMConfig {
|
|
41
|
+
/** Directory to output generated skeleton data */
|
|
42
|
+
outDir?: string;
|
|
43
|
+
/** Breakpoint widths to capture at (default: [375, 768, 1280]) */
|
|
44
|
+
breakpoints?: number[];
|
|
45
|
+
/** Base color for skeleton bones (default: "#e0e0e0") */
|
|
46
|
+
color?: string;
|
|
47
|
+
/** Shimmer highlight color (default: "#f0f0f0") */
|
|
48
|
+
shimmerColor?: string;
|
|
49
|
+
/** Animation duration in ms (default: 1500) */
|
|
50
|
+
animationDuration?: number;
|
|
51
|
+
/** Enable content-aware bone detection (default: true) */
|
|
52
|
+
contentAware?: boolean;
|
|
53
|
+
/** Minimum bone size to include in px (default: 4) */
|
|
54
|
+
minBoneSize?: number;
|
|
55
|
+
/** CSS class prefix (default: "castdom") */
|
|
56
|
+
classPrefix?: string;
|
|
57
|
+
/** Generate inline styles instead of class-based (default: false) */
|
|
58
|
+
inlineStyles?: boolean;
|
|
59
|
+
/** Enable SSR rendering (default: true) */
|
|
60
|
+
ssr?: boolean;
|
|
61
|
+
/** URL or path to dev server for extraction */
|
|
62
|
+
devServer?: string;
|
|
63
|
+
/** Routes to snapshot for extraction */
|
|
64
|
+
routes?: string[];
|
|
65
|
+
/** Playwright launch options */
|
|
66
|
+
playwright?: {
|
|
67
|
+
headless?: boolean;
|
|
68
|
+
timeout?: number;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/** Registry entry used at runtime */
|
|
72
|
+
interface RegistryEntry {
|
|
73
|
+
data: SkeletonData;
|
|
74
|
+
css: string;
|
|
75
|
+
html: Record<number, string>;
|
|
76
|
+
}
|
|
77
|
+
/** Extraction target — what to snapshot */
|
|
78
|
+
interface ExtractionTarget {
|
|
79
|
+
name: string;
|
|
80
|
+
selector: string;
|
|
81
|
+
route?: string;
|
|
82
|
+
}
|
|
83
|
+
/** Result from the extraction process */
|
|
84
|
+
interface ExtractionResult {
|
|
85
|
+
target: ExtractionTarget;
|
|
86
|
+
skeleton: SkeletonData;
|
|
87
|
+
}
|
|
88
|
+
/** Compressed bone format for wire/storage (delta-encoded) */
|
|
89
|
+
interface CompressedBones {
|
|
90
|
+
/** Version of compression format */
|
|
91
|
+
v: 1;
|
|
92
|
+
/** Viewport width */
|
|
93
|
+
vw: number;
|
|
94
|
+
/** Container dimensions [w, h] */
|
|
95
|
+
c: [number, number];
|
|
96
|
+
/** Flat array: [x, y, w, h, r, kind, ...] per bone. kind is enum index. */
|
|
97
|
+
d: number[];
|
|
98
|
+
}
|
|
99
|
+
/** Default configuration values */
|
|
100
|
+
declare const DEFAULTS: Required<Pick<CastDOMConfig, "outDir" | "breakpoints" | "color" | "shimmerColor" | "animationDuration" | "contentAware" | "minBoneSize" | "classPrefix" | "inlineStyles" | "ssr">>;
|
|
101
|
+
/** Map bone kind to numeric index for compression */
|
|
102
|
+
declare const BONE_KIND_INDEX: Record<BoneKind, number>;
|
|
103
|
+
declare const BONE_KIND_FROM_INDEX: Record<number, BoneKind>;
|
|
104
|
+
|
|
105
|
+
export { type BreakpointData as B, type CastDOMConfig as C, DEFAULTS as D, type ExtractionResult as E, type RegistryEntry as R, type SkeletonData as S, type Bone as a, type CompressedBones as b, BONE_KIND_FROM_INDEX as c, BONE_KIND_INDEX as d, type BoneKind as e, type ExtractionTarget as f };
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/** A single bone — one rectangular skeleton element */
|
|
2
|
+
interface Bone {
|
|
3
|
+
/** X position relative to container (px) */
|
|
4
|
+
x: number;
|
|
5
|
+
/** Y position relative to container (px) */
|
|
6
|
+
y: number;
|
|
7
|
+
/** Width (px) */
|
|
8
|
+
w: number;
|
|
9
|
+
/** Height (px) */
|
|
10
|
+
h: number;
|
|
11
|
+
/** Border radius (px). 9999 = circle */
|
|
12
|
+
r: number;
|
|
13
|
+
/** Element type hint for content-aware rendering */
|
|
14
|
+
kind?: BoneKind;
|
|
15
|
+
}
|
|
16
|
+
type BoneKind = "text" | "heading" | "image" | "avatar" | "button" | "input" | "icon" | "divider" | "block";
|
|
17
|
+
/** Bone data for a single breakpoint */
|
|
18
|
+
interface BreakpointData {
|
|
19
|
+
/** Viewport width this was captured at */
|
|
20
|
+
viewport: number;
|
|
21
|
+
/** Container width at capture time */
|
|
22
|
+
containerWidth: number;
|
|
23
|
+
/** Container height at capture time */
|
|
24
|
+
containerHeight: number;
|
|
25
|
+
/** All bones at this breakpoint */
|
|
26
|
+
bones: Bone[];
|
|
27
|
+
}
|
|
28
|
+
/** Complete skeleton definition for a named component */
|
|
29
|
+
interface SkeletonData {
|
|
30
|
+
/** Unique name for this skeleton */
|
|
31
|
+
name: string;
|
|
32
|
+
/** Version hash for cache busting */
|
|
33
|
+
hash: string;
|
|
34
|
+
/** Breakpoint data, sorted ascending by viewport width */
|
|
35
|
+
breakpoints: BreakpointData[];
|
|
36
|
+
/** Timestamp of last extraction */
|
|
37
|
+
extractedAt: number;
|
|
38
|
+
}
|
|
39
|
+
/** Configuration for CastDOM */
|
|
40
|
+
interface CastDOMConfig {
|
|
41
|
+
/** Directory to output generated skeleton data */
|
|
42
|
+
outDir?: string;
|
|
43
|
+
/** Breakpoint widths to capture at (default: [375, 768, 1280]) */
|
|
44
|
+
breakpoints?: number[];
|
|
45
|
+
/** Base color for skeleton bones (default: "#e0e0e0") */
|
|
46
|
+
color?: string;
|
|
47
|
+
/** Shimmer highlight color (default: "#f0f0f0") */
|
|
48
|
+
shimmerColor?: string;
|
|
49
|
+
/** Animation duration in ms (default: 1500) */
|
|
50
|
+
animationDuration?: number;
|
|
51
|
+
/** Enable content-aware bone detection (default: true) */
|
|
52
|
+
contentAware?: boolean;
|
|
53
|
+
/** Minimum bone size to include in px (default: 4) */
|
|
54
|
+
minBoneSize?: number;
|
|
55
|
+
/** CSS class prefix (default: "castdom") */
|
|
56
|
+
classPrefix?: string;
|
|
57
|
+
/** Generate inline styles instead of class-based (default: false) */
|
|
58
|
+
inlineStyles?: boolean;
|
|
59
|
+
/** Enable SSR rendering (default: true) */
|
|
60
|
+
ssr?: boolean;
|
|
61
|
+
/** URL or path to dev server for extraction */
|
|
62
|
+
devServer?: string;
|
|
63
|
+
/** Routes to snapshot for extraction */
|
|
64
|
+
routes?: string[];
|
|
65
|
+
/** Playwright launch options */
|
|
66
|
+
playwright?: {
|
|
67
|
+
headless?: boolean;
|
|
68
|
+
timeout?: number;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/** Registry entry used at runtime */
|
|
72
|
+
interface RegistryEntry {
|
|
73
|
+
data: SkeletonData;
|
|
74
|
+
css: string;
|
|
75
|
+
html: Record<number, string>;
|
|
76
|
+
}
|
|
77
|
+
/** Extraction target — what to snapshot */
|
|
78
|
+
interface ExtractionTarget {
|
|
79
|
+
name: string;
|
|
80
|
+
selector: string;
|
|
81
|
+
route?: string;
|
|
82
|
+
}
|
|
83
|
+
/** Result from the extraction process */
|
|
84
|
+
interface ExtractionResult {
|
|
85
|
+
target: ExtractionTarget;
|
|
86
|
+
skeleton: SkeletonData;
|
|
87
|
+
}
|
|
88
|
+
/** Compressed bone format for wire/storage (delta-encoded) */
|
|
89
|
+
interface CompressedBones {
|
|
90
|
+
/** Version of compression format */
|
|
91
|
+
v: 1;
|
|
92
|
+
/** Viewport width */
|
|
93
|
+
vw: number;
|
|
94
|
+
/** Container dimensions [w, h] */
|
|
95
|
+
c: [number, number];
|
|
96
|
+
/** Flat array: [x, y, w, h, r, kind, ...] per bone. kind is enum index. */
|
|
97
|
+
d: number[];
|
|
98
|
+
}
|
|
99
|
+
/** Default configuration values */
|
|
100
|
+
declare const DEFAULTS: Required<Pick<CastDOMConfig, "outDir" | "breakpoints" | "color" | "shimmerColor" | "animationDuration" | "contentAware" | "minBoneSize" | "classPrefix" | "inlineStyles" | "ssr">>;
|
|
101
|
+
/** Map bone kind to numeric index for compression */
|
|
102
|
+
declare const BONE_KIND_INDEX: Record<BoneKind, number>;
|
|
103
|
+
declare const BONE_KIND_FROM_INDEX: Record<number, BoneKind>;
|
|
104
|
+
|
|
105
|
+
export { type BreakpointData as B, type CastDOMConfig as C, DEFAULTS as D, type ExtractionResult as E, type RegistryEntry as R, type SkeletonData as S, type Bone as a, type CompressedBones as b, BONE_KIND_FROM_INDEX as c, BONE_KIND_INDEX as d, type BoneKind as e, type ExtractionTarget as f };
|
package/dist/vite.cjs
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var chunkJRQ6EVQP_cjs = require('./chunk-JRQ6EVQP.cjs');
|
|
6
|
+
|
|
7
|
+
// src/adapters/vite.ts
|
|
8
|
+
var VIRTUAL_MODULE_ID = "virtual:castdom";
|
|
9
|
+
var RESOLVED_VIRTUAL_MODULE_ID = "\0virtual:castdom";
|
|
10
|
+
function castdom(options = {}) {
|
|
11
|
+
const outDir = options.outDir ?? chunkJRQ6EVQP_cjs.DEFAULTS.outDir;
|
|
12
|
+
let devPort = options.devPort;
|
|
13
|
+
return {
|
|
14
|
+
name: "castdom",
|
|
15
|
+
enforce: "pre",
|
|
16
|
+
configResolved(config) {
|
|
17
|
+
if (config.command === "serve") {
|
|
18
|
+
devPort ??= config.server?.port ?? 5173;
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
configureServer(server) {
|
|
22
|
+
devPort ??= server.config.server.port ?? 5173;
|
|
23
|
+
server.watcher.add(outDir);
|
|
24
|
+
server.middlewares.use((req, res, next) => {
|
|
25
|
+
if (req.url === "/__castdom/extract") {
|
|
26
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
27
|
+
res.end(JSON.stringify({ status: "ok", message: "Use npx castdom build" }));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
next();
|
|
31
|
+
});
|
|
32
|
+
},
|
|
33
|
+
resolveId(id) {
|
|
34
|
+
if (id === VIRTUAL_MODULE_ID) {
|
|
35
|
+
return RESOLVED_VIRTUAL_MODULE_ID;
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
},
|
|
39
|
+
load(id) {
|
|
40
|
+
if (id === RESOLVED_VIRTUAL_MODULE_ID) {
|
|
41
|
+
return `
|
|
42
|
+
import { loadManifest } from "castdom";
|
|
43
|
+
|
|
44
|
+
let manifest;
|
|
45
|
+
try {
|
|
46
|
+
manifest = await import("${outDir}/manifest.json", { with: { type: "json" } });
|
|
47
|
+
loadManifest(manifest.default || manifest);
|
|
48
|
+
} catch (e) {
|
|
49
|
+
console.warn("CastDOM: No manifest found. Run 'npx castdom build' to generate.");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export default manifest;
|
|
53
|
+
`;
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
},
|
|
57
|
+
handleHotUpdate(ctx) {
|
|
58
|
+
if (ctx.file.includes(outDir)) {
|
|
59
|
+
ctx.server.ws.send({
|
|
60
|
+
type: "custom",
|
|
61
|
+
event: "castdom:update",
|
|
62
|
+
data: { file: ctx.file }
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function castdomExtract(options = {}) {
|
|
69
|
+
return {
|
|
70
|
+
name: "castdom-extract",
|
|
71
|
+
enforce: "pre",
|
|
72
|
+
async buildStart() {
|
|
73
|
+
console.log("CastDOM: Ensure skeletons are up to date with 'npx castdom build'");
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
var vite_default = castdom;
|
|
78
|
+
|
|
79
|
+
exports.castdom = castdom;
|
|
80
|
+
exports.castdomExtract = castdomExtract;
|
|
81
|
+
exports.default = vite_default;
|
|
82
|
+
//# sourceMappingURL=vite.cjs.map
|
|
83
|
+
//# sourceMappingURL=vite.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/vite.ts"],"names":["DEFAULTS"],"mappings":";;;;;;;AA4DA,IAAM,iBAAA,GAAoB,iBAAA;AAC1B,IAAM,0BAAA,GAA6B,mBAAA;AAE5B,SAAS,OAAA,CAAQ,OAAA,GAA8B,EAAC,EAAe;AACpE,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,IAAUA,0BAAA,CAAS,MAAA;AAC1C,EAAA,IAAI,UAA8B,OAAA,CAAQ,OAAA;AAG1C,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,SAAA;AAAA,IACN,OAAA,EAAS,KAAA;AAAA,IAET,eAAe,MAAA,EAAQ;AACrB,MAAA,IAAI,MAAA,CAAO,YAAY,OAAA,EAAS;AAE9B,QAAA,OAAA,KAAY,MAAA,CAAO,QAAQ,IAAA,IAAQ,IAAA;AAAA,MACrC;AAAA,IACF,CAAA;AAAA,IAEA,gBAAgB,MAAA,EAAQ;AACtB,MAAA,OAAA,KAAY,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,IAAA,IAAQ,IAAA;AAGzC,MAAA,MAAA,CAAO,OAAA,CAAQ,IAAI,MAAM,CAAA;AAGzB,MAAA,MAAA,CAAO,WAAA,CAAY,GAAA,CAAI,CAAC,GAAA,EAAU,KAAU,IAAA,KAAc;AACxD,QAAA,IAAI,GAAA,CAAI,QAAQ,oBAAA,EAAsB;AAEpC,UAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,UAAA,GAAA,CAAI,GAAA,CAAI,KAAK,SAAA,CAAU,EAAE,QAAQ,IAAA,EAAM,OAAA,EAAS,uBAAA,EAAyB,CAAC,CAAA;AAC1E,UAAA;AAAA,QACF;AACA,QAAA,IAAA,EAAK;AAAA,MACP,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,UAAU,EAAA,EAAI;AACZ,MAAA,IAAI,OAAO,iBAAA,EAAmB;AAC5B,QAAA,OAAO,0BAAA;AAAA,MACT;AACA,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IAEA,KAAK,EAAA,EAAI;AACP,MAAA,IAAI,OAAO,0BAAA,EAA4B;AAErC,QAAA,OAAO;AAAA;;AAAA;AAAA;AAAA,2BAAA,EAKc,MAAM,CAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,CAAA;AAAA,MAQ7B;AACA,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IAEA,gBAAgB,GAAA,EAAK;AAEnB,MAAA,IAAI,GAAA,CAAI,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AAC7B,QAAA,GAAA,CAAI,MAAA,CAAO,GAAG,IAAA,CAAK;AAAA,UACjB,IAAA,EAAM,QAAA;AAAA,UACN,KAAA,EAAO,gBAAA;AAAA,UACP,IAAA,EAAM,EAAE,IAAA,EAAM,GAAA,CAAI,IAAA;AAAK,SACxB,CAAA;AAAA,MACH;AAAA,IACF;AAAA,GACF;AACF;AAMO,SAAS,cAAA,CAAe,OAAA,GAA8B,EAAC,EAAe;AAC3E,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,iBAAA;AAAA,IACN,OAAA,EAAS,KAAA;AAAA,IAET,MAAM,UAAA,GAAa;AAGjB,MAAA,OAAA,CAAQ,IAAI,mEAAmE,CAAA;AAAA,IACjF;AAAA,GACF;AACF;AAEA,IAAO,YAAA,GAAQ","file":"vite.cjs","sourcesContent":["import type { CastDOMConfig, ExtractionTarget } from \"../core/types.js\";\nimport { DEFAULTS } from \"../core/types.js\";\n\n/**\n * Vite plugin for CastDOM.\n *\n * Features:\n * - Dev mode: live skeleton extraction from running dev server\n * - Build mode: pre-extract and embed skeleton data\n * - HMR: hot-reload skeleton changes\n * - Auto-discovery of [data-castdom] elements\n *\n * Usage:\n * ```ts\n * // vite.config.ts\n * import { castdom } from \"castdom/vite\";\n *\n * export default defineConfig({\n * plugins: [castdom()],\n * });\n * ```\n */\n\nexport interface CastDOMViteOptions {\n /** Path to castdom config file (default: \"castdom.config.json\") */\n configPath?: string;\n /** Output directory (default: \".castdom\") */\n outDir?: string;\n /** Dev server port to extract from (auto-detected if not set) */\n devPort?: number;\n /** Breakpoints to capture (default: [375, 768, 1280]) */\n breakpoints?: number[];\n /** Auto-extract on dev server start (default: false) */\n autoExtract?: boolean;\n /** Watch for changes and re-extract (default: true in dev) */\n watch?: boolean;\n /** Targets to extract (if not using config file) */\n targets?: ExtractionTarget[];\n /** Config overrides */\n config?: Partial<CastDOMConfig>;\n}\n\ninterface VitePlugin {\n name: string;\n enforce?: \"pre\" | \"post\";\n configResolved?: (config: { command: string; server?: { port?: number } }) => void;\n configureServer?: (server: ViteDevServer) => void;\n buildStart?: () => Promise<void>;\n resolveId?: (id: string) => string | null;\n load?: (id: string) => string | null;\n handleHotUpdate?: (ctx: { file: string; server: ViteDevServer }) => void;\n}\n\ninterface ViteDevServer {\n config: { server: { port?: number } };\n ws: { send: (data: unknown) => void };\n watcher: { add: (path: string) => void };\n middlewares: { use: (fn: unknown) => void };\n}\n\nconst VIRTUAL_MODULE_ID = \"virtual:castdom\";\nconst RESOLVED_VIRTUAL_MODULE_ID = \"\\0virtual:castdom\";\n\nexport function castdom(options: CastDOMViteOptions = {}): VitePlugin {\n const outDir = options.outDir ?? DEFAULTS.outDir;\n let devPort: number | undefined = options.devPort;\n let isServing = false;\n\n return {\n name: \"castdom\",\n enforce: \"pre\",\n\n configResolved(config) {\n if (config.command === \"serve\") {\n isServing = true;\n devPort ??= config.server?.port ?? 5173;\n }\n },\n\n configureServer(server) {\n devPort ??= server.config.server.port ?? 5173;\n\n // Watch the output directory for changes\n server.watcher.add(outDir);\n\n // Add dev middleware for on-demand extraction\n server.middlewares.use((req: any, res: any, next: any) => {\n if (req.url === \"/__castdom/extract\") {\n // Trigger extraction via HTTP endpoint in dev\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ status: \"ok\", message: \"Use npx castdom build\" }));\n return;\n }\n next();\n });\n },\n\n resolveId(id) {\n if (id === VIRTUAL_MODULE_ID) {\n return RESOLVED_VIRTUAL_MODULE_ID;\n }\n return null;\n },\n\n load(id) {\n if (id === RESOLVED_VIRTUAL_MODULE_ID) {\n // Provide a virtual module that loads the manifest\n return `\nimport { loadManifest } from \"castdom\";\n\nlet manifest;\ntry {\n manifest = await import(\"${outDir}/manifest.json\", { with: { type: \"json\" } });\n loadManifest(manifest.default || manifest);\n} catch (e) {\n console.warn(\"CastDOM: No manifest found. Run 'npx castdom build' to generate.\");\n}\n\nexport default manifest;\n`;\n }\n return null;\n },\n\n handleHotUpdate(ctx) {\n // Hot-reload when skeleton data changes\n if (ctx.file.includes(outDir)) {\n ctx.server.ws.send({\n type: \"custom\",\n event: \"castdom:update\",\n data: { file: ctx.file },\n });\n }\n },\n };\n}\n\n/**\n * Vite plugin for extracting skeletons during build.\n * Runs `castdom build` as part of the Vite build process.\n */\nexport function castdomExtract(options: CastDOMViteOptions = {}): VitePlugin {\n return {\n name: \"castdom-extract\",\n enforce: \"pre\",\n\n async buildStart() {\n // Only extract during build, not serve\n // The actual extraction is done via the CLI\n console.log(\"CastDOM: Ensure skeletons are up to date with 'npx castdom build'\");\n },\n };\n}\n\nexport default castdom;\n"]}
|
package/dist/vite.d.cts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { f as ExtractionTarget, C as CastDOMConfig } from './types-ChD5jENU.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Vite plugin for CastDOM.
|
|
5
|
+
*
|
|
6
|
+
* Features:
|
|
7
|
+
* - Dev mode: live skeleton extraction from running dev server
|
|
8
|
+
* - Build mode: pre-extract and embed skeleton data
|
|
9
|
+
* - HMR: hot-reload skeleton changes
|
|
10
|
+
* - Auto-discovery of [data-castdom] elements
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* ```ts
|
|
14
|
+
* // vite.config.ts
|
|
15
|
+
* import { castdom } from "castdom/vite";
|
|
16
|
+
*
|
|
17
|
+
* export default defineConfig({
|
|
18
|
+
* plugins: [castdom()],
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
interface CastDOMViteOptions {
|
|
23
|
+
/** Path to castdom config file (default: "castdom.config.json") */
|
|
24
|
+
configPath?: string;
|
|
25
|
+
/** Output directory (default: ".castdom") */
|
|
26
|
+
outDir?: string;
|
|
27
|
+
/** Dev server port to extract from (auto-detected if not set) */
|
|
28
|
+
devPort?: number;
|
|
29
|
+
/** Breakpoints to capture (default: [375, 768, 1280]) */
|
|
30
|
+
breakpoints?: number[];
|
|
31
|
+
/** Auto-extract on dev server start (default: false) */
|
|
32
|
+
autoExtract?: boolean;
|
|
33
|
+
/** Watch for changes and re-extract (default: true in dev) */
|
|
34
|
+
watch?: boolean;
|
|
35
|
+
/** Targets to extract (if not using config file) */
|
|
36
|
+
targets?: ExtractionTarget[];
|
|
37
|
+
/** Config overrides */
|
|
38
|
+
config?: Partial<CastDOMConfig>;
|
|
39
|
+
}
|
|
40
|
+
interface VitePlugin {
|
|
41
|
+
name: string;
|
|
42
|
+
enforce?: "pre" | "post";
|
|
43
|
+
configResolved?: (config: {
|
|
44
|
+
command: string;
|
|
45
|
+
server?: {
|
|
46
|
+
port?: number;
|
|
47
|
+
};
|
|
48
|
+
}) => void;
|
|
49
|
+
configureServer?: (server: ViteDevServer) => void;
|
|
50
|
+
buildStart?: () => Promise<void>;
|
|
51
|
+
resolveId?: (id: string) => string | null;
|
|
52
|
+
load?: (id: string) => string | null;
|
|
53
|
+
handleHotUpdate?: (ctx: {
|
|
54
|
+
file: string;
|
|
55
|
+
server: ViteDevServer;
|
|
56
|
+
}) => void;
|
|
57
|
+
}
|
|
58
|
+
interface ViteDevServer {
|
|
59
|
+
config: {
|
|
60
|
+
server: {
|
|
61
|
+
port?: number;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
ws: {
|
|
65
|
+
send: (data: unknown) => void;
|
|
66
|
+
};
|
|
67
|
+
watcher: {
|
|
68
|
+
add: (path: string) => void;
|
|
69
|
+
};
|
|
70
|
+
middlewares: {
|
|
71
|
+
use: (fn: unknown) => void;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
declare function castdom(options?: CastDOMViteOptions): VitePlugin;
|
|
75
|
+
/**
|
|
76
|
+
* Vite plugin for extracting skeletons during build.
|
|
77
|
+
* Runs `castdom build` as part of the Vite build process.
|
|
78
|
+
*/
|
|
79
|
+
declare function castdomExtract(options?: CastDOMViteOptions): VitePlugin;
|
|
80
|
+
|
|
81
|
+
export { type CastDOMViteOptions, castdom, castdomExtract, castdom as default };
|
package/dist/vite.d.ts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { f as ExtractionTarget, C as CastDOMConfig } from './types-ChD5jENU.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Vite plugin for CastDOM.
|
|
5
|
+
*
|
|
6
|
+
* Features:
|
|
7
|
+
* - Dev mode: live skeleton extraction from running dev server
|
|
8
|
+
* - Build mode: pre-extract and embed skeleton data
|
|
9
|
+
* - HMR: hot-reload skeleton changes
|
|
10
|
+
* - Auto-discovery of [data-castdom] elements
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* ```ts
|
|
14
|
+
* // vite.config.ts
|
|
15
|
+
* import { castdom } from "castdom/vite";
|
|
16
|
+
*
|
|
17
|
+
* export default defineConfig({
|
|
18
|
+
* plugins: [castdom()],
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
interface CastDOMViteOptions {
|
|
23
|
+
/** Path to castdom config file (default: "castdom.config.json") */
|
|
24
|
+
configPath?: string;
|
|
25
|
+
/** Output directory (default: ".castdom") */
|
|
26
|
+
outDir?: string;
|
|
27
|
+
/** Dev server port to extract from (auto-detected if not set) */
|
|
28
|
+
devPort?: number;
|
|
29
|
+
/** Breakpoints to capture (default: [375, 768, 1280]) */
|
|
30
|
+
breakpoints?: number[];
|
|
31
|
+
/** Auto-extract on dev server start (default: false) */
|
|
32
|
+
autoExtract?: boolean;
|
|
33
|
+
/** Watch for changes and re-extract (default: true in dev) */
|
|
34
|
+
watch?: boolean;
|
|
35
|
+
/** Targets to extract (if not using config file) */
|
|
36
|
+
targets?: ExtractionTarget[];
|
|
37
|
+
/** Config overrides */
|
|
38
|
+
config?: Partial<CastDOMConfig>;
|
|
39
|
+
}
|
|
40
|
+
interface VitePlugin {
|
|
41
|
+
name: string;
|
|
42
|
+
enforce?: "pre" | "post";
|
|
43
|
+
configResolved?: (config: {
|
|
44
|
+
command: string;
|
|
45
|
+
server?: {
|
|
46
|
+
port?: number;
|
|
47
|
+
};
|
|
48
|
+
}) => void;
|
|
49
|
+
configureServer?: (server: ViteDevServer) => void;
|
|
50
|
+
buildStart?: () => Promise<void>;
|
|
51
|
+
resolveId?: (id: string) => string | null;
|
|
52
|
+
load?: (id: string) => string | null;
|
|
53
|
+
handleHotUpdate?: (ctx: {
|
|
54
|
+
file: string;
|
|
55
|
+
server: ViteDevServer;
|
|
56
|
+
}) => void;
|
|
57
|
+
}
|
|
58
|
+
interface ViteDevServer {
|
|
59
|
+
config: {
|
|
60
|
+
server: {
|
|
61
|
+
port?: number;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
ws: {
|
|
65
|
+
send: (data: unknown) => void;
|
|
66
|
+
};
|
|
67
|
+
watcher: {
|
|
68
|
+
add: (path: string) => void;
|
|
69
|
+
};
|
|
70
|
+
middlewares: {
|
|
71
|
+
use: (fn: unknown) => void;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
declare function castdom(options?: CastDOMViteOptions): VitePlugin;
|
|
75
|
+
/**
|
|
76
|
+
* Vite plugin for extracting skeletons during build.
|
|
77
|
+
* Runs `castdom build` as part of the Vite build process.
|
|
78
|
+
*/
|
|
79
|
+
declare function castdomExtract(options?: CastDOMViteOptions): VitePlugin;
|
|
80
|
+
|
|
81
|
+
export { type CastDOMViteOptions, castdom, castdomExtract, castdom as default };
|
package/dist/vite.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { DEFAULTS } from './chunk-EJRNKHL5.js';
|
|
2
|
+
|
|
3
|
+
// src/adapters/vite.ts
|
|
4
|
+
var VIRTUAL_MODULE_ID = "virtual:castdom";
|
|
5
|
+
var RESOLVED_VIRTUAL_MODULE_ID = "\0virtual:castdom";
|
|
6
|
+
function castdom(options = {}) {
|
|
7
|
+
const outDir = options.outDir ?? DEFAULTS.outDir;
|
|
8
|
+
let devPort = options.devPort;
|
|
9
|
+
return {
|
|
10
|
+
name: "castdom",
|
|
11
|
+
enforce: "pre",
|
|
12
|
+
configResolved(config) {
|
|
13
|
+
if (config.command === "serve") {
|
|
14
|
+
devPort ??= config.server?.port ?? 5173;
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
configureServer(server) {
|
|
18
|
+
devPort ??= server.config.server.port ?? 5173;
|
|
19
|
+
server.watcher.add(outDir);
|
|
20
|
+
server.middlewares.use((req, res, next) => {
|
|
21
|
+
if (req.url === "/__castdom/extract") {
|
|
22
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
23
|
+
res.end(JSON.stringify({ status: "ok", message: "Use npx castdom build" }));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
next();
|
|
27
|
+
});
|
|
28
|
+
},
|
|
29
|
+
resolveId(id) {
|
|
30
|
+
if (id === VIRTUAL_MODULE_ID) {
|
|
31
|
+
return RESOLVED_VIRTUAL_MODULE_ID;
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
},
|
|
35
|
+
load(id) {
|
|
36
|
+
if (id === RESOLVED_VIRTUAL_MODULE_ID) {
|
|
37
|
+
return `
|
|
38
|
+
import { loadManifest } from "castdom";
|
|
39
|
+
|
|
40
|
+
let manifest;
|
|
41
|
+
try {
|
|
42
|
+
manifest = await import("${outDir}/manifest.json", { with: { type: "json" } });
|
|
43
|
+
loadManifest(manifest.default || manifest);
|
|
44
|
+
} catch (e) {
|
|
45
|
+
console.warn("CastDOM: No manifest found. Run 'npx castdom build' to generate.");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export default manifest;
|
|
49
|
+
`;
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
},
|
|
53
|
+
handleHotUpdate(ctx) {
|
|
54
|
+
if (ctx.file.includes(outDir)) {
|
|
55
|
+
ctx.server.ws.send({
|
|
56
|
+
type: "custom",
|
|
57
|
+
event: "castdom:update",
|
|
58
|
+
data: { file: ctx.file }
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function castdomExtract(options = {}) {
|
|
65
|
+
return {
|
|
66
|
+
name: "castdom-extract",
|
|
67
|
+
enforce: "pre",
|
|
68
|
+
async buildStart() {
|
|
69
|
+
console.log("CastDOM: Ensure skeletons are up to date with 'npx castdom build'");
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
var vite_default = castdom;
|
|
74
|
+
|
|
75
|
+
export { castdom, castdomExtract, vite_default as default };
|
|
76
|
+
//# sourceMappingURL=vite.js.map
|
|
77
|
+
//# sourceMappingURL=vite.js.map
|
package/dist/vite.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/vite.ts"],"names":[],"mappings":";;;AA4DA,IAAM,iBAAA,GAAoB,iBAAA;AAC1B,IAAM,0BAAA,GAA6B,mBAAA;AAE5B,SAAS,OAAA,CAAQ,OAAA,GAA8B,EAAC,EAAe;AACpE,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,IAAU,QAAA,CAAS,MAAA;AAC1C,EAAA,IAAI,UAA8B,OAAA,CAAQ,OAAA;AAG1C,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,SAAA;AAAA,IACN,OAAA,EAAS,KAAA;AAAA,IAET,eAAe,MAAA,EAAQ;AACrB,MAAA,IAAI,MAAA,CAAO,YAAY,OAAA,EAAS;AAE9B,QAAA,OAAA,KAAY,MAAA,CAAO,QAAQ,IAAA,IAAQ,IAAA;AAAA,MACrC;AAAA,IACF,CAAA;AAAA,IAEA,gBAAgB,MAAA,EAAQ;AACtB,MAAA,OAAA,KAAY,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,IAAA,IAAQ,IAAA;AAGzC,MAAA,MAAA,CAAO,OAAA,CAAQ,IAAI,MAAM,CAAA;AAGzB,MAAA,MAAA,CAAO,WAAA,CAAY,GAAA,CAAI,CAAC,GAAA,EAAU,KAAU,IAAA,KAAc;AACxD,QAAA,IAAI,GAAA,CAAI,QAAQ,oBAAA,EAAsB;AAEpC,UAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,UAAA,GAAA,CAAI,GAAA,CAAI,KAAK,SAAA,CAAU,EAAE,QAAQ,IAAA,EAAM,OAAA,EAAS,uBAAA,EAAyB,CAAC,CAAA;AAC1E,UAAA;AAAA,QACF;AACA,QAAA,IAAA,EAAK;AAAA,MACP,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,UAAU,EAAA,EAAI;AACZ,MAAA,IAAI,OAAO,iBAAA,EAAmB;AAC5B,QAAA,OAAO,0BAAA;AAAA,MACT;AACA,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IAEA,KAAK,EAAA,EAAI;AACP,MAAA,IAAI,OAAO,0BAAA,EAA4B;AAErC,QAAA,OAAO;AAAA;;AAAA;AAAA;AAAA,2BAAA,EAKc,MAAM,CAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,CAAA;AAAA,MAQ7B;AACA,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IAEA,gBAAgB,GAAA,EAAK;AAEnB,MAAA,IAAI,GAAA,CAAI,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AAC7B,QAAA,GAAA,CAAI,MAAA,CAAO,GAAG,IAAA,CAAK;AAAA,UACjB,IAAA,EAAM,QAAA;AAAA,UACN,KAAA,EAAO,gBAAA;AAAA,UACP,IAAA,EAAM,EAAE,IAAA,EAAM,GAAA,CAAI,IAAA;AAAK,SACxB,CAAA;AAAA,MACH;AAAA,IACF;AAAA,GACF;AACF;AAMO,SAAS,cAAA,CAAe,OAAA,GAA8B,EAAC,EAAe;AAC3E,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,iBAAA;AAAA,IACN,OAAA,EAAS,KAAA;AAAA,IAET,MAAM,UAAA,GAAa;AAGjB,MAAA,OAAA,CAAQ,IAAI,mEAAmE,CAAA;AAAA,IACjF;AAAA,GACF;AACF;AAEA,IAAO,YAAA,GAAQ","file":"vite.js","sourcesContent":["import type { CastDOMConfig, ExtractionTarget } from \"../core/types.js\";\nimport { DEFAULTS } from \"../core/types.js\";\n\n/**\n * Vite plugin for CastDOM.\n *\n * Features:\n * - Dev mode: live skeleton extraction from running dev server\n * - Build mode: pre-extract and embed skeleton data\n * - HMR: hot-reload skeleton changes\n * - Auto-discovery of [data-castdom] elements\n *\n * Usage:\n * ```ts\n * // vite.config.ts\n * import { castdom } from \"castdom/vite\";\n *\n * export default defineConfig({\n * plugins: [castdom()],\n * });\n * ```\n */\n\nexport interface CastDOMViteOptions {\n /** Path to castdom config file (default: \"castdom.config.json\") */\n configPath?: string;\n /** Output directory (default: \".castdom\") */\n outDir?: string;\n /** Dev server port to extract from (auto-detected if not set) */\n devPort?: number;\n /** Breakpoints to capture (default: [375, 768, 1280]) */\n breakpoints?: number[];\n /** Auto-extract on dev server start (default: false) */\n autoExtract?: boolean;\n /** Watch for changes and re-extract (default: true in dev) */\n watch?: boolean;\n /** Targets to extract (if not using config file) */\n targets?: ExtractionTarget[];\n /** Config overrides */\n config?: Partial<CastDOMConfig>;\n}\n\ninterface VitePlugin {\n name: string;\n enforce?: \"pre\" | \"post\";\n configResolved?: (config: { command: string; server?: { port?: number } }) => void;\n configureServer?: (server: ViteDevServer) => void;\n buildStart?: () => Promise<void>;\n resolveId?: (id: string) => string | null;\n load?: (id: string) => string | null;\n handleHotUpdate?: (ctx: { file: string; server: ViteDevServer }) => void;\n}\n\ninterface ViteDevServer {\n config: { server: { port?: number } };\n ws: { send: (data: unknown) => void };\n watcher: { add: (path: string) => void };\n middlewares: { use: (fn: unknown) => void };\n}\n\nconst VIRTUAL_MODULE_ID = \"virtual:castdom\";\nconst RESOLVED_VIRTUAL_MODULE_ID = \"\\0virtual:castdom\";\n\nexport function castdom(options: CastDOMViteOptions = {}): VitePlugin {\n const outDir = options.outDir ?? DEFAULTS.outDir;\n let devPort: number | undefined = options.devPort;\n let isServing = false;\n\n return {\n name: \"castdom\",\n enforce: \"pre\",\n\n configResolved(config) {\n if (config.command === \"serve\") {\n isServing = true;\n devPort ??= config.server?.port ?? 5173;\n }\n },\n\n configureServer(server) {\n devPort ??= server.config.server.port ?? 5173;\n\n // Watch the output directory for changes\n server.watcher.add(outDir);\n\n // Add dev middleware for on-demand extraction\n server.middlewares.use((req: any, res: any, next: any) => {\n if (req.url === \"/__castdom/extract\") {\n // Trigger extraction via HTTP endpoint in dev\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ status: \"ok\", message: \"Use npx castdom build\" }));\n return;\n }\n next();\n });\n },\n\n resolveId(id) {\n if (id === VIRTUAL_MODULE_ID) {\n return RESOLVED_VIRTUAL_MODULE_ID;\n }\n return null;\n },\n\n load(id) {\n if (id === RESOLVED_VIRTUAL_MODULE_ID) {\n // Provide a virtual module that loads the manifest\n return `\nimport { loadManifest } from \"castdom\";\n\nlet manifest;\ntry {\n manifest = await import(\"${outDir}/manifest.json\", { with: { type: \"json\" } });\n loadManifest(manifest.default || manifest);\n} catch (e) {\n console.warn(\"CastDOM: No manifest found. Run 'npx castdom build' to generate.\");\n}\n\nexport default manifest;\n`;\n }\n return null;\n },\n\n handleHotUpdate(ctx) {\n // Hot-reload when skeleton data changes\n if (ctx.file.includes(outDir)) {\n ctx.server.ws.send({\n type: \"custom\",\n event: \"castdom:update\",\n data: { file: ctx.file },\n });\n }\n },\n };\n}\n\n/**\n * Vite plugin for extracting skeletons during build.\n * Runs `castdom build` as part of the Vite build process.\n */\nexport function castdomExtract(options: CastDOMViteOptions = {}): VitePlugin {\n return {\n name: \"castdom-extract\",\n enforce: \"pre\",\n\n async buildStart() {\n // Only extract during build, not serve\n // The actual extraction is done via the CLI\n console.log(\"CastDOM: Ensure skeletons are up to date with 'npx castdom build'\");\n },\n };\n}\n\nexport default castdom;\n"]}
|