sculpted 0.0.0 → 0.1.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 +105 -0
- package/README.md +233 -0
- package/dist/index.d.mts +129 -0
- package/dist/index.mjs +3 -0
- package/dist/patcher-BAw2kF1Q.mjs +2594 -0
- package/dist/protocol-BJm-xGHP.mjs +54 -0
- package/dist/runtime-DwE3PVhB.d.mts +64 -0
- package/dist/runtime.d.mts +2 -0
- package/dist/runtime.mjs +613 -0
- package/dist/sourceSyntax-DanNzS7Y.d.mts +103 -0
- package/dist/types-CdByW0ji.d.mts +381 -0
- package/dist/ui.d.mts +54 -0
- package/dist/ui.mjs +11125 -0
- package/dist/vite.d.mts +85 -0
- package/dist/vite.mjs +2325 -0
- package/examples/manual-vite-preact-pandacss/README.md +75 -0
- package/examples/manual-vite-preact-pandacss/index.html +12 -0
- package/examples/manual-vite-preact-pandacss/package.json +23 -0
- package/examples/manual-vite-preact-pandacss/panda.config.ts +43 -0
- package/examples/manual-vite-preact-pandacss/pnpm-lock.yaml +3359 -0
- package/examples/manual-vite-preact-pandacss/pnpm-workspace.yaml +2 -0
- package/examples/manual-vite-preact-pandacss/postcss.config.cjs +5 -0
- package/examples/manual-vite-preact-pandacss/src/TsrxManualPanel.tsrx +47 -0
- package/examples/manual-vite-preact-pandacss/src/index.css +8 -0
- package/examples/manual-vite-preact-pandacss/src/main.style.ts +33 -0
- package/examples/manual-vite-preact-pandacss/src/main.tsx +484 -0
- package/examples/manual-vite-preact-pandacss/src/tsrx.d.ts +5 -0
- package/examples/manual-vite-preact-pandacss/tsconfig.json +21 -0
- package/examples/manual-vite-preact-pandacss/vite.config.ts +20 -0
- package/package.json +66 -8
- package/readme.md +0 -1
package/dist/vite.mjs
ADDED
|
@@ -0,0 +1,2325 @@
|
|
|
1
|
+
import { _ as markerClassForEditId, c as DEFAULT_OPEN_SOURCE_ENDPOINT, d as DEFAULT_TOKEN_WRITEBACK_ENDPOINT, f as DEFAULT_WRITEBACK_ENDPOINT, p as PANDA_INSPECTOR_EVENTS, u as DEFAULT_STYLE_MODULE_ENDPOINT } from "./protocol-BJm-xGHP.mjs";
|
|
2
|
+
import { _ as hashSource, a as createStyleModuleSourcePatch, c as safeProjectSourcePath, d as trustedManifestFilePath, f as trustedTokenSourceFilePath, g as analyzePandaCssSource, h as createInlineCssSourcePatch, i as createStyleModuleDetachPatch, l as stripViteQuery, m as createStaticCssPatch, n as componentStyleModulePaths, o as readComponentStyleModule, p as createStaticCssBatchPatch, r as createStyleModuleAttachPatch, s as normalizePath$1, t as createTokenConfigPatch, u as toRelativeProjectPath$1, x as resolveSourceParserAdapter, y as parsePandaSource } from "./patcher-BAw2kF1Q.mjs";
|
|
3
|
+
import ts from "typescript";
|
|
4
|
+
import { dirname } from "node:path";
|
|
5
|
+
import { access, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
6
|
+
import { loadConfigAndCreateContext } from "@pandacss/node";
|
|
7
|
+
//#region src/vite/constants.ts
|
|
8
|
+
const DEFAULT_EXCLUDE = ["node_modules/**", "styled-system/**"];
|
|
9
|
+
const DEFAULT_RUNTIME_BOOTSTRAP_ENDPOINT = "/@panda-inspector/runtime";
|
|
10
|
+
const DEFAULT_RUNTIME_MODULE_ENDPOINT = "/@panda-inspector/runtime-module";
|
|
11
|
+
const DEFAULT_UI_MODULE_ENDPOINT = "/@panda-inspector/ui-module";
|
|
12
|
+
const DEFAULT_RUNTIME_CHUNK_ENDPOINT = "/@panda-inspector/runtime-chunks/";
|
|
13
|
+
const DEFAULT_RUNTIME_MODULE_SOURCE_MAP_ENDPOINT = `${DEFAULT_RUNTIME_MODULE_ENDPOINT}.map`;
|
|
14
|
+
const DEFAULT_UI_MODULE_SOURCE_MAP_ENDPOINT = `${DEFAULT_UI_MODULE_ENDPOINT}.map`;
|
|
15
|
+
const DEFAULT_PANDA_CONFIG_FILES = [
|
|
16
|
+
"panda.config.ts",
|
|
17
|
+
"panda.config.mts",
|
|
18
|
+
"panda.config.js",
|
|
19
|
+
"panda.config.mjs",
|
|
20
|
+
"panda.config.cjs"
|
|
21
|
+
];
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/vite/editorProperties.ts
|
|
24
|
+
function editorProperty(name, label, category, cssProperty, aliases = [], tokenCategory) {
|
|
25
|
+
return {
|
|
26
|
+
name,
|
|
27
|
+
label,
|
|
28
|
+
category,
|
|
29
|
+
cssProperty,
|
|
30
|
+
aliases,
|
|
31
|
+
tokenCategory,
|
|
32
|
+
defaultUnit: defaultEditorPropertyUnit(name, category)
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function defaultEditorPropertyUnit(name, category) {
|
|
36
|
+
if ([
|
|
37
|
+
"zIndex",
|
|
38
|
+
"opacity",
|
|
39
|
+
"fontWeight",
|
|
40
|
+
"lineHeight",
|
|
41
|
+
"aspectRatio",
|
|
42
|
+
"order"
|
|
43
|
+
].includes(name)) return "";
|
|
44
|
+
if (name === "transitionDuration") return "ms";
|
|
45
|
+
if (category === "spacing" || category === "sizing" || [
|
|
46
|
+
"inset",
|
|
47
|
+
"top",
|
|
48
|
+
"right",
|
|
49
|
+
"bottom",
|
|
50
|
+
"left",
|
|
51
|
+
"fontSize",
|
|
52
|
+
"letterSpacing",
|
|
53
|
+
"flexBasis",
|
|
54
|
+
"borderWidth",
|
|
55
|
+
"borderRadius",
|
|
56
|
+
"borderTopRadius",
|
|
57
|
+
"borderRightRadius",
|
|
58
|
+
"borderBottomRadius",
|
|
59
|
+
"borderLeftRadius",
|
|
60
|
+
"borderTopWidth",
|
|
61
|
+
"borderRightWidth",
|
|
62
|
+
"borderBottomWidth",
|
|
63
|
+
"borderLeftWidth",
|
|
64
|
+
"outlineWidth",
|
|
65
|
+
"outlineOffset"
|
|
66
|
+
].includes(name)) return "px";
|
|
67
|
+
}
|
|
68
|
+
const DEFAULT_EDITOR_PROPERTIES = [
|
|
69
|
+
editorProperty("display", "Display", "layout", "display"),
|
|
70
|
+
editorProperty("position", "Position", "layout", "position", ["pos"]),
|
|
71
|
+
editorProperty("overflow", "Overflow", "layout", "overflow"),
|
|
72
|
+
editorProperty("overflowX", "Overflow X", "layout", "overflow-x"),
|
|
73
|
+
editorProperty("overflowY", "Overflow Y", "layout", "overflow-y"),
|
|
74
|
+
editorProperty("visibility", "Visibility", "layout", "visibility"),
|
|
75
|
+
editorProperty("boxSizing", "Box sizing", "layout", "box-sizing"),
|
|
76
|
+
editorProperty("zIndex", "Z index", "layout", "z-index", [], "zIndex"),
|
|
77
|
+
editorProperty("inset", "Inset", "layout", "inset", [], "spacing"),
|
|
78
|
+
editorProperty("top", "Top", "layout", "top", [], "spacing"),
|
|
79
|
+
editorProperty("right", "Right", "layout", "right", [], "spacing"),
|
|
80
|
+
editorProperty("bottom", "Bottom", "layout", "bottom", [], "spacing"),
|
|
81
|
+
editorProperty("left", "Left", "layout", "left", [], "spacing"),
|
|
82
|
+
editorProperty("padding", "Padding", "spacing", "padding", ["p"], "spacing"),
|
|
83
|
+
editorProperty("paddingX", "Padding X", "spacing", "padding-inline", ["px"], "spacing"),
|
|
84
|
+
editorProperty("paddingY", "Padding Y", "spacing", "padding-block", ["py"], "spacing"),
|
|
85
|
+
editorProperty("paddingTop", "Padding top", "spacing", "padding-top", ["pt"], "spacing"),
|
|
86
|
+
editorProperty("paddingRight", "Padding right", "spacing", "padding-right", ["pr"], "spacing"),
|
|
87
|
+
editorProperty("paddingBottom", "Padding bottom", "spacing", "padding-bottom", ["pb"], "spacing"),
|
|
88
|
+
editorProperty("paddingLeft", "Padding left", "spacing", "padding-left", ["pl"], "spacing"),
|
|
89
|
+
editorProperty("margin", "Margin", "spacing", "margin", ["m"], "spacing"),
|
|
90
|
+
editorProperty("marginX", "Margin X", "spacing", "margin-inline", ["mx"], "spacing"),
|
|
91
|
+
editorProperty("marginY", "Margin Y", "spacing", "margin-block", ["my"], "spacing"),
|
|
92
|
+
editorProperty("marginTop", "Margin top", "spacing", "margin-top", ["mt"], "spacing"),
|
|
93
|
+
editorProperty("marginRight", "Margin right", "spacing", "margin-right", ["mr"], "spacing"),
|
|
94
|
+
editorProperty("marginBottom", "Margin bottom", "spacing", "margin-bottom", ["mb"], "spacing"),
|
|
95
|
+
editorProperty("marginLeft", "Margin left", "spacing", "margin-left", ["ml"], "spacing"),
|
|
96
|
+
editorProperty("gap", "Gap", "spacing", "gap", [], "spacing"),
|
|
97
|
+
editorProperty("rowGap", "Row gap", "spacing", "row-gap", [], "spacing"),
|
|
98
|
+
editorProperty("columnGap", "Column gap", "spacing", "column-gap", [], "spacing"),
|
|
99
|
+
editorProperty("width", "Width", "sizing", "width", ["w"], "sizes"),
|
|
100
|
+
editorProperty("height", "Height", "sizing", "height", ["h"], "sizes"),
|
|
101
|
+
editorProperty("minWidth", "Min width", "sizing", "min-width", ["minW"], "sizes"),
|
|
102
|
+
editorProperty("maxWidth", "Max width", "sizing", "max-width", ["maxW"], "sizes"),
|
|
103
|
+
editorProperty("minHeight", "Min height", "sizing", "min-height", ["minH"], "sizes"),
|
|
104
|
+
editorProperty("maxHeight", "Max height", "sizing", "max-height", ["maxH"], "sizes"),
|
|
105
|
+
editorProperty("aspectRatio", "Aspect ratio", "sizing", "aspect-ratio"),
|
|
106
|
+
editorProperty("fontFamily", "Font family", "typography", "font-family", [], "fonts"),
|
|
107
|
+
editorProperty("fontSize", "Font size", "typography", "font-size", [], "fontSizes"),
|
|
108
|
+
editorProperty("fontWeight", "Font weight", "typography", "font-weight", [], "fontWeights"),
|
|
109
|
+
editorProperty("lineHeight", "Line height", "typography", "line-height", [], "lineHeights"),
|
|
110
|
+
editorProperty("letterSpacing", "Letter spacing", "typography", "letter-spacing", [], "letterSpacings"),
|
|
111
|
+
editorProperty("textAlign", "Text align", "typography", "text-align"),
|
|
112
|
+
editorProperty("textDecoration", "Text decoration", "typography", "text-decoration"),
|
|
113
|
+
editorProperty("textTransform", "Text transform", "typography", "text-transform"),
|
|
114
|
+
editorProperty("whiteSpace", "White space", "typography", "white-space"),
|
|
115
|
+
editorProperty("wordBreak", "Word break", "typography", "word-break"),
|
|
116
|
+
editorProperty("overflowWrap", "Overflow wrap", "typography", "overflow-wrap"),
|
|
117
|
+
editorProperty("textOverflow", "Text overflow", "typography", "text-overflow"),
|
|
118
|
+
editorProperty("color", "Color", "color", "color", [], "colors"),
|
|
119
|
+
editorProperty("background", "Background", "color", "background", ["bg"], "colors"),
|
|
120
|
+
editorProperty("backgroundColor", "Background color", "color", "background-color", ["bgColor"], "colors"),
|
|
121
|
+
editorProperty("borderColor", "Border color", "color", "border-color", [
|
|
122
|
+
"borderTopColor",
|
|
123
|
+
"borderRightColor",
|
|
124
|
+
"borderBottomColor",
|
|
125
|
+
"borderLeftColor",
|
|
126
|
+
"borderXColor",
|
|
127
|
+
"borderYColor"
|
|
128
|
+
], "colors"),
|
|
129
|
+
editorProperty("outlineColor", "Outline color", "color", "outline-color", [], "colors"),
|
|
130
|
+
editorProperty("fill", "Fill", "color", "fill", [], "colors"),
|
|
131
|
+
editorProperty("stroke", "Stroke", "color", "stroke", [], "colors"),
|
|
132
|
+
editorProperty("caretColor", "Caret color", "color", "caret-color", [], "colors"),
|
|
133
|
+
editorProperty("accentColor", "Accent color", "color", "accent-color", [], "colors"),
|
|
134
|
+
editorProperty("flex", "Flex", "layout", "flex"),
|
|
135
|
+
editorProperty("flexBasis", "Flex basis", "layout", "flex-basis", [], "sizes"),
|
|
136
|
+
editorProperty("flexDirection", "Flex direction", "layout", "flex-direction"),
|
|
137
|
+
editorProperty("flexWrap", "Flex wrap", "layout", "flex-wrap"),
|
|
138
|
+
editorProperty("alignItems", "Align items", "layout", "align-items"),
|
|
139
|
+
editorProperty("alignContent", "Align content", "layout", "align-content"),
|
|
140
|
+
editorProperty("alignSelf", "Align self", "layout", "align-self"),
|
|
141
|
+
editorProperty("justifyContent", "Justify content", "layout", "justify-content"),
|
|
142
|
+
editorProperty("justifyItems", "Justify items", "layout", "justify-items"),
|
|
143
|
+
editorProperty("justifySelf", "Justify self", "layout", "justify-self"),
|
|
144
|
+
editorProperty("order", "Order", "layout", "order"),
|
|
145
|
+
editorProperty("gridTemplateColumns", "Grid template columns", "layout", "grid-template-columns"),
|
|
146
|
+
editorProperty("gridTemplateRows", "Grid template rows", "layout", "grid-template-rows"),
|
|
147
|
+
editorProperty("gridColumn", "Grid column", "layout", "grid-column"),
|
|
148
|
+
editorProperty("gridRow", "Grid row", "layout", "grid-row"),
|
|
149
|
+
editorProperty("gridAutoFlow", "Grid auto flow", "layout", "grid-auto-flow"),
|
|
150
|
+
editorProperty("gridAutoColumns", "Grid auto columns", "layout", "grid-auto-columns"),
|
|
151
|
+
editorProperty("gridAutoRows", "Grid auto rows", "layout", "grid-auto-rows"),
|
|
152
|
+
editorProperty("border", "Border", "border", "border"),
|
|
153
|
+
editorProperty("borderWidth", "Border width", "border", "border-width", [], "borderWidths"),
|
|
154
|
+
editorProperty("borderStyle", "Border style", "border", "border-style"),
|
|
155
|
+
editorProperty("borderRadius", "Border radius", "border", "border-radius", ["rounded"], "radii"),
|
|
156
|
+
editorProperty("cornerShape", "Corner shape", "border", "corner-shape"),
|
|
157
|
+
editorProperty("borderTopRadius", "Rounded top", "border", "border-start-start-radius", ["roundedTop"], "radii"),
|
|
158
|
+
editorProperty("borderRightRadius", "Rounded right", "border", "border-start-end-radius", ["roundedRight"], "radii"),
|
|
159
|
+
editorProperty("borderBottomRadius", "Rounded bottom", "border", "border-end-end-radius", ["roundedBottom"], "radii"),
|
|
160
|
+
editorProperty("borderLeftRadius", "Rounded left", "border", "border-end-start-radius", ["roundedLeft"], "radii"),
|
|
161
|
+
editorProperty("borderTopWidth", "Border top width", "border", "border-top-width", [], "borderWidths"),
|
|
162
|
+
editorProperty("borderRightWidth", "Border right width", "border", "border-right-width", [], "borderWidths"),
|
|
163
|
+
editorProperty("borderBottomWidth", "Border bottom width", "border", "border-bottom-width", [], "borderWidths"),
|
|
164
|
+
editorProperty("borderLeftWidth", "Border left width", "border", "border-left-width", [], "borderWidths"),
|
|
165
|
+
editorProperty("backgroundImage", "Background image", "other", "background-image", ["bgImage"]),
|
|
166
|
+
editorProperty("backgroundSize", "Background size", "other", "background-size", ["bgSize"]),
|
|
167
|
+
editorProperty("backgroundPosition", "Background position", "other", "background-position", ["bgPosition"]),
|
|
168
|
+
editorProperty("backgroundRepeat", "Background repeat", "other", "background-repeat", ["bgRepeat"]),
|
|
169
|
+
editorProperty("backgroundAttachment", "Background attachment", "other", "background-attachment", ["bgAttachment"]),
|
|
170
|
+
editorProperty("backgroundClip", "Background clip", "other", "background-clip", ["bgClip"]),
|
|
171
|
+
editorProperty("opacity", "Opacity", "effects", "opacity", [], "opacity"),
|
|
172
|
+
editorProperty("boxShadow", "Box shadow", "effects", "box-shadow", [], "shadows"),
|
|
173
|
+
editorProperty("outline", "Outline", "effects", "outline"),
|
|
174
|
+
editorProperty("outlineWidth", "Outline width", "effects", "outline-width"),
|
|
175
|
+
editorProperty("outlineStyle", "Outline style", "effects", "outline-style"),
|
|
176
|
+
editorProperty("outlineOffset", "Outline offset", "effects", "outline-offset"),
|
|
177
|
+
editorProperty("transform", "Transform", "effects", "transform"),
|
|
178
|
+
editorProperty("filter", "Filter", "effects", "filter"),
|
|
179
|
+
editorProperty("backdropFilter", "Backdrop filter", "effects", "backdrop-filter"),
|
|
180
|
+
editorProperty("mixBlendMode", "Mix blend mode", "effects", "mix-blend-mode"),
|
|
181
|
+
editorProperty("cursor", "Cursor", "other", "cursor"),
|
|
182
|
+
editorProperty("pointerEvents", "Pointer events", "other", "pointer-events"),
|
|
183
|
+
editorProperty("userSelect", "User select", "other", "user-select"),
|
|
184
|
+
editorProperty("resize", "Resize", "other", "resize"),
|
|
185
|
+
editorProperty("scrollBehavior", "Scroll behavior", "other", "scroll-behavior"),
|
|
186
|
+
editorProperty("transition", "Transition", "other", "transition"),
|
|
187
|
+
editorProperty("transitionProperty", "Transition property", "other", "transition-property"),
|
|
188
|
+
editorProperty("transitionDuration", "Transition duration", "other", "transition-duration"),
|
|
189
|
+
editorProperty("transitionTimingFunction", "Transition timing function", "other", "transition-timing-function")
|
|
190
|
+
];
|
|
191
|
+
//#endregion
|
|
192
|
+
//#region src/vite/editorMetadata.ts
|
|
193
|
+
async function createEditorMetadata(options) {
|
|
194
|
+
const config = await readPandaConfigSource(options.projectRoot, options.pandaConfigPath);
|
|
195
|
+
const properties = {
|
|
196
|
+
status: "available",
|
|
197
|
+
items: DEFAULT_EDITOR_PROPERTIES
|
|
198
|
+
};
|
|
199
|
+
if (!config.ok) {
|
|
200
|
+
const unavailable = unavailableMetadataSection(config.reason, config.message);
|
|
201
|
+
const unavailableFontTokens = unavailableMetadataSection(config.reason, config.message);
|
|
202
|
+
const unavailableSources = unavailableMetadataSection(config.reason, config.message);
|
|
203
|
+
return {
|
|
204
|
+
version: 1,
|
|
205
|
+
projectRoot: options.projectRoot,
|
|
206
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
207
|
+
tokenSources: unavailableSources,
|
|
208
|
+
colorTokens: unavailable,
|
|
209
|
+
semanticColorTokens: unavailable,
|
|
210
|
+
fontTokens: unavailableFontTokens,
|
|
211
|
+
properties
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
const parsed = parsePandaConfigEditorMetadata({
|
|
215
|
+
projectRoot: options.projectRoot,
|
|
216
|
+
filePath: config.filePath,
|
|
217
|
+
sourceText: config.sourceText
|
|
218
|
+
});
|
|
219
|
+
const resolved = await resolvePandaConfigEditorMetadata({
|
|
220
|
+
projectRoot: options.projectRoot,
|
|
221
|
+
pandaConfigPath: options.pandaConfigPath
|
|
222
|
+
});
|
|
223
|
+
if (!parsed.ok) {
|
|
224
|
+
const unavailable = unavailableMetadataSection(parsed.reason, parsed.message);
|
|
225
|
+
if (resolved.ok) return {
|
|
226
|
+
version: 1,
|
|
227
|
+
projectRoot: options.projectRoot,
|
|
228
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
229
|
+
tokenSources: {
|
|
230
|
+
status: "available",
|
|
231
|
+
items: parsed.tokenSources
|
|
232
|
+
},
|
|
233
|
+
colorTokens: {
|
|
234
|
+
status: "available",
|
|
235
|
+
items: resolved.colorTokens
|
|
236
|
+
},
|
|
237
|
+
semanticColorTokens: {
|
|
238
|
+
status: "available",
|
|
239
|
+
items: resolved.semanticColorTokens
|
|
240
|
+
},
|
|
241
|
+
fontTokens: {
|
|
242
|
+
status: "available",
|
|
243
|
+
items: resolved.fontTokens
|
|
244
|
+
},
|
|
245
|
+
properties
|
|
246
|
+
};
|
|
247
|
+
return {
|
|
248
|
+
version: 1,
|
|
249
|
+
projectRoot: options.projectRoot,
|
|
250
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
251
|
+
tokenSources: {
|
|
252
|
+
status: "available",
|
|
253
|
+
items: parsed.tokenSources
|
|
254
|
+
},
|
|
255
|
+
colorTokens: unavailable,
|
|
256
|
+
semanticColorTokens: unavailable,
|
|
257
|
+
fontTokens: unavailableMetadataSection(parsed.reason, parsed.message),
|
|
258
|
+
properties
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
return {
|
|
262
|
+
version: 1,
|
|
263
|
+
projectRoot: options.projectRoot,
|
|
264
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
265
|
+
tokenSources: {
|
|
266
|
+
status: "available",
|
|
267
|
+
items: parsed.tokenSources
|
|
268
|
+
},
|
|
269
|
+
colorTokens: {
|
|
270
|
+
status: "available",
|
|
271
|
+
items: mergeResolvedAndStaticColorTokens(resolved.ok ? resolved.colorTokens : [], parsed.colorTokens)
|
|
272
|
+
},
|
|
273
|
+
semanticColorTokens: {
|
|
274
|
+
status: "available",
|
|
275
|
+
items: mergeResolvedAndStaticColorTokens(resolved.ok ? resolved.semanticColorTokens : [], parsed.semanticColorTokens)
|
|
276
|
+
},
|
|
277
|
+
fontTokens: {
|
|
278
|
+
status: "available",
|
|
279
|
+
items: mergeResolvedAndStaticFontTokens(resolved.ok ? resolved.fontTokens : [], parsed.fontTokens)
|
|
280
|
+
},
|
|
281
|
+
properties
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
async function readPandaConfigSource(projectRoot, pandaConfigPath) {
|
|
285
|
+
const root = normalizePath(projectRoot).replace(/\/$/, "");
|
|
286
|
+
const candidates = pandaConfigPath ? [absoluteProjectPath(root, pandaConfigPath)] : DEFAULT_PANDA_CONFIG_FILES.map((fileName) => `${root}/${fileName}`);
|
|
287
|
+
for (const filePath of candidates) try {
|
|
288
|
+
return {
|
|
289
|
+
ok: true,
|
|
290
|
+
filePath,
|
|
291
|
+
sourceText: await readFile(filePath, "utf8")
|
|
292
|
+
};
|
|
293
|
+
} catch (error) {
|
|
294
|
+
if (isMissingFileError$2(error)) continue;
|
|
295
|
+
return {
|
|
296
|
+
ok: false,
|
|
297
|
+
reason: "panda-config-unreadable",
|
|
298
|
+
message: `Failed to read Panda config ${filePath}: ${errorMessage(error)}`
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
return {
|
|
302
|
+
ok: false,
|
|
303
|
+
reason: "panda-config-missing",
|
|
304
|
+
message: pandaConfigPath ? `Panda config was not found at ${candidates[0]}.` : `No Panda config was found in ${root}.`
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
function parsePandaConfigEditorMetadata(options) {
|
|
308
|
+
const configObject = findPandaConfigObject(ts.createSourceFile(options.filePath, options.sourceText, ts.ScriptTarget.Latest, true));
|
|
309
|
+
if (!configObject) return {
|
|
310
|
+
ok: false,
|
|
311
|
+
reason: "unsupported-panda-config",
|
|
312
|
+
message: "Panda config metadata can only be read from a static object or defineConfig({ ... }) call.",
|
|
313
|
+
tokenSources: []
|
|
314
|
+
};
|
|
315
|
+
const theme = objectProperty(configObject, "theme");
|
|
316
|
+
const themeObject = theme ? objectLiteralExpression(theme) : void 0;
|
|
317
|
+
if (!themeObject) return {
|
|
318
|
+
ok: true,
|
|
319
|
+
tokenSources: [],
|
|
320
|
+
colorTokens: [],
|
|
321
|
+
semanticColorTokens: [],
|
|
322
|
+
fontTokens: []
|
|
323
|
+
};
|
|
324
|
+
const colorMetadata = collectThemeColorTokenMetadata({
|
|
325
|
+
projectRoot: options.projectRoot,
|
|
326
|
+
filePath: options.filePath,
|
|
327
|
+
sourceText: options.sourceText,
|
|
328
|
+
themeObject,
|
|
329
|
+
section: "tokens",
|
|
330
|
+
kind: "token"
|
|
331
|
+
});
|
|
332
|
+
const semanticColorMetadata = collectThemeColorTokenMetadata({
|
|
333
|
+
projectRoot: options.projectRoot,
|
|
334
|
+
filePath: options.filePath,
|
|
335
|
+
sourceText: options.sourceText,
|
|
336
|
+
themeObject,
|
|
337
|
+
section: "semanticTokens",
|
|
338
|
+
kind: "semantic-token"
|
|
339
|
+
});
|
|
340
|
+
const fontTokens = collectThemeFontTokenMetadata(themeObject);
|
|
341
|
+
return {
|
|
342
|
+
ok: true,
|
|
343
|
+
tokenSources: [...colorMetadata.tokenSources, ...semanticColorMetadata.tokenSources],
|
|
344
|
+
colorTokens: colorMetadata.tokens,
|
|
345
|
+
semanticColorTokens: semanticColorMetadata.tokens,
|
|
346
|
+
fontTokens
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
function collectThemeColorTokenMetadata(options) {
|
|
350
|
+
const directExpression = colorTokenExpressionForThemeSection(options.themeObject, options.section);
|
|
351
|
+
const direct = objectLiteralExpression(directExpression);
|
|
352
|
+
const extend = objectProperty(options.themeObject, "extend");
|
|
353
|
+
const extendedExpression = extend ? colorTokenExpressionForThemeSection(objectLiteralExpression(extend), options.section) : void 0;
|
|
354
|
+
const extended = objectLiteralExpression(extendedExpression);
|
|
355
|
+
const tokenSources = [];
|
|
356
|
+
const tokens = [];
|
|
357
|
+
if (direct) {
|
|
358
|
+
const sourceTarget = editorTokenSourceTarget({
|
|
359
|
+
projectRoot: options.projectRoot,
|
|
360
|
+
filePath: options.filePath,
|
|
361
|
+
sourceText: options.sourceText,
|
|
362
|
+
object: direct,
|
|
363
|
+
section: tokenSourceSection(options.section),
|
|
364
|
+
extended: false
|
|
365
|
+
});
|
|
366
|
+
tokenSources.push(sourceTarget);
|
|
367
|
+
tokens.push(...collectColorTokenMetadata(direct, {
|
|
368
|
+
kind: options.kind,
|
|
369
|
+
sourceTargetId: sourceTarget.id,
|
|
370
|
+
writable: sourceTarget.writable
|
|
371
|
+
}));
|
|
372
|
+
} else if (directExpression) tokenSources.push(editorReadOnlyTokenSourceTarget({
|
|
373
|
+
projectRoot: options.projectRoot,
|
|
374
|
+
filePath: options.filePath,
|
|
375
|
+
sourceText: options.sourceText,
|
|
376
|
+
node: directExpression,
|
|
377
|
+
section: tokenSourceSection(options.section),
|
|
378
|
+
extended: false,
|
|
379
|
+
reason: "Token colors source is not a static object literal."
|
|
380
|
+
}));
|
|
381
|
+
if (extended) {
|
|
382
|
+
const sourceTarget = editorTokenSourceTarget({
|
|
383
|
+
projectRoot: options.projectRoot,
|
|
384
|
+
filePath: options.filePath,
|
|
385
|
+
sourceText: options.sourceText,
|
|
386
|
+
object: extended,
|
|
387
|
+
section: tokenSourceSection(options.section),
|
|
388
|
+
extended: true
|
|
389
|
+
});
|
|
390
|
+
tokenSources.push(sourceTarget);
|
|
391
|
+
tokens.push(...collectColorTokenMetadata(extended, {
|
|
392
|
+
kind: options.kind,
|
|
393
|
+
sourceTargetId: sourceTarget.id,
|
|
394
|
+
writable: sourceTarget.writable
|
|
395
|
+
}));
|
|
396
|
+
} else if (extendedExpression) tokenSources.push(editorReadOnlyTokenSourceTarget({
|
|
397
|
+
projectRoot: options.projectRoot,
|
|
398
|
+
filePath: options.filePath,
|
|
399
|
+
sourceText: options.sourceText,
|
|
400
|
+
node: extendedExpression,
|
|
401
|
+
section: tokenSourceSection(options.section),
|
|
402
|
+
extended: true,
|
|
403
|
+
reason: "Extended token colors source is not a static object literal."
|
|
404
|
+
}));
|
|
405
|
+
return {
|
|
406
|
+
tokenSources,
|
|
407
|
+
tokens
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
function colorTokenExpressionForThemeSection(themeObject, section) {
|
|
411
|
+
if (!themeObject) return void 0;
|
|
412
|
+
const tokenSection = objectProperty(themeObject, section);
|
|
413
|
+
const tokenSectionObject = tokenSection ? objectLiteralExpression(tokenSection) : void 0;
|
|
414
|
+
return tokenSectionObject ? objectProperty(tokenSectionObject, "colors") : void 0;
|
|
415
|
+
}
|
|
416
|
+
function tokenSourceSection(section) {
|
|
417
|
+
return section === "tokens" ? "tokens.colors" : "semanticTokens.colors";
|
|
418
|
+
}
|
|
419
|
+
function collectThemeFontTokenMetadata(themeObject) {
|
|
420
|
+
const tokens = [];
|
|
421
|
+
for (const expression of [fontTokenExpressionForThemeSection(themeObject), fontTokenExpressionForThemeSection(objectLiteralExpression(objectProperty(themeObject, "extend")))]) {
|
|
422
|
+
const object = objectLiteralExpression(expression);
|
|
423
|
+
if (!object) continue;
|
|
424
|
+
tokens.push(...collectFontTokenMetadata(object));
|
|
425
|
+
}
|
|
426
|
+
return tokens;
|
|
427
|
+
}
|
|
428
|
+
function fontTokenExpressionForThemeSection(themeObject) {
|
|
429
|
+
if (!themeObject) return void 0;
|
|
430
|
+
const tokens = objectLiteralExpression(objectProperty(themeObject, "tokens"));
|
|
431
|
+
return tokens ? objectProperty(tokens, "fonts") : void 0;
|
|
432
|
+
}
|
|
433
|
+
async function resolvePandaConfigEditorMetadata(options) {
|
|
434
|
+
try {
|
|
435
|
+
const context = await loadConfigAndCreateContext({
|
|
436
|
+
cwd: options.projectRoot,
|
|
437
|
+
configPath: options.pandaConfigPath ? absoluteProjectPath(options.projectRoot, options.pandaConfigPath) : void 0
|
|
438
|
+
});
|
|
439
|
+
const presetColorTokenOwners = presetColorTokenOwnersByKind(context.config.presets);
|
|
440
|
+
return {
|
|
441
|
+
ok: true,
|
|
442
|
+
colorTokens: resolvedTokenSpecColorMetadata(context.getSpecOfType("tokens"), "token", presetColorTokenOwners.token),
|
|
443
|
+
semanticColorTokens: resolvedTokenSpecColorMetadata(context.getSpecOfType("semantic-tokens"), "semantic-token", presetColorTokenOwners.semanticToken),
|
|
444
|
+
fontTokens: resolvedTokenSpecFontMetadata(context.getSpecOfType("tokens"), presetFontTokenOwners(context.config.presets))
|
|
445
|
+
};
|
|
446
|
+
} catch (error) {
|
|
447
|
+
return {
|
|
448
|
+
ok: false,
|
|
449
|
+
message: `Failed to resolve Panda token metadata: ${errorMessage(error)}`
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
function resolvedTokenSpecFontMetadata(spec, presetOwners) {
|
|
454
|
+
if (!isRecord$3(spec) || !Array.isArray(spec.data)) return [];
|
|
455
|
+
const fontGroup = spec.data.find((group) => isRecord$3(group) && group.type === "fonts" && Array.isArray(group.values));
|
|
456
|
+
if (!fontGroup) return [];
|
|
457
|
+
return fontGroup.values.map((value) => resolvedFontTokenMetadata(value, presetOwners)).filter((value) => value !== void 0);
|
|
458
|
+
}
|
|
459
|
+
function resolvedFontTokenMetadata(value, presetOwners) {
|
|
460
|
+
if (!isRecord$3(value) || typeof value.name !== "string" || value.name.length === 0) return;
|
|
461
|
+
return {
|
|
462
|
+
kind: "token",
|
|
463
|
+
category: "fonts",
|
|
464
|
+
path: value.name,
|
|
465
|
+
label: value.name,
|
|
466
|
+
value: jsonValueFromUnknown(value.value),
|
|
467
|
+
cssVariable: typeof value.cssVar === "string" ? value.cssVar : void 0,
|
|
468
|
+
presetName: presetOwners.get(value.name)
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
function resolvedTokenSpecColorMetadata(spec, kind, presetOwners) {
|
|
472
|
+
if (!isRecord$3(spec) || !Array.isArray(spec.data)) return [];
|
|
473
|
+
const colorGroup = spec.data.find((group) => isRecord$3(group) && group.type === "colors" && Array.isArray(group.values));
|
|
474
|
+
if (!colorGroup) return [];
|
|
475
|
+
return colorGroup.values.map((value) => resolvedColorTokenMetadata(value, kind, presetOwners)).filter((value) => value !== void 0);
|
|
476
|
+
}
|
|
477
|
+
function resolvedColorTokenMetadata(value, kind, presetOwners) {
|
|
478
|
+
if (!isRecord$3(value) || typeof value.name !== "string" || value.name.length === 0) return;
|
|
479
|
+
if (kind === "semantic-token") {
|
|
480
|
+
const conditions = Array.isArray(value.values) ? value.values.flatMap((condition) => {
|
|
481
|
+
if (!isRecord$3(condition) || typeof condition.condition !== "string") return [];
|
|
482
|
+
const conditionValue = jsonValueFromUnknown(condition.value);
|
|
483
|
+
if (conditionValue === void 0) return [];
|
|
484
|
+
const swatch = swatchFromJsonValue(conditionValue);
|
|
485
|
+
return [swatch ? {
|
|
486
|
+
condition: condition.condition,
|
|
487
|
+
value: conditionValue,
|
|
488
|
+
swatch
|
|
489
|
+
} : {
|
|
490
|
+
condition: condition.condition,
|
|
491
|
+
value: conditionValue
|
|
492
|
+
}];
|
|
493
|
+
}) : void 0;
|
|
494
|
+
return {
|
|
495
|
+
kind,
|
|
496
|
+
category: "colors",
|
|
497
|
+
path: value.name,
|
|
498
|
+
label: value.name,
|
|
499
|
+
cssVariable: typeof value.cssVar === "string" ? value.cssVar : void 0,
|
|
500
|
+
presetName: presetOwners.get(value.name),
|
|
501
|
+
conditions,
|
|
502
|
+
writable: false,
|
|
503
|
+
readonlyReason: "Resolved Panda token metadata is read-only."
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
const tokenValue = jsonValueFromUnknown(value.value);
|
|
507
|
+
if (tokenValue === void 0) return void 0;
|
|
508
|
+
return {
|
|
509
|
+
kind,
|
|
510
|
+
category: "colors",
|
|
511
|
+
path: value.name,
|
|
512
|
+
label: value.name,
|
|
513
|
+
value: tokenValue,
|
|
514
|
+
swatch: swatchFromJsonValue(tokenValue),
|
|
515
|
+
cssVariable: typeof value.cssVar === "string" ? value.cssVar : void 0,
|
|
516
|
+
presetName: presetOwners.get(value.name),
|
|
517
|
+
writable: false,
|
|
518
|
+
readonlyReason: "Resolved Panda token metadata is read-only."
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
function presetColorTokenOwnersByKind(presets) {
|
|
522
|
+
const token = /* @__PURE__ */ new Map();
|
|
523
|
+
const semanticToken = /* @__PURE__ */ new Map();
|
|
524
|
+
if (!Array.isArray(presets)) return {
|
|
525
|
+
token,
|
|
526
|
+
semanticToken
|
|
527
|
+
};
|
|
528
|
+
for (const preset of presets) {
|
|
529
|
+
if (!isRecord$3(preset) || typeof preset.name !== "string") continue;
|
|
530
|
+
const theme = isRecord$3(preset.theme) ? preset.theme : void 0;
|
|
531
|
+
const tokens = isRecord$3(theme?.tokens) ? theme.tokens : void 0;
|
|
532
|
+
const semanticTokens = isRecord$3(theme?.semanticTokens) ? theme.semanticTokens : void 0;
|
|
533
|
+
collectPresetColorTokenOwners(tokens?.colors, preset.name, token);
|
|
534
|
+
collectPresetColorTokenOwners(semanticTokens?.colors, preset.name, semanticToken);
|
|
535
|
+
}
|
|
536
|
+
return {
|
|
537
|
+
token,
|
|
538
|
+
semanticToken
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
function collectPresetColorTokenOwners(value, presetName, owners, path = []) {
|
|
542
|
+
if (!isRecord$3(value)) return;
|
|
543
|
+
for (const [key, child] of Object.entries(value)) {
|
|
544
|
+
const nextPath = key === "DEFAULT" ? path : [...path, key];
|
|
545
|
+
if (!isRecord$3(child)) continue;
|
|
546
|
+
if ("value" in child && nextPath.length > 0) {
|
|
547
|
+
owners.set(nextPath.join("."), presetName);
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
collectPresetColorTokenOwners(child, presetName, owners, nextPath);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
function presetFontTokenOwners(presets) {
|
|
554
|
+
const token = /* @__PURE__ */ new Map();
|
|
555
|
+
if (!Array.isArray(presets)) return token;
|
|
556
|
+
for (const preset of presets) {
|
|
557
|
+
if (!isRecord$3(preset) || typeof preset.name !== "string") continue;
|
|
558
|
+
const theme = isRecord$3(preset.theme) ? preset.theme : void 0;
|
|
559
|
+
collectPresetFontTokenOwners((isRecord$3(theme?.tokens) ? theme.tokens : void 0)?.fonts, preset.name, token);
|
|
560
|
+
}
|
|
561
|
+
return token;
|
|
562
|
+
}
|
|
563
|
+
function collectPresetFontTokenOwners(value, presetName, owners, path = []) {
|
|
564
|
+
if (!isRecord$3(value)) return;
|
|
565
|
+
for (const [key, child] of Object.entries(value)) {
|
|
566
|
+
const nextPath = key === "DEFAULT" ? path : [...path, key];
|
|
567
|
+
if (!isRecord$3(child)) continue;
|
|
568
|
+
if ("value" in child && nextPath.length > 0) {
|
|
569
|
+
owners.set(nextPath.join("."), presetName);
|
|
570
|
+
continue;
|
|
571
|
+
}
|
|
572
|
+
collectPresetFontTokenOwners(child, presetName, owners, nextPath);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
function mergeResolvedAndStaticColorTokens(resolved, staticTokens) {
|
|
576
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
577
|
+
for (const token of staticTokens) byKey.set(`${token.kind}:${token.path}`, token);
|
|
578
|
+
for (const token of resolved) {
|
|
579
|
+
const key = `${token.kind}:${token.path}`;
|
|
580
|
+
if (!byKey.has(key)) byKey.set(key, token);
|
|
581
|
+
}
|
|
582
|
+
return [...byKey.values()];
|
|
583
|
+
}
|
|
584
|
+
function mergeResolvedAndStaticFontTokens(resolved, staticTokens) {
|
|
585
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
586
|
+
for (const token of staticTokens) byPath.set(token.path, token);
|
|
587
|
+
for (const token of resolved) if (!byPath.has(token.path)) byPath.set(token.path, token);
|
|
588
|
+
return [...byPath.values()];
|
|
589
|
+
}
|
|
590
|
+
function editorTokenSourceTarget(options) {
|
|
591
|
+
const file = toRelativeProjectPath(options.filePath, options.projectRoot);
|
|
592
|
+
const rangeText = options.sourceText.slice(options.object.getStart(), options.object.getEnd());
|
|
593
|
+
const safety = tokenObjectWriteSafety(options.object);
|
|
594
|
+
const sourcePathPrefix = options.extended ? "theme.extend" : "theme";
|
|
595
|
+
return {
|
|
596
|
+
id: [
|
|
597
|
+
file,
|
|
598
|
+
sourcePathPrefix,
|
|
599
|
+
options.section,
|
|
600
|
+
options.object.getStart(),
|
|
601
|
+
options.object.getEnd()
|
|
602
|
+
].join("#"),
|
|
603
|
+
kind: "panda-config",
|
|
604
|
+
file,
|
|
605
|
+
absoluteFile: options.filePath,
|
|
606
|
+
range: {
|
|
607
|
+
start: options.object.getStart(),
|
|
608
|
+
end: options.object.getEnd()
|
|
609
|
+
},
|
|
610
|
+
sourceHash: hashSource(rangeText),
|
|
611
|
+
configPath: options.extended ? `${sourcePathPrefix}.${options.section}` : `${sourcePathPrefix}.${options.section}`,
|
|
612
|
+
writableSections: safety.writable ? [options.section] : [],
|
|
613
|
+
confidence: safety.writable ? "high" : "low",
|
|
614
|
+
writable: safety.writable,
|
|
615
|
+
readonlyReason: safety.writable ? void 0 : safety.reason
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
function editorReadOnlyTokenSourceTarget(options) {
|
|
619
|
+
const file = toRelativeProjectPath(options.filePath, options.projectRoot);
|
|
620
|
+
const rangeText = options.sourceText.slice(options.node.getStart(), options.node.getEnd());
|
|
621
|
+
const sourcePathPrefix = options.extended ? "theme.extend" : "theme";
|
|
622
|
+
return {
|
|
623
|
+
id: [
|
|
624
|
+
file,
|
|
625
|
+
sourcePathPrefix,
|
|
626
|
+
options.section,
|
|
627
|
+
options.node.getStart(),
|
|
628
|
+
options.node.getEnd()
|
|
629
|
+
].join("#"),
|
|
630
|
+
kind: "panda-config",
|
|
631
|
+
file,
|
|
632
|
+
absoluteFile: options.filePath,
|
|
633
|
+
range: {
|
|
634
|
+
start: options.node.getStart(),
|
|
635
|
+
end: options.node.getEnd()
|
|
636
|
+
},
|
|
637
|
+
sourceHash: hashSource(rangeText),
|
|
638
|
+
configPath: `${sourcePathPrefix}.${options.section}`,
|
|
639
|
+
writableSections: [],
|
|
640
|
+
confidence: "low",
|
|
641
|
+
writable: false,
|
|
642
|
+
readonlyReason: options.reason
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
function tokenObjectWriteSafety(object) {
|
|
646
|
+
const keys = /* @__PURE__ */ new Set();
|
|
647
|
+
for (const property of object.properties) {
|
|
648
|
+
if (!ts.isPropertyAssignment(property)) return {
|
|
649
|
+
writable: false,
|
|
650
|
+
reason: "Token object contains a spread, shorthand, method, or accessor."
|
|
651
|
+
};
|
|
652
|
+
const key = propertyNameText(property.name);
|
|
653
|
+
if (!key) return {
|
|
654
|
+
writable: false,
|
|
655
|
+
reason: "Token object contains a computed key."
|
|
656
|
+
};
|
|
657
|
+
if (keys.has(key)) return {
|
|
658
|
+
writable: false,
|
|
659
|
+
reason: "Token object contains duplicate keys."
|
|
660
|
+
};
|
|
661
|
+
keys.add(key);
|
|
662
|
+
const valueObject = objectLiteralExpression(property.initializer);
|
|
663
|
+
if (!valueObject) return {
|
|
664
|
+
writable: false,
|
|
665
|
+
reason: "Token object contains a non-object token branch."
|
|
666
|
+
};
|
|
667
|
+
if (!objectProperty(valueObject, "value")) {
|
|
668
|
+
const nestedSafety = tokenObjectWriteSafety(valueObject);
|
|
669
|
+
if (!nestedSafety.writable) return nestedSafety;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
return { writable: true };
|
|
673
|
+
}
|
|
674
|
+
function collectColorTokenMetadata(object, options, path = []) {
|
|
675
|
+
const tokens = [];
|
|
676
|
+
for (const property of object.properties) {
|
|
677
|
+
if (!ts.isPropertyAssignment(property)) continue;
|
|
678
|
+
const key = propertyNameText(property.name);
|
|
679
|
+
if (!key) continue;
|
|
680
|
+
const valueObject = objectLiteralExpression(property.initializer);
|
|
681
|
+
if (!valueObject) continue;
|
|
682
|
+
const valueExpression = objectProperty(valueObject, "value");
|
|
683
|
+
const nextPath = key === "DEFAULT" ? path : [...path, key];
|
|
684
|
+
if (valueExpression) {
|
|
685
|
+
const value = jsonValueFromExpression(valueExpression);
|
|
686
|
+
if (value !== void 0 && nextPath.length > 0) {
|
|
687
|
+
const tokenPath = nextPath.join(".");
|
|
688
|
+
tokens.push({
|
|
689
|
+
kind: options.kind,
|
|
690
|
+
category: "colors",
|
|
691
|
+
path: tokenPath,
|
|
692
|
+
label: tokenPath,
|
|
693
|
+
value,
|
|
694
|
+
swatch: swatchFromJsonValue(value),
|
|
695
|
+
cssVariable: `var(--colors-${tokenPathToCssVariableSuffix(tokenPath)})`,
|
|
696
|
+
sourceTargetId: options.sourceTargetId,
|
|
697
|
+
sourcePath: nextPath,
|
|
698
|
+
writable: options.writable,
|
|
699
|
+
readonlyReason: options.writable ? void 0 : "Token source target is read-only.",
|
|
700
|
+
conditions: options.kind === "semantic-token" && isJsonObject(value) ? Object.entries(value).map(([condition, conditionValue]) => ({
|
|
701
|
+
condition,
|
|
702
|
+
value: conditionValue,
|
|
703
|
+
swatch: swatchFromJsonValue(conditionValue)
|
|
704
|
+
})) : void 0
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
continue;
|
|
708
|
+
}
|
|
709
|
+
tokens.push(...collectColorTokenMetadata(valueObject, options, nextPath));
|
|
710
|
+
}
|
|
711
|
+
return tokens;
|
|
712
|
+
}
|
|
713
|
+
function collectFontTokenMetadata(object, path = []) {
|
|
714
|
+
const tokens = [];
|
|
715
|
+
for (const property of object.properties) {
|
|
716
|
+
if (!ts.isPropertyAssignment(property)) continue;
|
|
717
|
+
const key = propertyNameText(property.name);
|
|
718
|
+
if (!key) continue;
|
|
719
|
+
const valueObject = objectLiteralExpression(property.initializer);
|
|
720
|
+
if (!valueObject) continue;
|
|
721
|
+
const valueExpression = objectProperty(valueObject, "value");
|
|
722
|
+
const nextPath = key === "DEFAULT" ? path : [...path, key];
|
|
723
|
+
if (valueExpression) {
|
|
724
|
+
const value = jsonValueFromExpression(valueExpression);
|
|
725
|
+
if (value !== void 0 && nextPath.length > 0) {
|
|
726
|
+
const tokenPath = nextPath.join(".");
|
|
727
|
+
tokens.push({
|
|
728
|
+
kind: "token",
|
|
729
|
+
category: "fonts",
|
|
730
|
+
path: tokenPath,
|
|
731
|
+
label: tokenPath,
|
|
732
|
+
value,
|
|
733
|
+
cssVariable: `var(--fonts-${tokenPathToCssVariableSuffix(tokenPath)})`,
|
|
734
|
+
sourcePath: nextPath
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
continue;
|
|
738
|
+
}
|
|
739
|
+
tokens.push(...collectFontTokenMetadata(valueObject, nextPath));
|
|
740
|
+
}
|
|
741
|
+
return tokens;
|
|
742
|
+
}
|
|
743
|
+
function findPandaConfigObject(sourceFile) {
|
|
744
|
+
let result;
|
|
745
|
+
const visit = (node) => {
|
|
746
|
+
if (result) return;
|
|
747
|
+
if (ts.isExportAssignment(node)) {
|
|
748
|
+
result = configObjectFromExpression(node.expression);
|
|
749
|
+
if (result) return;
|
|
750
|
+
}
|
|
751
|
+
if (ts.isCallExpression(node) && callExpressionName(node.expression) === "defineConfig") {
|
|
752
|
+
result = objectLiteralExpression(node.arguments[0]);
|
|
753
|
+
if (result) return;
|
|
754
|
+
}
|
|
755
|
+
ts.forEachChild(node, visit);
|
|
756
|
+
};
|
|
757
|
+
visit(sourceFile);
|
|
758
|
+
return result;
|
|
759
|
+
}
|
|
760
|
+
function configObjectFromExpression(expression) {
|
|
761
|
+
const unwrapped = unwrapExpression(expression);
|
|
762
|
+
if (ts.isObjectLiteralExpression(unwrapped)) return unwrapped;
|
|
763
|
+
if (ts.isCallExpression(unwrapped) && callExpressionName(unwrapped.expression) === "defineConfig") return objectLiteralExpression(unwrapped.arguments[0]);
|
|
764
|
+
}
|
|
765
|
+
function callExpressionName(expression) {
|
|
766
|
+
const unwrapped = unwrapExpression(expression);
|
|
767
|
+
if (ts.isIdentifier(unwrapped)) return unwrapped.text;
|
|
768
|
+
if (ts.isPropertyAccessExpression(unwrapped)) return unwrapped.name.text;
|
|
769
|
+
}
|
|
770
|
+
function objectProperty(object, name) {
|
|
771
|
+
for (const property of object.properties) {
|
|
772
|
+
if (!ts.isPropertyAssignment(property)) continue;
|
|
773
|
+
if (propertyNameText(property.name) === name) return property.initializer;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
function propertyNameText(name) {
|
|
777
|
+
if (ts.isIdentifier(name)) return name.text;
|
|
778
|
+
if (ts.isStringLiteral(name) || ts.isNumericLiteral(name)) return name.text;
|
|
779
|
+
}
|
|
780
|
+
function objectLiteralExpression(expression) {
|
|
781
|
+
if (!expression) return void 0;
|
|
782
|
+
const unwrapped = unwrapExpression(expression);
|
|
783
|
+
return ts.isObjectLiteralExpression(unwrapped) ? unwrapped : void 0;
|
|
784
|
+
}
|
|
785
|
+
function unwrapExpression(expression) {
|
|
786
|
+
let current = expression;
|
|
787
|
+
while (ts.isAsExpression(current) || ts.isSatisfiesExpression(current) || ts.isParenthesizedExpression(current)) current = current.expression;
|
|
788
|
+
return current;
|
|
789
|
+
}
|
|
790
|
+
function jsonValueFromExpression(expression) {
|
|
791
|
+
const unwrapped = unwrapExpression(expression);
|
|
792
|
+
if (ts.isStringLiteral(unwrapped) || ts.isNoSubstitutionTemplateLiteral(unwrapped)) return unwrapped.text;
|
|
793
|
+
if (ts.isNumericLiteral(unwrapped)) return Number(unwrapped.text);
|
|
794
|
+
if (unwrapped.kind === ts.SyntaxKind.TrueKeyword) return true;
|
|
795
|
+
if (unwrapped.kind === ts.SyntaxKind.FalseKeyword) return false;
|
|
796
|
+
if (unwrapped.kind === ts.SyntaxKind.NullKeyword) return null;
|
|
797
|
+
if (ts.isArrayLiteralExpression(unwrapped)) {
|
|
798
|
+
const items = unwrapped.elements.map((item) => jsonValueFromExpression(item));
|
|
799
|
+
return items.every((item) => item !== void 0) ? items : void 0;
|
|
800
|
+
}
|
|
801
|
+
if (ts.isObjectLiteralExpression(unwrapped)) {
|
|
802
|
+
const value = {};
|
|
803
|
+
for (const property of unwrapped.properties) {
|
|
804
|
+
if (!ts.isPropertyAssignment(property)) return void 0;
|
|
805
|
+
const key = propertyNameText(property.name);
|
|
806
|
+
if (!key) return void 0;
|
|
807
|
+
const propertyValue = jsonValueFromExpression(property.initializer);
|
|
808
|
+
if (propertyValue === void 0) return void 0;
|
|
809
|
+
value[key] = propertyValue;
|
|
810
|
+
}
|
|
811
|
+
return value;
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
function jsonValueFromUnknown(value) {
|
|
815
|
+
return isJsonValue$1(value) ? value : void 0;
|
|
816
|
+
}
|
|
817
|
+
function unavailableMetadataSection(reason, message) {
|
|
818
|
+
return {
|
|
819
|
+
status: "unavailable",
|
|
820
|
+
items: [],
|
|
821
|
+
reason,
|
|
822
|
+
message
|
|
823
|
+
};
|
|
824
|
+
}
|
|
825
|
+
function isJsonObject(value) {
|
|
826
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
827
|
+
}
|
|
828
|
+
function swatchFromJsonValue(value) {
|
|
829
|
+
if (typeof value !== "string") return void 0;
|
|
830
|
+
const trimmed = value.trim();
|
|
831
|
+
if (/^#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(trimmed)) return trimmed;
|
|
832
|
+
if (/^(rgb|rgba|hsl|hsla|oklch|oklab|lch|lab|color)\(/i.test(trimmed)) return trimmed;
|
|
833
|
+
}
|
|
834
|
+
function tokenPathToCssVariableSuffix(value) {
|
|
835
|
+
return value.replace(/\./g, "-");
|
|
836
|
+
}
|
|
837
|
+
function absoluteProjectPath(projectRoot, filePath) {
|
|
838
|
+
const normalized = normalizePath(filePath);
|
|
839
|
+
if (normalized.startsWith("/")) return normalized;
|
|
840
|
+
return `${projectRoot}/${normalized.replace(/^\.\//, "")}`;
|
|
841
|
+
}
|
|
842
|
+
function toRelativeProjectPath(filePath, projectRoot) {
|
|
843
|
+
const file = normalizePath(filePath);
|
|
844
|
+
const root = normalizePath(projectRoot).replace(/\/$/, "");
|
|
845
|
+
return file.startsWith(`${root}/`) ? file.slice(root.length + 1) : file;
|
|
846
|
+
}
|
|
847
|
+
function normalizePath(path) {
|
|
848
|
+
return path.replace(/\\/g, "/");
|
|
849
|
+
}
|
|
850
|
+
function isMissingFileError$2(error) {
|
|
851
|
+
return isRecord$3(error) && error.code === "ENOENT";
|
|
852
|
+
}
|
|
853
|
+
function errorMessage(error) {
|
|
854
|
+
return error instanceof Error ? error.message : String(error);
|
|
855
|
+
}
|
|
856
|
+
function isRecord$3(value) {
|
|
857
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
858
|
+
}
|
|
859
|
+
function isJsonValue$1(value) {
|
|
860
|
+
if (value === null) return true;
|
|
861
|
+
if ([
|
|
862
|
+
"string",
|
|
863
|
+
"number",
|
|
864
|
+
"boolean"
|
|
865
|
+
].includes(typeof value)) return true;
|
|
866
|
+
if (Array.isArray(value)) return value.every(isJsonValue$1);
|
|
867
|
+
if (!isRecord$3(value)) return false;
|
|
868
|
+
return Object.values(value).every(isJsonValue$1);
|
|
869
|
+
}
|
|
870
|
+
//#endregion
|
|
871
|
+
//#region src/vite/sourceLocation.ts
|
|
872
|
+
async function readOpenSourceLocationRequest(request) {
|
|
873
|
+
try {
|
|
874
|
+
const body = await readRequestBody$2(request);
|
|
875
|
+
const parsed = JSON.parse(body);
|
|
876
|
+
if (!isOpenSourceLocationRequest(parsed)) return {
|
|
877
|
+
ok: false,
|
|
878
|
+
response: openSourceLocationFailure("invalid-request", "Request body is not a valid source location request.")
|
|
879
|
+
};
|
|
880
|
+
return {
|
|
881
|
+
ok: true,
|
|
882
|
+
request: parsed
|
|
883
|
+
};
|
|
884
|
+
} catch (error) {
|
|
885
|
+
return {
|
|
886
|
+
ok: false,
|
|
887
|
+
response: openSourceLocationFailure("invalid-request", `Failed to read source location request: ${error instanceof Error ? error.message : String(error)}`)
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
async function resolveOpenSourceLocation(options) {
|
|
892
|
+
const request = options.request;
|
|
893
|
+
if (request.kind === "component") {
|
|
894
|
+
const entry = options.manifest.entries.find((item) => item.id === request.editId);
|
|
895
|
+
if (!entry) return openSourceLocationFailure("missing-metadata", "No manifest entry exists for that component source location.");
|
|
896
|
+
const trustedPath = trustedManifestFilePath(options.manifest, entry);
|
|
897
|
+
if (!trustedPath.ok) return openSourceLocationFailure("path-outside-project", trustedPath.message, trustedPath.details);
|
|
898
|
+
const line = entry.loc?.start.line;
|
|
899
|
+
const column = entry.loc?.start.column;
|
|
900
|
+
try {
|
|
901
|
+
await access(trustedPath.file);
|
|
902
|
+
} catch {
|
|
903
|
+
return openSourceLocationFailure("file-not-found", "Component source file does not exist.", { file: toRelativeProjectPath$1(trustedPath.file, options.projectRoot) });
|
|
904
|
+
}
|
|
905
|
+
return openSourceLocationSuccess({
|
|
906
|
+
file: trustedPath.file,
|
|
907
|
+
line,
|
|
908
|
+
column,
|
|
909
|
+
projectRoot: options.projectRoot
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
const parsed = parseSourceLocationText(request.source);
|
|
913
|
+
if (!parsed.ok) return parsed.response;
|
|
914
|
+
const safePath = safeProjectSourcePath(options.projectRoot, parsed.file);
|
|
915
|
+
if (!safePath.ok) return openSourceLocationFailure(safePath.code, safePath.message, safePath.details);
|
|
916
|
+
try {
|
|
917
|
+
await access(safePath.file);
|
|
918
|
+
} catch {
|
|
919
|
+
return openSourceLocationFailure("file-not-found", "Source file does not exist.", { file: toRelativeProjectPath$1(safePath.file, options.projectRoot) });
|
|
920
|
+
}
|
|
921
|
+
return openSourceLocationSuccess({
|
|
922
|
+
file: safePath.file,
|
|
923
|
+
line: parsed.line,
|
|
924
|
+
column: parsed.column,
|
|
925
|
+
projectRoot: options.projectRoot
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
function parseSourceLocationText(source) {
|
|
929
|
+
const value = source.trim();
|
|
930
|
+
if (!value || /:\/\//.test(value)) return {
|
|
931
|
+
ok: false,
|
|
932
|
+
response: openSourceLocationFailure("invalid-request", "Source location must be a project file path.")
|
|
933
|
+
};
|
|
934
|
+
const match = /^(.*?)(?::(\d+)(?::(\d+))?)?$/.exec(value);
|
|
935
|
+
const file = match?.[1]?.trim();
|
|
936
|
+
if (!match || !file) return {
|
|
937
|
+
ok: false,
|
|
938
|
+
response: openSourceLocationFailure("invalid-request", "Source location must include a file path.")
|
|
939
|
+
};
|
|
940
|
+
const line = match[2] ? Number.parseInt(match[2], 10) : void 0;
|
|
941
|
+
const column = match[3] ? Number.parseInt(match[3], 10) : void 0;
|
|
942
|
+
if (line !== void 0 && line < 1 || column !== void 0 && column < 1) return {
|
|
943
|
+
ok: false,
|
|
944
|
+
response: openSourceLocationFailure("invalid-request", "Line and column numbers must be positive integers.")
|
|
945
|
+
};
|
|
946
|
+
return {
|
|
947
|
+
ok: true,
|
|
948
|
+
file,
|
|
949
|
+
line,
|
|
950
|
+
column
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
function openSourceLocationSuccess(options) {
|
|
954
|
+
const file = toRelativeProjectPath$1(options.file, options.projectRoot);
|
|
955
|
+
const location = [
|
|
956
|
+
options.file,
|
|
957
|
+
options.line === void 0 ? void 0 : String(options.line),
|
|
958
|
+
options.column === void 0 ? void 0 : String(options.column)
|
|
959
|
+
].filter((part) => part !== void 0).join(":");
|
|
960
|
+
return {
|
|
961
|
+
ok: true,
|
|
962
|
+
file,
|
|
963
|
+
line: options.line,
|
|
964
|
+
column: options.column,
|
|
965
|
+
openEditorUrl: `/__open-in-editor?file=${encodeURIComponent(location)}`
|
|
966
|
+
};
|
|
967
|
+
}
|
|
968
|
+
function openSourceLocationFailure(code, message, details) {
|
|
969
|
+
return {
|
|
970
|
+
ok: false,
|
|
971
|
+
error: {
|
|
972
|
+
code,
|
|
973
|
+
message,
|
|
974
|
+
details
|
|
975
|
+
}
|
|
976
|
+
};
|
|
977
|
+
}
|
|
978
|
+
function isOpenSourceLocationRequest(value) {
|
|
979
|
+
if (!isRecord$2(value)) return false;
|
|
980
|
+
if (value.kind === "source") return typeof value.source === "string" && value.source.length > 0;
|
|
981
|
+
if (value.kind === "component") return typeof value.editId === "string" && value.editId.length > 0;
|
|
982
|
+
return false;
|
|
983
|
+
}
|
|
984
|
+
async function readRequestBody$2(request) {
|
|
985
|
+
if (!request[Symbol.asyncIterator]) return "";
|
|
986
|
+
let body = "";
|
|
987
|
+
for await (const chunk of request) body += typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
988
|
+
return body;
|
|
989
|
+
}
|
|
990
|
+
function isRecord$2(value) {
|
|
991
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
992
|
+
}
|
|
993
|
+
//#endregion
|
|
994
|
+
//#region src/vite/runtimeModules.ts
|
|
995
|
+
function registerRuntimeModuleRoutes(server, options) {
|
|
996
|
+
server.middlewares.use(options.runtimeBootstrapEndpoint, (_request, response) => {
|
|
997
|
+
response.statusCode = 200;
|
|
998
|
+
response.setHeader("content-type", "application/javascript");
|
|
999
|
+
response.setHeader("cache-control", "no-store");
|
|
1000
|
+
response.end(runtimeBootstrapSource({
|
|
1001
|
+
manifestEndpoint: options.manifestEndpoint,
|
|
1002
|
+
editorMetadataEndpoint: options.editorMetadataEndpoint,
|
|
1003
|
+
globalName: options.globalName,
|
|
1004
|
+
runtimeModuleEndpoint: options.runtimeModuleEndpoint,
|
|
1005
|
+
uiModuleEndpoint: options.uiModuleEndpoint
|
|
1006
|
+
}));
|
|
1007
|
+
});
|
|
1008
|
+
server.middlewares.use(DEFAULT_RUNTIME_MODULE_SOURCE_MAP_ENDPOINT, async (_request, response) => {
|
|
1009
|
+
try {
|
|
1010
|
+
const runtimeModuleSourceMap = await readFile(new URL("./runtime.mjs.map", import.meta.url), "utf8");
|
|
1011
|
+
response.statusCode = 200;
|
|
1012
|
+
response.setHeader("content-type", "application/json");
|
|
1013
|
+
response.setHeader("cache-control", "no-store");
|
|
1014
|
+
response.end(runtimeModuleSourceMap);
|
|
1015
|
+
} catch (error) {
|
|
1016
|
+
response.statusCode = 404;
|
|
1017
|
+
response.setHeader("content-type", "text/plain");
|
|
1018
|
+
response.setHeader("cache-control", "no-store");
|
|
1019
|
+
response.end(`Failed to load Panda inspector runtime module source map: ${error instanceof Error ? error.message : String(error)}`);
|
|
1020
|
+
}
|
|
1021
|
+
});
|
|
1022
|
+
server.middlewares.use(options.runtimeModuleEndpoint, async (_request, response) => {
|
|
1023
|
+
try {
|
|
1024
|
+
const runtimeModuleSource = rewriteInspectorModuleSource(await readFile(new URL("./runtime.mjs", import.meta.url), "utf8"), options.runtimeChunkEndpoint, DEFAULT_RUNTIME_MODULE_SOURCE_MAP_ENDPOINT);
|
|
1025
|
+
response.statusCode = 200;
|
|
1026
|
+
response.setHeader("content-type", "application/javascript");
|
|
1027
|
+
response.setHeader("cache-control", "no-store");
|
|
1028
|
+
response.end(runtimeModuleSource);
|
|
1029
|
+
} catch (error) {
|
|
1030
|
+
response.statusCode = 500;
|
|
1031
|
+
response.setHeader("content-type", "text/plain");
|
|
1032
|
+
response.setHeader("cache-control", "no-store");
|
|
1033
|
+
response.end(`Failed to load Panda inspector runtime module: ${error instanceof Error ? error.message : String(error)}`);
|
|
1034
|
+
}
|
|
1035
|
+
});
|
|
1036
|
+
server.middlewares.use(options.runtimeChunkEndpoint, async (request, response) => {
|
|
1037
|
+
const fileName = runtimeChunkFileName(request.url);
|
|
1038
|
+
if (!fileName) {
|
|
1039
|
+
response.statusCode = 404;
|
|
1040
|
+
response.setHeader("content-type", "text/plain");
|
|
1041
|
+
response.setHeader("cache-control", "no-store");
|
|
1042
|
+
response.end("Unknown Panda inspector runtime chunk.");
|
|
1043
|
+
return;
|
|
1044
|
+
}
|
|
1045
|
+
try {
|
|
1046
|
+
const runtimeChunkSource = await readFile(new URL(`./${fileName}`, import.meta.url), "utf8");
|
|
1047
|
+
response.statusCode = 200;
|
|
1048
|
+
response.setHeader("content-type", fileName.endsWith(".map") ? "application/json" : "application/javascript");
|
|
1049
|
+
response.setHeader("cache-control", "no-store");
|
|
1050
|
+
response.end(runtimeChunkSource);
|
|
1051
|
+
} catch (error) {
|
|
1052
|
+
response.statusCode = 404;
|
|
1053
|
+
response.setHeader("content-type", "text/plain");
|
|
1054
|
+
response.setHeader("cache-control", "no-store");
|
|
1055
|
+
response.end(`Failed to load Panda inspector runtime chunk: ${error instanceof Error ? error.message : String(error)}`);
|
|
1056
|
+
}
|
|
1057
|
+
});
|
|
1058
|
+
server.middlewares.use(DEFAULT_UI_MODULE_SOURCE_MAP_ENDPOINT, async (_request, response) => {
|
|
1059
|
+
try {
|
|
1060
|
+
const uiModuleSourceMap = await readFile(new URL("./ui.mjs.map", import.meta.url), "utf8");
|
|
1061
|
+
response.statusCode = 200;
|
|
1062
|
+
response.setHeader("content-type", "application/json");
|
|
1063
|
+
response.setHeader("cache-control", "no-store");
|
|
1064
|
+
response.end(uiModuleSourceMap);
|
|
1065
|
+
} catch (error) {
|
|
1066
|
+
response.statusCode = 404;
|
|
1067
|
+
response.setHeader("content-type", "text/plain");
|
|
1068
|
+
response.setHeader("cache-control", "no-store");
|
|
1069
|
+
response.end(`Failed to load Panda inspector UI module source map: ${error instanceof Error ? error.message : String(error)}`);
|
|
1070
|
+
}
|
|
1071
|
+
});
|
|
1072
|
+
server.middlewares.use(options.uiModuleEndpoint, async (_request, response) => {
|
|
1073
|
+
try {
|
|
1074
|
+
const uiModuleSource = rewriteInspectorModuleSource(await readFile(new URL("./ui.mjs", import.meta.url), "utf8"), options.runtimeChunkEndpoint, DEFAULT_UI_MODULE_SOURCE_MAP_ENDPOINT);
|
|
1075
|
+
response.statusCode = 200;
|
|
1076
|
+
response.setHeader("content-type", "application/javascript");
|
|
1077
|
+
response.setHeader("cache-control", "no-store");
|
|
1078
|
+
response.end(uiModuleSource);
|
|
1079
|
+
} catch (error) {
|
|
1080
|
+
response.statusCode = 500;
|
|
1081
|
+
response.setHeader("content-type", "text/plain");
|
|
1082
|
+
response.setHeader("cache-control", "no-store");
|
|
1083
|
+
response.end(`Failed to load Panda inspector UI module: ${error instanceof Error ? error.message : String(error)}`);
|
|
1084
|
+
}
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1087
|
+
function runtimeBootstrapSource(options) {
|
|
1088
|
+
const runtimeOptions = JSON.stringify({
|
|
1089
|
+
globalName: options.globalName,
|
|
1090
|
+
manifestEndpoint: options.manifestEndpoint,
|
|
1091
|
+
editorMetadataEndpoint: options.editorMetadataEndpoint
|
|
1092
|
+
});
|
|
1093
|
+
return [
|
|
1094
|
+
`import { installPandaInspectorRuntime } from ${JSON.stringify(options.runtimeModuleEndpoint)};`,
|
|
1095
|
+
`import { installReadonlyInspectorPanel } from ${JSON.stringify(options.uiModuleEndpoint)};`,
|
|
1096
|
+
`const pandaInspectorRuntime = installPandaInspectorRuntime(${runtimeOptions});`,
|
|
1097
|
+
"installReadonlyInspectorPanel(pandaInspectorRuntime);"
|
|
1098
|
+
].join("\n");
|
|
1099
|
+
}
|
|
1100
|
+
function rewriteInspectorModuleSource(source, runtimeChunkEndpoint, sourceMapEndpoint) {
|
|
1101
|
+
return source.replaceAll("from \"./", `from "${runtimeChunkEndpoint}`).replace(/\/\/# sourceMappingURL=[^\r\n]+/g, `//# sourceMappingURL=${sourceMapEndpoint}`);
|
|
1102
|
+
}
|
|
1103
|
+
function runtimeChunkFileName(url) {
|
|
1104
|
+
const fileName = (url ?? "").replace(/[?#].*$/, "").split("/").filter(Boolean).at(-1);
|
|
1105
|
+
if (!fileName || !/^[A-Za-z0-9._-]+\.mjs(?:\.map)?$/.test(fileName)) return void 0;
|
|
1106
|
+
return fileName;
|
|
1107
|
+
}
|
|
1108
|
+
//#endregion
|
|
1109
|
+
//#region src/vite/styleModuleEndpoint.ts
|
|
1110
|
+
function registerStyleModuleRoute(server, options) {
|
|
1111
|
+
server.middlewares.use(options.endpoint, async (request, response) => {
|
|
1112
|
+
if (request.method && request.method !== "POST") {
|
|
1113
|
+
response.statusCode = 405;
|
|
1114
|
+
response.setHeader("content-type", "application/json");
|
|
1115
|
+
response.setHeader("cache-control", "no-store");
|
|
1116
|
+
response.end(JSON.stringify(styleModuleFailure("invalid-edit", "Panda inspector style-module discovery requires POST.")));
|
|
1117
|
+
return;
|
|
1118
|
+
}
|
|
1119
|
+
const requestResult = await readStyleModuleRequest(request);
|
|
1120
|
+
if (!requestResult.ok) {
|
|
1121
|
+
response.statusCode = 400;
|
|
1122
|
+
response.setHeader("content-type", "application/json");
|
|
1123
|
+
response.setHeader("cache-control", "no-store");
|
|
1124
|
+
response.end(JSON.stringify(requestResult.response));
|
|
1125
|
+
return;
|
|
1126
|
+
}
|
|
1127
|
+
const paths = componentStyleModulePaths({
|
|
1128
|
+
projectRoot: options.projectRoot,
|
|
1129
|
+
componentSource: requestResult.componentSource
|
|
1130
|
+
});
|
|
1131
|
+
if (!paths.ok) {
|
|
1132
|
+
response.statusCode = 400;
|
|
1133
|
+
response.setHeader("content-type", "application/json");
|
|
1134
|
+
response.setHeader("cache-control", "no-store");
|
|
1135
|
+
response.end(JSON.stringify(styleModuleFailure(paths.code, paths.message, paths.details)));
|
|
1136
|
+
return;
|
|
1137
|
+
}
|
|
1138
|
+
let sourceText;
|
|
1139
|
+
try {
|
|
1140
|
+
sourceText = await readFile(paths.paths.styleFile, "utf8");
|
|
1141
|
+
} catch (error) {
|
|
1142
|
+
if (!isMissingFileError$1(error)) {
|
|
1143
|
+
response.statusCode = 400;
|
|
1144
|
+
response.setHeader("content-type", "application/json");
|
|
1145
|
+
response.setHeader("cache-control", "no-store");
|
|
1146
|
+
response.end(JSON.stringify(styleModuleFailure("write-failed", `Failed to read style module: ${error instanceof Error ? error.message : String(error)}`)));
|
|
1147
|
+
return;
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
const result = readComponentStyleModule({
|
|
1151
|
+
projectRoot: options.projectRoot,
|
|
1152
|
+
componentSource: requestResult.componentSource,
|
|
1153
|
+
sourceText,
|
|
1154
|
+
cssImportSources: options.cssImportSources
|
|
1155
|
+
});
|
|
1156
|
+
response.statusCode = result.ok ? 200 : 400;
|
|
1157
|
+
response.setHeader("content-type", "application/json");
|
|
1158
|
+
response.setHeader("cache-control", "no-store");
|
|
1159
|
+
response.end(JSON.stringify(result));
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
1162
|
+
async function readStyleModuleRequest(request) {
|
|
1163
|
+
try {
|
|
1164
|
+
const body = await readRequestBody$1(request);
|
|
1165
|
+
const parsed = JSON.parse(body);
|
|
1166
|
+
if (!isRecord$1(parsed) || typeof parsed.componentSource !== "string") return {
|
|
1167
|
+
ok: false,
|
|
1168
|
+
response: styleModuleFailure("invalid-edit", "Request body is not a valid style-module request.")
|
|
1169
|
+
};
|
|
1170
|
+
return {
|
|
1171
|
+
ok: true,
|
|
1172
|
+
componentSource: parsed.componentSource
|
|
1173
|
+
};
|
|
1174
|
+
} catch (error) {
|
|
1175
|
+
return {
|
|
1176
|
+
ok: false,
|
|
1177
|
+
response: styleModuleFailure("invalid-edit", `Failed to read style-module request: ${error instanceof Error ? error.message : String(error)}`)
|
|
1178
|
+
};
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
async function readRequestBody$1(request) {
|
|
1182
|
+
if (!request[Symbol.asyncIterator]) return "";
|
|
1183
|
+
let body = "";
|
|
1184
|
+
for await (const chunk of request) body += typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
1185
|
+
return body;
|
|
1186
|
+
}
|
|
1187
|
+
function styleModuleFailure(code, message, details) {
|
|
1188
|
+
return {
|
|
1189
|
+
ok: false,
|
|
1190
|
+
error: {
|
|
1191
|
+
code,
|
|
1192
|
+
message,
|
|
1193
|
+
details
|
|
1194
|
+
}
|
|
1195
|
+
};
|
|
1196
|
+
}
|
|
1197
|
+
function isMissingFileError$1(error) {
|
|
1198
|
+
return isRecord$1(error) && error.code === "ENOENT";
|
|
1199
|
+
}
|
|
1200
|
+
function isRecord$1(value) {
|
|
1201
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1202
|
+
}
|
|
1203
|
+
//#endregion
|
|
1204
|
+
//#region src/vite/tsxInstrumentation.ts
|
|
1205
|
+
function transformTsxSource(options) {
|
|
1206
|
+
const analysis = analyzePandaCssSource({
|
|
1207
|
+
filePath: options.filePath,
|
|
1208
|
+
projectRoot: options.projectRoot,
|
|
1209
|
+
sourceText: options.sourceText,
|
|
1210
|
+
cssImportSources: options.cssImportSources,
|
|
1211
|
+
sourceSyntax: options.sourceSyntax
|
|
1212
|
+
});
|
|
1213
|
+
const source = parsePandaSource(options.sourceSyntax, {
|
|
1214
|
+
filePath: options.filePath,
|
|
1215
|
+
sourceText: options.sourceText
|
|
1216
|
+
});
|
|
1217
|
+
const targets = source.astKind === "typescript" ? findEditableJsxTargets(source.root, options.projectRoot) : [];
|
|
1218
|
+
const jsxMetadataTargets = source.astKind === "typescript" ? findJsxMetadataTargets(source.root, options.projectRoot) : [];
|
|
1219
|
+
const targetsByObjectStart = new Map(targets.map((target) => [target.objectStart, target]));
|
|
1220
|
+
const cssCallTargets = findCssCallTargets(source);
|
|
1221
|
+
const cssCallsByCallStart = new Map(cssCallTargets.map((target) => [target.callStart, target]));
|
|
1222
|
+
const cssCallsByObjectStart = new Map(cssCallTargets.filter((target) => target.objectStart !== void 0).map((target) => [target.objectStart, target]));
|
|
1223
|
+
const helperName = availableHelperName(options.sourceText);
|
|
1224
|
+
const edits = [];
|
|
1225
|
+
const entries = [];
|
|
1226
|
+
const editableMetadataPositions = /* @__PURE__ */ new Set();
|
|
1227
|
+
let needsHelper = false;
|
|
1228
|
+
for (const entry of analysis.entries) {
|
|
1229
|
+
const markerClass = markerClassForEditId(entry.id);
|
|
1230
|
+
const target = entry.range ? targetsByObjectStart.get(entry.range.start) : void 0;
|
|
1231
|
+
const nextEntry = {
|
|
1232
|
+
...entry,
|
|
1233
|
+
markerClass,
|
|
1234
|
+
component: target?.component,
|
|
1235
|
+
element: target?.element,
|
|
1236
|
+
attribute: target?.attribute,
|
|
1237
|
+
jsxSource: target?.jsxSource
|
|
1238
|
+
};
|
|
1239
|
+
entries.push(nextEntry);
|
|
1240
|
+
const callTarget = entry.kind === "panda-css" && entry.range ? cssCallsByObjectStart.get(entry.range.start) : entry.range ? cssCallsByCallStart.get(entry.range.start) : void 0;
|
|
1241
|
+
if (callTarget) {
|
|
1242
|
+
edits.push({
|
|
1243
|
+
position: callTarget.callStart,
|
|
1244
|
+
text: `${helperName}(`
|
|
1245
|
+
});
|
|
1246
|
+
edits.push({
|
|
1247
|
+
position: callTarget.callEnd,
|
|
1248
|
+
text: `, ${JSON.stringify(markerClass)})`
|
|
1249
|
+
});
|
|
1250
|
+
needsHelper = true;
|
|
1251
|
+
}
|
|
1252
|
+
if (target) {
|
|
1253
|
+
const attributeText = metadataAttributeText(nextEntry, target, options.attributes);
|
|
1254
|
+
if (attributeText.length > 0) edits.push({
|
|
1255
|
+
position: target.insertPosition,
|
|
1256
|
+
text: attributeText
|
|
1257
|
+
});
|
|
1258
|
+
editableMetadataPositions.add(target.insertPosition);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
for (const target of jsxMetadataTargets) {
|
|
1262
|
+
if (editableMetadataPositions.has(target.insertPosition)) continue;
|
|
1263
|
+
const attributeText = jsxMetadataAttributeText(target, options.attributes);
|
|
1264
|
+
if (attributeText.length > 0) edits.push({
|
|
1265
|
+
position: target.insertPosition,
|
|
1266
|
+
text: attributeText
|
|
1267
|
+
});
|
|
1268
|
+
}
|
|
1269
|
+
if (edits.length === 0) return {
|
|
1270
|
+
code: options.sourceText,
|
|
1271
|
+
entries
|
|
1272
|
+
};
|
|
1273
|
+
if (needsHelper) edits.push({
|
|
1274
|
+
position: source.ops.firstImportEnd(source.root),
|
|
1275
|
+
text: markerHelperSource(helperName)
|
|
1276
|
+
});
|
|
1277
|
+
let code = options.sourceText;
|
|
1278
|
+
for (const edit of edits.sort((left, right) => right.position - left.position)) code = `${code.slice(0, edit.position)}${edit.text}${code.slice(edit.position)}`;
|
|
1279
|
+
return {
|
|
1280
|
+
code,
|
|
1281
|
+
entries
|
|
1282
|
+
};
|
|
1283
|
+
}
|
|
1284
|
+
function findCssCallTargets(source) {
|
|
1285
|
+
const targets = [];
|
|
1286
|
+
source.ops.walk(source.root, (node) => {
|
|
1287
|
+
if (source.ops.isCallExpression(node)) {
|
|
1288
|
+
const firstArg = source.ops.getCallArguments(node)[0];
|
|
1289
|
+
const callRange = source.ops.getRange(node);
|
|
1290
|
+
targets.push({
|
|
1291
|
+
callStart: callRange.start,
|
|
1292
|
+
callEnd: callRange.end,
|
|
1293
|
+
objectStart: firstArg && source.ops.isObjectExpression(firstArg) ? source.ops.getRange(firstArg).start : void 0
|
|
1294
|
+
});
|
|
1295
|
+
}
|
|
1296
|
+
});
|
|
1297
|
+
return targets;
|
|
1298
|
+
}
|
|
1299
|
+
function availableHelperName(sourceText) {
|
|
1300
|
+
const base = "__pandaInspectorClass";
|
|
1301
|
+
if (!new RegExp(`\\b${base}\\b`).test(sourceText)) return base;
|
|
1302
|
+
let index = 1;
|
|
1303
|
+
while (new RegExp(`\\b${base}${index}\\b`).test(sourceText)) index += 1;
|
|
1304
|
+
return `${base}${index}`;
|
|
1305
|
+
}
|
|
1306
|
+
function markerHelperSource(helperName) {
|
|
1307
|
+
return [
|
|
1308
|
+
"",
|
|
1309
|
+
"",
|
|
1310
|
+
`function ${helperName}(className, markerClass) {`,
|
|
1311
|
+
" return className ? `${className} ${markerClass}` : markerClass;",
|
|
1312
|
+
"}",
|
|
1313
|
+
""
|
|
1314
|
+
].join("\n");
|
|
1315
|
+
}
|
|
1316
|
+
function findEditableJsxTargets(sourceFile, projectRoot) {
|
|
1317
|
+
const targets = [];
|
|
1318
|
+
const componentStack = [];
|
|
1319
|
+
const visit = (node) => {
|
|
1320
|
+
const component = componentNameForNode(node);
|
|
1321
|
+
if (component) {
|
|
1322
|
+
componentStack.push(component);
|
|
1323
|
+
ts.forEachChild(node, visit);
|
|
1324
|
+
componentStack.pop();
|
|
1325
|
+
return;
|
|
1326
|
+
}
|
|
1327
|
+
if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
|
|
1328
|
+
const target = targetForJsxElement(sourceFile, node, componentStack.at(-1), projectRoot);
|
|
1329
|
+
if (target) targets.push(target);
|
|
1330
|
+
}
|
|
1331
|
+
ts.forEachChild(node, visit);
|
|
1332
|
+
};
|
|
1333
|
+
visit(sourceFile);
|
|
1334
|
+
return targets;
|
|
1335
|
+
}
|
|
1336
|
+
function findJsxMetadataTargets(sourceFile, projectRoot) {
|
|
1337
|
+
const targets = [];
|
|
1338
|
+
const componentStack = [];
|
|
1339
|
+
const visit = (node) => {
|
|
1340
|
+
const component = componentNameForNode(node);
|
|
1341
|
+
if (component) {
|
|
1342
|
+
componentStack.push(component);
|
|
1343
|
+
ts.forEachChild(node, visit);
|
|
1344
|
+
componentStack.pop();
|
|
1345
|
+
return;
|
|
1346
|
+
}
|
|
1347
|
+
if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
|
|
1348
|
+
const existingAttributes = /* @__PURE__ */ new Set();
|
|
1349
|
+
for (const property of node.attributes.properties) if (ts.isJsxAttribute(property) && ts.isIdentifier(property.name)) existingAttributes.add(property.name.text);
|
|
1350
|
+
targets.push({
|
|
1351
|
+
insertPosition: node.getEnd() - (ts.isJsxSelfClosingElement(node) ? 2 : 1),
|
|
1352
|
+
component: componentStack.at(-1),
|
|
1353
|
+
jsxSource: sourceLocationText(sourceFile, node, projectRoot),
|
|
1354
|
+
existingAttributes
|
|
1355
|
+
});
|
|
1356
|
+
}
|
|
1357
|
+
ts.forEachChild(node, visit);
|
|
1358
|
+
};
|
|
1359
|
+
visit(sourceFile);
|
|
1360
|
+
return targets;
|
|
1361
|
+
}
|
|
1362
|
+
function targetForJsxElement(sourceFile, node, component, projectRoot) {
|
|
1363
|
+
const element = jsxTagNameText(node.tagName);
|
|
1364
|
+
const existingAttributes = /* @__PURE__ */ new Set();
|
|
1365
|
+
for (const property of node.attributes.properties) if (ts.isJsxAttribute(property) && ts.isIdentifier(property.name)) existingAttributes.add(property.name.text);
|
|
1366
|
+
for (const property of node.attributes.properties) {
|
|
1367
|
+
if (!ts.isJsxAttribute(property)) continue;
|
|
1368
|
+
if (!ts.isIdentifier(property.name)) continue;
|
|
1369
|
+
if (property.name.text !== "class" && property.name.text !== "className") continue;
|
|
1370
|
+
const expression = property.initializer && jsxAttributeExpression(property.initializer);
|
|
1371
|
+
if (!expression) continue;
|
|
1372
|
+
const objectStart = firstCssObjectLiteralStart(sourceFile, expression);
|
|
1373
|
+
if (objectStart === void 0) continue;
|
|
1374
|
+
return {
|
|
1375
|
+
objectStart,
|
|
1376
|
+
insertPosition: node.getEnd() - (ts.isJsxSelfClosingElement(node) ? 2 : 1),
|
|
1377
|
+
component,
|
|
1378
|
+
jsxSource: sourceLocationText(sourceFile, node, projectRoot),
|
|
1379
|
+
element,
|
|
1380
|
+
attribute: property.name.text,
|
|
1381
|
+
existingAttributes
|
|
1382
|
+
};
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
function jsxAttributeExpression(initializer) {
|
|
1386
|
+
if (ts.isJsxExpression(initializer)) return initializer.expression;
|
|
1387
|
+
}
|
|
1388
|
+
function sourceLocationText(sourceFile, node, projectRoot) {
|
|
1389
|
+
const start = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
|
|
1390
|
+
return `${toRelativeProjectPath$1(sourceFile.fileName, projectRoot)}:${start.line + 1}:${start.character + 1}`;
|
|
1391
|
+
}
|
|
1392
|
+
function firstCssObjectLiteralStart(sourceFile, expression) {
|
|
1393
|
+
let result;
|
|
1394
|
+
const visit = (node) => {
|
|
1395
|
+
if (result !== void 0) return;
|
|
1396
|
+
if (ts.isCallExpression(node) && ts.isObjectLiteralExpression(node.arguments[0])) {
|
|
1397
|
+
result = node.arguments[0].getStart(sourceFile);
|
|
1398
|
+
return;
|
|
1399
|
+
}
|
|
1400
|
+
ts.forEachChild(node, visit);
|
|
1401
|
+
};
|
|
1402
|
+
visit(expression);
|
|
1403
|
+
return result;
|
|
1404
|
+
}
|
|
1405
|
+
function metadataAttributeText(entry, target, attributes) {
|
|
1406
|
+
const source = entry.id.split("#")[0] ?? entry.id;
|
|
1407
|
+
const metadata = [
|
|
1408
|
+
[attributes.editId, entry.id],
|
|
1409
|
+
[attributes.source, source],
|
|
1410
|
+
[attributes.jsxSource, target.jsxSource],
|
|
1411
|
+
[attributes.component, target.component]
|
|
1412
|
+
];
|
|
1413
|
+
let text = "";
|
|
1414
|
+
for (const [name, value] of metadata) {
|
|
1415
|
+
if (!value || target.existingAttributes.has(name)) continue;
|
|
1416
|
+
text += ` ${name}="${escapeAttribute(value)}"`;
|
|
1417
|
+
}
|
|
1418
|
+
return text;
|
|
1419
|
+
}
|
|
1420
|
+
function jsxMetadataAttributeText(target, attributes) {
|
|
1421
|
+
const metadata = [[attributes.jsxSource, target.jsxSource], [attributes.component, target.component]];
|
|
1422
|
+
let text = "";
|
|
1423
|
+
for (const [name, value] of metadata) {
|
|
1424
|
+
if (!value || target.existingAttributes.has(name)) continue;
|
|
1425
|
+
text += ` ${name}="${escapeAttribute(value)}"`;
|
|
1426
|
+
}
|
|
1427
|
+
return text;
|
|
1428
|
+
}
|
|
1429
|
+
function componentNameForNode(node) {
|
|
1430
|
+
if (ts.isFunctionDeclaration(node) && node.name && isComponentName(node.name.text)) return node.name.text;
|
|
1431
|
+
if (!ts.isVariableDeclaration(node)) return void 0;
|
|
1432
|
+
if (!ts.isIdentifier(node.name) || !isComponentName(node.name.text)) return void 0;
|
|
1433
|
+
if (!node.initializer) return void 0;
|
|
1434
|
+
if (!ts.isArrowFunction(node.initializer) && !ts.isFunctionExpression(node.initializer)) return;
|
|
1435
|
+
return node.name.text;
|
|
1436
|
+
}
|
|
1437
|
+
function jsxTagNameText(name) {
|
|
1438
|
+
if (ts.isIdentifier(name)) return name.text;
|
|
1439
|
+
if (ts.isPropertyAccessExpression(name)) return name.name.text;
|
|
1440
|
+
}
|
|
1441
|
+
function isComponentName(name) {
|
|
1442
|
+
return /^[A-Z]/.test(name);
|
|
1443
|
+
}
|
|
1444
|
+
function shouldTransform(filePath, options) {
|
|
1445
|
+
if (filePath.endsWith(".d.ts")) return false;
|
|
1446
|
+
if (!resolveSourceParserAdapter(filePath, options.sourceSyntax).isSupportedFile(filePath)) return false;
|
|
1447
|
+
if ([...DEFAULT_EXCLUDE, ...options.exclude ?? []].some((pattern) => matchesGlob(filePath, pattern))) return false;
|
|
1448
|
+
if (!options.include || options.include.length === 0) return true;
|
|
1449
|
+
return options.include.some((pattern) => matchesGlob(filePath, pattern));
|
|
1450
|
+
}
|
|
1451
|
+
function matchesGlob(filePath, pattern) {
|
|
1452
|
+
const normalizedPattern = normalizePath$1(pattern);
|
|
1453
|
+
let regex = "";
|
|
1454
|
+
for (let index = 0; index < normalizedPattern.length; index += 1) {
|
|
1455
|
+
const char = normalizedPattern[index];
|
|
1456
|
+
const next = normalizedPattern[index + 1];
|
|
1457
|
+
if (char === "*" && next === "*") {
|
|
1458
|
+
if (normalizedPattern[index + 2] === "/") {
|
|
1459
|
+
regex += "(?:.*/)?";
|
|
1460
|
+
index += 2;
|
|
1461
|
+
continue;
|
|
1462
|
+
}
|
|
1463
|
+
regex += ".*";
|
|
1464
|
+
index += 1;
|
|
1465
|
+
continue;
|
|
1466
|
+
}
|
|
1467
|
+
if (char === "*") {
|
|
1468
|
+
regex += "[^/]*";
|
|
1469
|
+
continue;
|
|
1470
|
+
}
|
|
1471
|
+
if (char === "{") {
|
|
1472
|
+
const close = normalizedPattern.indexOf("}", index);
|
|
1473
|
+
if (close !== -1) {
|
|
1474
|
+
regex += `(${normalizedPattern.slice(index + 1, close).split(",").map(escapeRegExp).join("|")})`;
|
|
1475
|
+
index = close;
|
|
1476
|
+
continue;
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
regex += escapeRegExp(char);
|
|
1480
|
+
}
|
|
1481
|
+
return new RegExp(`(^|/)${regex}$`).test(filePath);
|
|
1482
|
+
}
|
|
1483
|
+
function escapeAttribute(value) {
|
|
1484
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
1485
|
+
}
|
|
1486
|
+
function escapeRegExp(value) {
|
|
1487
|
+
return value.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&");
|
|
1488
|
+
}
|
|
1489
|
+
//#endregion
|
|
1490
|
+
//#region src/vite/writebackEndpoints.ts
|
|
1491
|
+
function registerWritebackRoutes(server, options) {
|
|
1492
|
+
server.middlewares.use(DEFAULT_WRITEBACK_ENDPOINT, async (request, response) => {
|
|
1493
|
+
if (request.method && request.method !== "POST") {
|
|
1494
|
+
response.statusCode = 405;
|
|
1495
|
+
response.setHeader("content-type", "application/json");
|
|
1496
|
+
response.setHeader("cache-control", "no-store");
|
|
1497
|
+
response.end(JSON.stringify({
|
|
1498
|
+
ok: false,
|
|
1499
|
+
editId: "",
|
|
1500
|
+
written: false,
|
|
1501
|
+
error: {
|
|
1502
|
+
code: "invalid-edit",
|
|
1503
|
+
message: "Panda inspector writeback requires POST."
|
|
1504
|
+
}
|
|
1505
|
+
}));
|
|
1506
|
+
return;
|
|
1507
|
+
}
|
|
1508
|
+
const requestResult = await readStyleEditRequest(request);
|
|
1509
|
+
if (!requestResult.ok) {
|
|
1510
|
+
response.statusCode = 400;
|
|
1511
|
+
response.setHeader("content-type", "application/json");
|
|
1512
|
+
response.setHeader("cache-control", "no-store");
|
|
1513
|
+
response.end(JSON.stringify(requestResult.response));
|
|
1514
|
+
return;
|
|
1515
|
+
}
|
|
1516
|
+
const result = requestResult.request.kind === "panda-css-inline-source" ? await writeInlineCssSourcePatch({
|
|
1517
|
+
request: requestResult.request,
|
|
1518
|
+
projectRoot: options.projectRoot,
|
|
1519
|
+
cssImportSources: options.cssImportSources,
|
|
1520
|
+
sourceSyntax: options.sourceSyntax,
|
|
1521
|
+
attributes: options.attributes,
|
|
1522
|
+
onManifestEntries: options.onManifestEntries
|
|
1523
|
+
}) : requestResult.request.kind === "panda-css-style-module-source" || requestResult.request.kind === "panda-css-style-module-attach" || requestResult.request.kind === "panda-css-style-module-detach" ? await writeStyleModulePatch({
|
|
1524
|
+
request: requestResult.request,
|
|
1525
|
+
projectRoot: options.projectRoot,
|
|
1526
|
+
cssImportSources: options.cssImportSources,
|
|
1527
|
+
styledSystemPackageName: await inferStyledSystemPackageName(options.projectRoot),
|
|
1528
|
+
attributes: options.attributes,
|
|
1529
|
+
onManifestEntries: options.onManifestEntries
|
|
1530
|
+
}) : requestResult.request.kind === "panda-css-batch" ? await writeStaticCssBatchPatch({
|
|
1531
|
+
manifest: options.manifest(),
|
|
1532
|
+
request: requestResult.request,
|
|
1533
|
+
projectRoot: options.projectRoot,
|
|
1534
|
+
cssImportSources: options.cssImportSources,
|
|
1535
|
+
sourceSyntax: options.sourceSyntax,
|
|
1536
|
+
onManifestEntries: options.onManifestEntries
|
|
1537
|
+
}) : await writeStaticCssPatch({
|
|
1538
|
+
manifest: options.manifest(),
|
|
1539
|
+
request: requestResult.request,
|
|
1540
|
+
projectRoot: options.projectRoot,
|
|
1541
|
+
cssImportSources: options.cssImportSources,
|
|
1542
|
+
sourceSyntax: options.sourceSyntax,
|
|
1543
|
+
onManifestEntries: options.onManifestEntries
|
|
1544
|
+
});
|
|
1545
|
+
response.statusCode = result.ok ? 200 : 400;
|
|
1546
|
+
response.setHeader("content-type", "application/json");
|
|
1547
|
+
response.setHeader("cache-control", "no-store");
|
|
1548
|
+
response.end(JSON.stringify(result));
|
|
1549
|
+
if (result.ok && result.written && result.manifestUpdate) {
|
|
1550
|
+
notifyViteAboutWrittenFiles(server, options.projectRoot, result.manifestUpdate.changedFiles);
|
|
1551
|
+
server.ws?.send(PANDA_INSPECTOR_EVENTS.manifestUpdate, result.manifestUpdate);
|
|
1552
|
+
}
|
|
1553
|
+
});
|
|
1554
|
+
server.middlewares.use(DEFAULT_TOKEN_WRITEBACK_ENDPOINT, async (request, response) => {
|
|
1555
|
+
if (request.method && request.method !== "POST") {
|
|
1556
|
+
response.statusCode = 405;
|
|
1557
|
+
response.setHeader("content-type", "application/json");
|
|
1558
|
+
response.setHeader("cache-control", "no-store");
|
|
1559
|
+
response.end(JSON.stringify(tokenConfigEditFailure("", "invalid-edit", "Panda inspector token writeback requires POST.")));
|
|
1560
|
+
return;
|
|
1561
|
+
}
|
|
1562
|
+
const requestResult = await readTokenConfigEditRequest(request);
|
|
1563
|
+
if (!requestResult.ok) {
|
|
1564
|
+
response.statusCode = 400;
|
|
1565
|
+
response.setHeader("content-type", "application/json");
|
|
1566
|
+
response.setHeader("cache-control", "no-store");
|
|
1567
|
+
response.end(JSON.stringify(requestResult.response));
|
|
1568
|
+
return;
|
|
1569
|
+
}
|
|
1570
|
+
const result = await writeTokenConfigPatch({
|
|
1571
|
+
request: requestResult.request,
|
|
1572
|
+
projectRoot: options.projectRoot,
|
|
1573
|
+
pandaConfigPath: options.pandaConfigPath
|
|
1574
|
+
});
|
|
1575
|
+
response.statusCode = result.ok ? 200 : 400;
|
|
1576
|
+
response.setHeader("content-type", "application/json");
|
|
1577
|
+
response.setHeader("cache-control", "no-store");
|
|
1578
|
+
response.end(JSON.stringify(result));
|
|
1579
|
+
if (result.ok && result.written && result.metadataUpdate) {
|
|
1580
|
+
notifyViteAboutWrittenFiles(server, options.projectRoot, result.metadataUpdate.changedFiles);
|
|
1581
|
+
server.ws?.send(PANDA_INSPECTOR_EVENTS.metadataUpdate, result.metadataUpdate);
|
|
1582
|
+
}
|
|
1583
|
+
});
|
|
1584
|
+
}
|
|
1585
|
+
function notifyViteAboutWrittenFiles(server, projectRoot, changedFiles) {
|
|
1586
|
+
for (const changedFile of changedFiles) {
|
|
1587
|
+
const absoluteFile = normalizePath$1(`${projectRoot.replace(/\/$/, "")}/${changedFile}`);
|
|
1588
|
+
const modules = server.moduleGraph?.getModulesByFile?.(absoluteFile);
|
|
1589
|
+
if (modules) for (const module of modules) server.moduleGraph?.invalidateModule?.(module);
|
|
1590
|
+
server.watcher?.emit?.("change", absoluteFile);
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
async function readStyleEditRequest(request) {
|
|
1594
|
+
try {
|
|
1595
|
+
const body = await readRequestBody(request);
|
|
1596
|
+
const parsed = JSON.parse(body);
|
|
1597
|
+
if (!isStyleEditRequest(parsed) && !isStyleEditBatchRequest(parsed) && !isInlineCssSourceCreateRequest(parsed) && !isStyleModuleEditRequest(parsed)) return {
|
|
1598
|
+
ok: false,
|
|
1599
|
+
response: styleEditFailure("", "invalid-edit", "Request body is not a valid style edit request.")
|
|
1600
|
+
};
|
|
1601
|
+
return {
|
|
1602
|
+
ok: true,
|
|
1603
|
+
request: parsed
|
|
1604
|
+
};
|
|
1605
|
+
} catch (error) {
|
|
1606
|
+
return {
|
|
1607
|
+
ok: false,
|
|
1608
|
+
response: styleEditFailure("", "invalid-edit", `Failed to read style edit request: ${error instanceof Error ? error.message : String(error)}`)
|
|
1609
|
+
};
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
async function readTokenConfigEditRequest(request) {
|
|
1613
|
+
try {
|
|
1614
|
+
const body = await readRequestBody(request);
|
|
1615
|
+
const parsed = JSON.parse(body);
|
|
1616
|
+
if (!isTokenConfigEditRequest(parsed)) return {
|
|
1617
|
+
ok: false,
|
|
1618
|
+
response: tokenConfigEditFailure("", "invalid-edit", "Request body is not a valid token config edit request.")
|
|
1619
|
+
};
|
|
1620
|
+
return {
|
|
1621
|
+
ok: true,
|
|
1622
|
+
request: parsed
|
|
1623
|
+
};
|
|
1624
|
+
} catch (error) {
|
|
1625
|
+
return {
|
|
1626
|
+
ok: false,
|
|
1627
|
+
response: tokenConfigEditFailure("", "invalid-edit", `Failed to read token config edit request: ${error instanceof Error ? error.message : String(error)}`)
|
|
1628
|
+
};
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
async function readRequestBody(request) {
|
|
1632
|
+
if (!request[Symbol.asyncIterator]) return "";
|
|
1633
|
+
let body = "";
|
|
1634
|
+
for await (const chunk of request) body += typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
1635
|
+
return body;
|
|
1636
|
+
}
|
|
1637
|
+
function isStyleEditRequest(value) {
|
|
1638
|
+
if (!isRecord(value)) return false;
|
|
1639
|
+
if (typeof value.editId !== "string" || value.editId.length === 0) return false;
|
|
1640
|
+
if (value.kind !== "panda-css") return false;
|
|
1641
|
+
if (!Array.isArray(value.edits) || value.edits.length === 0) return false;
|
|
1642
|
+
return value.edits.every((edit) => {
|
|
1643
|
+
if (!isRecord(edit)) return false;
|
|
1644
|
+
if (edit.op === "set") return isPath(edit.path) && isJsonValue(edit.value);
|
|
1645
|
+
if (edit.op === "delete") return isPath(edit.path);
|
|
1646
|
+
if (edit.op === "rename") return isPath(edit.from) && isPath(edit.to);
|
|
1647
|
+
if (edit.op === "replace-object") return isRecord(edit.value);
|
|
1648
|
+
return false;
|
|
1649
|
+
});
|
|
1650
|
+
}
|
|
1651
|
+
function isStyleEditBatchRequest(value) {
|
|
1652
|
+
if (!isRecord(value)) return false;
|
|
1653
|
+
if (value.kind !== "panda-css-batch") return false;
|
|
1654
|
+
if (!Array.isArray(value.requests) || value.requests.length === 0) return false;
|
|
1655
|
+
return value.requests.every(isStyleEditRequest);
|
|
1656
|
+
}
|
|
1657
|
+
function isInlineCssSourceCreateRequest(value) {
|
|
1658
|
+
if (!isRecord(value)) return false;
|
|
1659
|
+
if (typeof value.editId !== "string" || value.editId.length === 0) return false;
|
|
1660
|
+
if (value.kind !== "panda-css-inline-source") return false;
|
|
1661
|
+
if (typeof value.jsxSource !== "string" || value.jsxSource.length === 0) return false;
|
|
1662
|
+
return value.options === void 0 || isRecord(value.options);
|
|
1663
|
+
}
|
|
1664
|
+
function isStyleModuleEditRequest(value) {
|
|
1665
|
+
return isStyleModuleSourceCreateRequest(value) || isStyleModuleSourceAttachRequest(value) || isStyleModuleSourceDetachRequest(value);
|
|
1666
|
+
}
|
|
1667
|
+
function isStyleModuleSourceCreateRequest(value) {
|
|
1668
|
+
if (!isRecord(value)) return false;
|
|
1669
|
+
if (typeof value.editId !== "string" || value.editId.length === 0) return false;
|
|
1670
|
+
if (value.kind !== "panda-css-style-module-source") return false;
|
|
1671
|
+
if (typeof value.componentSource !== "string" || value.componentSource.length === 0) return false;
|
|
1672
|
+
if (typeof value.name !== "string" || value.name.length === 0) return false;
|
|
1673
|
+
if (value.edits !== void 0) {
|
|
1674
|
+
if (!Array.isArray(value.edits)) return false;
|
|
1675
|
+
if (!value.edits.every((edit) => {
|
|
1676
|
+
if (!isRecord(edit)) return false;
|
|
1677
|
+
if (edit.op === "set") return isPath(edit.path) && isJsonValue(edit.value);
|
|
1678
|
+
if (edit.op === "delete") return isPath(edit.path);
|
|
1679
|
+
return false;
|
|
1680
|
+
})) return false;
|
|
1681
|
+
}
|
|
1682
|
+
return value.options === void 0 || isRecord(value.options);
|
|
1683
|
+
}
|
|
1684
|
+
function isStyleModuleSourceAttachRequest(value) {
|
|
1685
|
+
if (!isRecord(value)) return false;
|
|
1686
|
+
if (typeof value.editId !== "string" || value.editId.length === 0) return false;
|
|
1687
|
+
if (value.kind !== "panda-css-style-module-attach") return false;
|
|
1688
|
+
if (typeof value.jsxSource !== "string" || value.jsxSource.length === 0) return false;
|
|
1689
|
+
if (typeof value.componentSource !== "string" || value.componentSource.length === 0) return false;
|
|
1690
|
+
if (typeof value.name !== "string" || value.name.length === 0) return false;
|
|
1691
|
+
return value.options === void 0 || isRecord(value.options);
|
|
1692
|
+
}
|
|
1693
|
+
function isStyleModuleSourceDetachRequest(value) {
|
|
1694
|
+
if (!isRecord(value)) return false;
|
|
1695
|
+
if (typeof value.editId !== "string" || value.editId.length === 0) return false;
|
|
1696
|
+
if (value.kind !== "panda-css-style-module-detach") return false;
|
|
1697
|
+
if (typeof value.jsxSource !== "string" || value.jsxSource.length === 0) return false;
|
|
1698
|
+
if (typeof value.componentSource !== "string" || value.componentSource.length === 0) return false;
|
|
1699
|
+
if (typeof value.name !== "string" || value.name.length === 0) return false;
|
|
1700
|
+
return value.options === void 0 || isRecord(value.options);
|
|
1701
|
+
}
|
|
1702
|
+
function isTokenConfigEditRequest(value) {
|
|
1703
|
+
if (!isRecord(value)) return false;
|
|
1704
|
+
if (typeof value.editId !== "string" || value.editId.length === 0) return false;
|
|
1705
|
+
if (value.kind !== "panda-token-config") return false;
|
|
1706
|
+
if (typeof value.sourceTargetId !== "string" || value.sourceTargetId.length === 0) return false;
|
|
1707
|
+
if (value.section !== "tokens.colors" && value.section !== "semanticTokens.colors") return false;
|
|
1708
|
+
if (!isPath(value.path)) return false;
|
|
1709
|
+
if (!isJsonPrimitive(value.value)) return false;
|
|
1710
|
+
return value.options === void 0 || isRecord(value.options);
|
|
1711
|
+
}
|
|
1712
|
+
function styleEditBatchFailure(response) {
|
|
1713
|
+
return {
|
|
1714
|
+
ok: false,
|
|
1715
|
+
editId: "",
|
|
1716
|
+
responses: [response],
|
|
1717
|
+
written: false,
|
|
1718
|
+
error: response.error
|
|
1719
|
+
};
|
|
1720
|
+
}
|
|
1721
|
+
function isNewEmptyInlineSourceEntry(entry) {
|
|
1722
|
+
return entry.kind === "panda-css" && (entry.attribute === "class" || entry.attribute === "className") && Object.keys(entry.styleObject).length === 0;
|
|
1723
|
+
}
|
|
1724
|
+
async function writeInlineCssSourcePatch(options) {
|
|
1725
|
+
const parsed = parseJsxSourceFile(options.request.jsxSource);
|
|
1726
|
+
if (!parsed.ok) return styleEditFailure(options.request.editId, parsed.code, parsed.message, parsed.details);
|
|
1727
|
+
const filePath = safeProjectSourcePath(options.projectRoot, parsed.file);
|
|
1728
|
+
if (!filePath.ok) return styleEditFailure(options.request.editId, filePath.code, filePath.message, filePath.details);
|
|
1729
|
+
let sourceText;
|
|
1730
|
+
try {
|
|
1731
|
+
sourceText = await readFile(filePath.file, "utf8");
|
|
1732
|
+
} catch (error) {
|
|
1733
|
+
return styleEditFailure(options.request.editId, "write-failed", `Failed to read source file before inline source creation: ${error instanceof Error ? error.message : String(error)}`);
|
|
1734
|
+
}
|
|
1735
|
+
const patch = createInlineCssSourcePatch({
|
|
1736
|
+
projectRoot: options.projectRoot,
|
|
1737
|
+
request: {
|
|
1738
|
+
...options.request,
|
|
1739
|
+
options: {
|
|
1740
|
+
...options.request.options,
|
|
1741
|
+
write: true
|
|
1742
|
+
}
|
|
1743
|
+
},
|
|
1744
|
+
sourceText,
|
|
1745
|
+
filePath: filePath.file,
|
|
1746
|
+
cssImportSources: options.cssImportSources,
|
|
1747
|
+
sourceSyntax: options.sourceSyntax
|
|
1748
|
+
});
|
|
1749
|
+
if (!patch.ok || !patch.nextSource) return patch;
|
|
1750
|
+
if (options.request.options?.write !== true) return patch;
|
|
1751
|
+
try {
|
|
1752
|
+
await writeFile(filePath.file, patch.nextSource, "utf8");
|
|
1753
|
+
} catch (error) {
|
|
1754
|
+
return styleEditFailure(options.request.editId, "write-failed", `Failed to write source file: ${error instanceof Error ? error.message : String(error)}`);
|
|
1755
|
+
}
|
|
1756
|
+
const nextEntries = transformTsxSource({
|
|
1757
|
+
sourceText: patch.nextSource,
|
|
1758
|
+
filePath: filePath.file,
|
|
1759
|
+
projectRoot: options.projectRoot,
|
|
1760
|
+
attributes: options.attributes,
|
|
1761
|
+
cssImportSources: options.cssImportSources,
|
|
1762
|
+
sourceSyntax: options.sourceSyntax
|
|
1763
|
+
}).entries.map((entry) => isNewEmptyInlineSourceEntry(entry) ? {
|
|
1764
|
+
...entry,
|
|
1765
|
+
jsxSourceAliases: Array.from(new Set([...entry.jsxSourceAliases ?? [], options.request.jsxSource]))
|
|
1766
|
+
} : entry);
|
|
1767
|
+
options.onManifestEntries(filePath.file, nextEntries);
|
|
1768
|
+
const manifestUpdate = {
|
|
1769
|
+
version: 1,
|
|
1770
|
+
changedFiles: [toRelativeProjectPath$1(filePath.file, options.projectRoot)],
|
|
1771
|
+
entryIds: nextEntries.map((nextEntry) => nextEntry.id)
|
|
1772
|
+
};
|
|
1773
|
+
return {
|
|
1774
|
+
...patch,
|
|
1775
|
+
written: true,
|
|
1776
|
+
manifestUpdate
|
|
1777
|
+
};
|
|
1778
|
+
}
|
|
1779
|
+
async function writeStyleModulePatch(options) {
|
|
1780
|
+
const paths = componentStyleModulePaths({
|
|
1781
|
+
projectRoot: options.projectRoot,
|
|
1782
|
+
componentSource: options.request.componentSource
|
|
1783
|
+
});
|
|
1784
|
+
if (!paths.ok) return styleEditFailure(options.request.editId, paths.code, paths.message, paths.details);
|
|
1785
|
+
const write = options.request.options?.write === true;
|
|
1786
|
+
if (options.request.kind === "panda-css-style-module-source") {
|
|
1787
|
+
let sourceText;
|
|
1788
|
+
try {
|
|
1789
|
+
sourceText = await readFile(paths.paths.styleFile, "utf8");
|
|
1790
|
+
} catch (error) {
|
|
1791
|
+
if (!isMissingFileError(error)) return styleEditFailure(options.request.editId, "write-failed", `Failed to read style module before writeback: ${error instanceof Error ? error.message : String(error)}`);
|
|
1792
|
+
}
|
|
1793
|
+
const patch = createStyleModuleSourcePatch({
|
|
1794
|
+
projectRoot: options.projectRoot,
|
|
1795
|
+
request: {
|
|
1796
|
+
...options.request,
|
|
1797
|
+
options: {
|
|
1798
|
+
...options.request.options,
|
|
1799
|
+
write
|
|
1800
|
+
}
|
|
1801
|
+
},
|
|
1802
|
+
sourceText,
|
|
1803
|
+
filePath: paths.paths.styleFile,
|
|
1804
|
+
cssImportSources: options.cssImportSources
|
|
1805
|
+
});
|
|
1806
|
+
if (!patch.ok || !patch.nextSource) return patch;
|
|
1807
|
+
if (!write) return patch;
|
|
1808
|
+
try {
|
|
1809
|
+
await mkdir(dirname(paths.paths.styleFile), { recursive: true });
|
|
1810
|
+
await writeFile(paths.paths.styleFile, patch.nextSource, "utf8");
|
|
1811
|
+
} catch (error) {
|
|
1812
|
+
return styleEditFailure(options.request.editId, "write-failed", `Failed to write style module: ${error instanceof Error ? error.message : String(error)}`);
|
|
1813
|
+
}
|
|
1814
|
+
const nextEntries = analyzePandaCssSource({
|
|
1815
|
+
sourceText: patch.nextSource,
|
|
1816
|
+
filePath: paths.paths.styleFile,
|
|
1817
|
+
projectRoot: options.projectRoot,
|
|
1818
|
+
cssImportSources: options.cssImportSources
|
|
1819
|
+
}).entries;
|
|
1820
|
+
options.onManifestEntries(paths.paths.styleFile, nextEntries);
|
|
1821
|
+
const manifestUpdate = {
|
|
1822
|
+
version: 1,
|
|
1823
|
+
changedFiles: [paths.paths.styleFileRelative],
|
|
1824
|
+
entryIds: nextEntries.map((nextEntry) => nextEntry.id)
|
|
1825
|
+
};
|
|
1826
|
+
return {
|
|
1827
|
+
...patch,
|
|
1828
|
+
written: true,
|
|
1829
|
+
manifestUpdate
|
|
1830
|
+
};
|
|
1831
|
+
}
|
|
1832
|
+
let componentSourceText;
|
|
1833
|
+
try {
|
|
1834
|
+
componentSourceText = await readFile(paths.paths.componentFile, "utf8");
|
|
1835
|
+
} catch (error) {
|
|
1836
|
+
return styleEditFailure(options.request.editId, "write-failed", `Failed to read component module before style attachment: ${error instanceof Error ? error.message : String(error)}`);
|
|
1837
|
+
}
|
|
1838
|
+
let styleSourceText;
|
|
1839
|
+
try {
|
|
1840
|
+
styleSourceText = await readFile(paths.paths.styleFile, "utf8");
|
|
1841
|
+
} catch (error) {
|
|
1842
|
+
return styleEditFailure(options.request.editId, isMissingFileError(error) ? "manifest-entry-not-found" : "write-failed", isMissingFileError(error) ? "Style module does not exist yet." : `Failed to read style module before attachment: ${error instanceof Error ? error.message : String(error)}`);
|
|
1843
|
+
}
|
|
1844
|
+
const patch = options.request.kind === "panda-css-style-module-attach" ? createStyleModuleAttachPatch({
|
|
1845
|
+
projectRoot: options.projectRoot,
|
|
1846
|
+
request: {
|
|
1847
|
+
...options.request,
|
|
1848
|
+
options: {
|
|
1849
|
+
...options.request.options,
|
|
1850
|
+
write
|
|
1851
|
+
}
|
|
1852
|
+
},
|
|
1853
|
+
sourceText: componentSourceText,
|
|
1854
|
+
filePath: paths.paths.componentFile,
|
|
1855
|
+
styledSystemPackageName: options.styledSystemPackageName
|
|
1856
|
+
}) : createStyleModuleDetachPatch({
|
|
1857
|
+
projectRoot: options.projectRoot,
|
|
1858
|
+
request: {
|
|
1859
|
+
...options.request,
|
|
1860
|
+
options: {
|
|
1861
|
+
...options.request.options,
|
|
1862
|
+
write
|
|
1863
|
+
}
|
|
1864
|
+
},
|
|
1865
|
+
sourceText: componentSourceText,
|
|
1866
|
+
filePath: paths.paths.componentFile
|
|
1867
|
+
});
|
|
1868
|
+
if (!patch.ok || !patch.nextSource) return patch;
|
|
1869
|
+
if (!write) return patch;
|
|
1870
|
+
try {
|
|
1871
|
+
await writeFile(paths.paths.componentFile, patch.nextSource, "utf8");
|
|
1872
|
+
} catch (error) {
|
|
1873
|
+
return styleEditFailure(options.request.editId, "write-failed", `Failed to write component module: ${error instanceof Error ? error.message : String(error)}`);
|
|
1874
|
+
}
|
|
1875
|
+
const componentEntries = transformTsxSource({
|
|
1876
|
+
sourceText: patch.nextSource,
|
|
1877
|
+
filePath: paths.paths.componentFile,
|
|
1878
|
+
projectRoot: options.projectRoot,
|
|
1879
|
+
attributes: options.attributes,
|
|
1880
|
+
cssImportSources: options.cssImportSources
|
|
1881
|
+
}).entries;
|
|
1882
|
+
const analyzedStyleEntries = analyzePandaCssSource({
|
|
1883
|
+
sourceText: styleSourceText,
|
|
1884
|
+
filePath: paths.paths.styleFile,
|
|
1885
|
+
projectRoot: options.projectRoot,
|
|
1886
|
+
cssImportSources: options.cssImportSources
|
|
1887
|
+
}).entries;
|
|
1888
|
+
const styleEntries = styleModuleEntriesWithJsxAlias({
|
|
1889
|
+
entries: analyzedStyleEntries,
|
|
1890
|
+
request: options.request
|
|
1891
|
+
});
|
|
1892
|
+
options.onManifestEntries(paths.paths.componentFile, componentEntries);
|
|
1893
|
+
options.onManifestEntries(paths.paths.styleFile, styleEntries);
|
|
1894
|
+
const manifestUpdate = {
|
|
1895
|
+
version: 1,
|
|
1896
|
+
changedFiles: [toRelativeProjectPath$1(paths.paths.componentFile, options.projectRoot), paths.paths.styleFileRelative],
|
|
1897
|
+
entryIds: [...componentEntries, ...styleEntries].map((nextEntry) => nextEntry.id)
|
|
1898
|
+
};
|
|
1899
|
+
return {
|
|
1900
|
+
...patch,
|
|
1901
|
+
written: true,
|
|
1902
|
+
manifestUpdate
|
|
1903
|
+
};
|
|
1904
|
+
}
|
|
1905
|
+
function styleModuleEntriesWithJsxAlias(options) {
|
|
1906
|
+
return options.entries.map((entry) => {
|
|
1907
|
+
if (entry.name !== options.request.name) return entry;
|
|
1908
|
+
if (options.request.kind === "panda-css-style-module-attach") return {
|
|
1909
|
+
...entry,
|
|
1910
|
+
jsxSourceAliases: Array.from(new Set([...entry.jsxSourceAliases ?? [], options.request.jsxSource]))
|
|
1911
|
+
};
|
|
1912
|
+
const nextAliases = (entry.jsxSourceAliases ?? []).filter((source) => source !== options.request.jsxSource);
|
|
1913
|
+
const { jsxSourceAliases: _removed, ...entryWithoutAliases } = entry;
|
|
1914
|
+
return nextAliases.length === 0 ? entryWithoutAliases : {
|
|
1915
|
+
...entry,
|
|
1916
|
+
jsxSourceAliases: nextAliases
|
|
1917
|
+
};
|
|
1918
|
+
});
|
|
1919
|
+
}
|
|
1920
|
+
async function writeStaticCssPatch(options) {
|
|
1921
|
+
const entry = options.manifest.entries.find((item) => item.id === options.request.editId);
|
|
1922
|
+
if (!entry) return styleEditFailure(options.request.editId, "manifest-entry-not-found", "No manifest entry exists for edit id.");
|
|
1923
|
+
const filePath = trustedManifestFilePath(options.manifest, entry);
|
|
1924
|
+
if (!filePath.ok) return styleEditFailure(options.request.editId, filePath.code, filePath.message, filePath.details);
|
|
1925
|
+
let sourceText;
|
|
1926
|
+
try {
|
|
1927
|
+
sourceText = await readFile(filePath.file, "utf8");
|
|
1928
|
+
} catch (error) {
|
|
1929
|
+
return styleEditFailure(options.request.editId, "write-failed", `Failed to read source file before writeback: ${error instanceof Error ? error.message : String(error)}`);
|
|
1930
|
+
}
|
|
1931
|
+
const patch = createStaticCssPatch({
|
|
1932
|
+
manifest: options.manifest,
|
|
1933
|
+
request: {
|
|
1934
|
+
...options.request,
|
|
1935
|
+
options: {
|
|
1936
|
+
...options.request.options,
|
|
1937
|
+
write: true
|
|
1938
|
+
}
|
|
1939
|
+
},
|
|
1940
|
+
sourceText,
|
|
1941
|
+
filePath: filePath.file,
|
|
1942
|
+
styledSystemPackageName: await inferStyledSystemPackageName(options.projectRoot),
|
|
1943
|
+
sourceSyntax: options.sourceSyntax
|
|
1944
|
+
});
|
|
1945
|
+
if (!patch.ok || !patch.nextSource) return patch;
|
|
1946
|
+
if (options.request.options?.write !== true) return patch;
|
|
1947
|
+
try {
|
|
1948
|
+
await writeFile(filePath.file, patch.nextSource, "utf8");
|
|
1949
|
+
} catch (error) {
|
|
1950
|
+
return styleEditFailure(options.request.editId, "write-failed", `Failed to write source file: ${error instanceof Error ? error.message : String(error)}`);
|
|
1951
|
+
}
|
|
1952
|
+
const nextEntries = analyzePandaCssSource({
|
|
1953
|
+
sourceText: patch.nextSource,
|
|
1954
|
+
filePath: filePath.file,
|
|
1955
|
+
projectRoot: options.projectRoot,
|
|
1956
|
+
cssImportSources: options.cssImportSources,
|
|
1957
|
+
sourceSyntax: options.sourceSyntax
|
|
1958
|
+
}).entries;
|
|
1959
|
+
options.onManifestEntries(filePath.file, nextEntries);
|
|
1960
|
+
const manifestUpdate = {
|
|
1961
|
+
version: 1,
|
|
1962
|
+
changedFiles: [toRelativeProjectPath$1(filePath.file, options.projectRoot)],
|
|
1963
|
+
entryIds: nextEntries.map((nextEntry) => nextEntry.id)
|
|
1964
|
+
};
|
|
1965
|
+
return {
|
|
1966
|
+
...patch,
|
|
1967
|
+
written: true,
|
|
1968
|
+
manifestUpdate
|
|
1969
|
+
};
|
|
1970
|
+
}
|
|
1971
|
+
async function writeStaticCssBatchPatch(options) {
|
|
1972
|
+
const write = options.request.options?.write === true;
|
|
1973
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1974
|
+
for (const request of options.request.requests) {
|
|
1975
|
+
const entry = options.manifest.entries.find((item) => item.id === request.editId);
|
|
1976
|
+
if (!entry) return styleEditBatchFailure(styleEditFailure(request.editId, "manifest-entry-not-found", "No manifest entry exists for edit id."));
|
|
1977
|
+
const filePath = trustedManifestFilePath(options.manifest, entry);
|
|
1978
|
+
if (!filePath.ok) return styleEditBatchFailure(styleEditFailure(request.editId, filePath.code, filePath.message, filePath.details));
|
|
1979
|
+
const changedFile = toRelativeProjectPath$1(filePath.file, options.projectRoot);
|
|
1980
|
+
const group = groups.get(filePath.file);
|
|
1981
|
+
if (group) group.requests.push(request);
|
|
1982
|
+
else groups.set(filePath.file, {
|
|
1983
|
+
file: filePath.file,
|
|
1984
|
+
changedFile,
|
|
1985
|
+
requests: [request]
|
|
1986
|
+
});
|
|
1987
|
+
}
|
|
1988
|
+
const prepared = [];
|
|
1989
|
+
for (const group of groups.values()) {
|
|
1990
|
+
let sourceText;
|
|
1991
|
+
try {
|
|
1992
|
+
sourceText = await readFile(group.file, "utf8");
|
|
1993
|
+
} catch (error) {
|
|
1994
|
+
return styleEditBatchFailure(styleEditFailure(group.requests[0]?.editId ?? "", "write-failed", `Failed to read source file before writeback: ${error instanceof Error ? error.message : String(error)}`));
|
|
1995
|
+
}
|
|
1996
|
+
const patch = createStaticCssBatchPatch({
|
|
1997
|
+
manifest: options.manifest,
|
|
1998
|
+
requests: group.requests.map((request) => ({
|
|
1999
|
+
...request,
|
|
2000
|
+
options: {
|
|
2001
|
+
...request.options,
|
|
2002
|
+
write
|
|
2003
|
+
}
|
|
2004
|
+
})),
|
|
2005
|
+
sourceText,
|
|
2006
|
+
filePath: group.file,
|
|
2007
|
+
styledSystemPackageName: await inferStyledSystemPackageName(options.projectRoot),
|
|
2008
|
+
sourceSyntax: options.sourceSyntax
|
|
2009
|
+
});
|
|
2010
|
+
if (!patch.ok || !patch.nextSource) return styleEditBatchFailure(patch);
|
|
2011
|
+
prepared.push({
|
|
2012
|
+
file: group.file,
|
|
2013
|
+
changedFile: group.changedFile,
|
|
2014
|
+
requests: group.requests,
|
|
2015
|
+
nextSource: patch.nextSource
|
|
2016
|
+
});
|
|
2017
|
+
}
|
|
2018
|
+
const changedFiles = prepared.map((item) => item.changedFile);
|
|
2019
|
+
const entryIds = [];
|
|
2020
|
+
if (write) for (const item of prepared) {
|
|
2021
|
+
try {
|
|
2022
|
+
await writeFile(item.file, item.nextSource, "utf8");
|
|
2023
|
+
} catch (error) {
|
|
2024
|
+
return styleEditBatchFailure(styleEditFailure(item.requests[0]?.editId ?? "", "write-failed", `Failed to write source file: ${error instanceof Error ? error.message : String(error)}`));
|
|
2025
|
+
}
|
|
2026
|
+
const nextEntries = analyzePandaCssSource({
|
|
2027
|
+
sourceText: item.nextSource,
|
|
2028
|
+
filePath: item.file,
|
|
2029
|
+
projectRoot: options.projectRoot,
|
|
2030
|
+
cssImportSources: options.cssImportSources,
|
|
2031
|
+
sourceSyntax: options.sourceSyntax
|
|
2032
|
+
}).entries;
|
|
2033
|
+
options.onManifestEntries(item.file, nextEntries);
|
|
2034
|
+
entryIds.push(...nextEntries.map((nextEntry) => nextEntry.id));
|
|
2035
|
+
}
|
|
2036
|
+
const manifestUpdate = write ? {
|
|
2037
|
+
version: 1,
|
|
2038
|
+
changedFiles,
|
|
2039
|
+
entryIds
|
|
2040
|
+
} : void 0;
|
|
2041
|
+
const fileByEditId = /* @__PURE__ */ new Map();
|
|
2042
|
+
for (const item of prepared) for (const request of item.requests) fileByEditId.set(request.editId, item.changedFile);
|
|
2043
|
+
return {
|
|
2044
|
+
ok: true,
|
|
2045
|
+
editId: "",
|
|
2046
|
+
written: write,
|
|
2047
|
+
manifestUpdate,
|
|
2048
|
+
responses: options.request.requests.map((request) => ({
|
|
2049
|
+
ok: true,
|
|
2050
|
+
editId: request.editId,
|
|
2051
|
+
file: fileByEditId.get(request.editId),
|
|
2052
|
+
written: write,
|
|
2053
|
+
manifestUpdate
|
|
2054
|
+
}))
|
|
2055
|
+
};
|
|
2056
|
+
}
|
|
2057
|
+
async function writeTokenConfigPatch(options) {
|
|
2058
|
+
const metadata = await createEditorMetadata({
|
|
2059
|
+
projectRoot: options.projectRoot,
|
|
2060
|
+
pandaConfigPath: options.pandaConfigPath
|
|
2061
|
+
});
|
|
2062
|
+
if (metadata.tokenSources.status !== "available") return tokenConfigEditFailure(options.request.editId, "unsupported-source-shape", metadata.tokenSources.message);
|
|
2063
|
+
const tokenSource = metadata.tokenSources.items.find((item) => item.id === options.request.sourceTargetId);
|
|
2064
|
+
if (!tokenSource) return tokenConfigEditFailure(options.request.editId, "manifest-entry-not-found", "No token source exists for source target id.", { sourceTargetId: options.request.sourceTargetId });
|
|
2065
|
+
const filePath = trustedTokenSourceFilePath(options.projectRoot, tokenSource);
|
|
2066
|
+
if (!filePath.ok) return tokenConfigEditFailure(options.request.editId, filePath.code, filePath.message, filePath.details);
|
|
2067
|
+
let sourceText;
|
|
2068
|
+
try {
|
|
2069
|
+
sourceText = await readFile(filePath.file, "utf8");
|
|
2070
|
+
} catch (error) {
|
|
2071
|
+
return tokenConfigEditFailure(options.request.editId, "write-failed", `Failed to read Panda config before token writeback: ${error instanceof Error ? error.message : String(error)}`);
|
|
2072
|
+
}
|
|
2073
|
+
const write = options.request.options?.write === true;
|
|
2074
|
+
const patch = createTokenConfigPatch({
|
|
2075
|
+
projectRoot: options.projectRoot,
|
|
2076
|
+
tokenSource,
|
|
2077
|
+
request: {
|
|
2078
|
+
...options.request,
|
|
2079
|
+
options: {
|
|
2080
|
+
...options.request.options,
|
|
2081
|
+
write
|
|
2082
|
+
}
|
|
2083
|
+
},
|
|
2084
|
+
sourceText,
|
|
2085
|
+
filePath: filePath.file
|
|
2086
|
+
});
|
|
2087
|
+
if (!patch.ok || !patch.nextSource) return patch;
|
|
2088
|
+
if (!write) return patch;
|
|
2089
|
+
try {
|
|
2090
|
+
await writeFile(filePath.file, patch.nextSource, "utf8");
|
|
2091
|
+
} catch (error) {
|
|
2092
|
+
return tokenConfigEditFailure(options.request.editId, "write-failed", `Failed to write Panda config: ${error instanceof Error ? error.message : String(error)}`);
|
|
2093
|
+
}
|
|
2094
|
+
const nextMetadata = await createEditorMetadata({
|
|
2095
|
+
projectRoot: options.projectRoot,
|
|
2096
|
+
pandaConfigPath: options.pandaConfigPath
|
|
2097
|
+
});
|
|
2098
|
+
const metadataUpdate = {
|
|
2099
|
+
version: 1,
|
|
2100
|
+
changedFiles: [toRelativeProjectPath$1(filePath.file, options.projectRoot)],
|
|
2101
|
+
tokenSourceIds: nextMetadata.tokenSources.status === "available" ? nextMetadata.tokenSources.items.map((item) => item.id) : []
|
|
2102
|
+
};
|
|
2103
|
+
return {
|
|
2104
|
+
...patch,
|
|
2105
|
+
written: true,
|
|
2106
|
+
metadataUpdate
|
|
2107
|
+
};
|
|
2108
|
+
}
|
|
2109
|
+
async function inferStyledSystemPackageName(projectRoot) {
|
|
2110
|
+
try {
|
|
2111
|
+
const packageText = await readFile(`${projectRoot.replace(/\/$/, "")}/styled-system/package.json`, "utf8");
|
|
2112
|
+
const parsed = JSON.parse(packageText);
|
|
2113
|
+
return typeof parsed.name === "string" && parsed.name.trim() ? parsed.name : void 0;
|
|
2114
|
+
} catch {
|
|
2115
|
+
return;
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
function styleEditFailure(editId, code, message, details) {
|
|
2119
|
+
return {
|
|
2120
|
+
ok: false,
|
|
2121
|
+
editId,
|
|
2122
|
+
written: false,
|
|
2123
|
+
error: {
|
|
2124
|
+
code,
|
|
2125
|
+
message,
|
|
2126
|
+
details
|
|
2127
|
+
}
|
|
2128
|
+
};
|
|
2129
|
+
}
|
|
2130
|
+
function tokenConfigEditFailure(editId, code, message, details) {
|
|
2131
|
+
return {
|
|
2132
|
+
ok: false,
|
|
2133
|
+
editId,
|
|
2134
|
+
written: false,
|
|
2135
|
+
error: {
|
|
2136
|
+
code,
|
|
2137
|
+
message,
|
|
2138
|
+
details
|
|
2139
|
+
}
|
|
2140
|
+
};
|
|
2141
|
+
}
|
|
2142
|
+
function parseJsxSourceFile(source) {
|
|
2143
|
+
const match = /^(.*):\d+:\d+$/.exec(source.trim());
|
|
2144
|
+
const file = match?.[1]?.trim();
|
|
2145
|
+
if (!match || !file) return {
|
|
2146
|
+
ok: false,
|
|
2147
|
+
code: "invalid-edit",
|
|
2148
|
+
message: "Inline source creation requires a JSX source path with line and column.",
|
|
2149
|
+
details: { source }
|
|
2150
|
+
};
|
|
2151
|
+
return {
|
|
2152
|
+
ok: true,
|
|
2153
|
+
file
|
|
2154
|
+
};
|
|
2155
|
+
}
|
|
2156
|
+
function isRecord(value) {
|
|
2157
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2158
|
+
}
|
|
2159
|
+
function isMissingFileError(error) {
|
|
2160
|
+
return isRecord(error) && error.code === "ENOENT";
|
|
2161
|
+
}
|
|
2162
|
+
function isPath(value) {
|
|
2163
|
+
return Array.isArray(value) && value.every((part) => typeof part === "string" && part.length > 0);
|
|
2164
|
+
}
|
|
2165
|
+
function isJsonValue(value) {
|
|
2166
|
+
if (value === null) return true;
|
|
2167
|
+
if ([
|
|
2168
|
+
"string",
|
|
2169
|
+
"number",
|
|
2170
|
+
"boolean"
|
|
2171
|
+
].includes(typeof value)) return true;
|
|
2172
|
+
if (Array.isArray(value)) return value.every(isJsonValue);
|
|
2173
|
+
if (!isRecord(value)) return false;
|
|
2174
|
+
return Object.values(value).every(isJsonValue);
|
|
2175
|
+
}
|
|
2176
|
+
function isJsonPrimitive(value) {
|
|
2177
|
+
return value === null || [
|
|
2178
|
+
"string",
|
|
2179
|
+
"number",
|
|
2180
|
+
"boolean"
|
|
2181
|
+
].includes(typeof value);
|
|
2182
|
+
}
|
|
2183
|
+
//#endregion
|
|
2184
|
+
//#region src/vite.ts
|
|
2185
|
+
function preactPandaInspector(options = {}) {
|
|
2186
|
+
const manifestByFile = /* @__PURE__ */ new Map();
|
|
2187
|
+
const endpoint = options.manifest?.virtualEndpoint ?? "/@panda-inspector/manifest";
|
|
2188
|
+
const editorMetadataEndpoint = options.metadata?.virtualEndpoint ?? "/@panda-inspector/editor-metadata";
|
|
2189
|
+
const runtimeBootstrapEndpoint = DEFAULT_RUNTIME_BOOTSTRAP_ENDPOINT;
|
|
2190
|
+
const runtimeModuleEndpoint = DEFAULT_RUNTIME_MODULE_ENDPOINT;
|
|
2191
|
+
const uiModuleEndpoint = DEFAULT_UI_MODULE_ENDPOINT;
|
|
2192
|
+
const runtimeChunkEndpoint = DEFAULT_RUNTIME_CHUNK_ENDPOINT;
|
|
2193
|
+
const attributes = {
|
|
2194
|
+
editId: options.attributes?.editId ?? "data-panda-edit-id",
|
|
2195
|
+
source: options.attributes?.source ?? "data-panda-source",
|
|
2196
|
+
jsxSource: options.attributes?.jsxSource ?? "data-panda-jsx-source",
|
|
2197
|
+
component: options.attributes?.component ?? "data-preact-component"
|
|
2198
|
+
};
|
|
2199
|
+
let projectRoot = normalizePath$1(options.projectRoot ?? "");
|
|
2200
|
+
let devEnabled = options.enabled !== false;
|
|
2201
|
+
let server;
|
|
2202
|
+
const manifest = () => ({
|
|
2203
|
+
version: 1,
|
|
2204
|
+
projectRoot,
|
|
2205
|
+
entries: [...manifestByFile.values()].flat()
|
|
2206
|
+
});
|
|
2207
|
+
return {
|
|
2208
|
+
name: "preact-panda-inspector",
|
|
2209
|
+
enforce: "pre",
|
|
2210
|
+
configResolved(config) {
|
|
2211
|
+
projectRoot = normalizePath$1(options.projectRoot ?? config.root ?? "");
|
|
2212
|
+
devEnabled = options.enabled !== false && config.command !== "build" && config.mode !== "production";
|
|
2213
|
+
},
|
|
2214
|
+
configureServer(nextServer) {
|
|
2215
|
+
server = nextServer;
|
|
2216
|
+
if (!devEnabled) return;
|
|
2217
|
+
nextServer.middlewares.use(endpoint, (_request, response) => {
|
|
2218
|
+
response.statusCode = 200;
|
|
2219
|
+
response.setHeader("content-type", "application/json");
|
|
2220
|
+
response.setHeader("cache-control", "no-store");
|
|
2221
|
+
response.end(JSON.stringify(manifest()));
|
|
2222
|
+
});
|
|
2223
|
+
nextServer.middlewares.use(editorMetadataEndpoint, async (_request, response) => {
|
|
2224
|
+
const metadata = await createEditorMetadata({
|
|
2225
|
+
projectRoot,
|
|
2226
|
+
pandaConfigPath: options.panda?.configPath
|
|
2227
|
+
});
|
|
2228
|
+
response.statusCode = 200;
|
|
2229
|
+
response.setHeader("content-type", "application/json");
|
|
2230
|
+
response.setHeader("cache-control", "no-store");
|
|
2231
|
+
response.end(JSON.stringify(metadata));
|
|
2232
|
+
});
|
|
2233
|
+
nextServer.middlewares.use(DEFAULT_OPEN_SOURCE_ENDPOINT, async (request, response) => {
|
|
2234
|
+
if (request.method && request.method !== "POST") {
|
|
2235
|
+
response.statusCode = 405;
|
|
2236
|
+
response.setHeader("content-type", "application/json");
|
|
2237
|
+
response.setHeader("cache-control", "no-store");
|
|
2238
|
+
response.end(JSON.stringify(openSourceLocationFailure("invalid-request", "Panda inspector source opening requires POST.")));
|
|
2239
|
+
return;
|
|
2240
|
+
}
|
|
2241
|
+
const requestResult = await readOpenSourceLocationRequest(request);
|
|
2242
|
+
if (!requestResult.ok) {
|
|
2243
|
+
response.statusCode = 400;
|
|
2244
|
+
response.setHeader("content-type", "application/json");
|
|
2245
|
+
response.setHeader("cache-control", "no-store");
|
|
2246
|
+
response.end(JSON.stringify(requestResult.response));
|
|
2247
|
+
return;
|
|
2248
|
+
}
|
|
2249
|
+
const result = await resolveOpenSourceLocation({
|
|
2250
|
+
request: requestResult.request,
|
|
2251
|
+
manifest: manifest(),
|
|
2252
|
+
projectRoot
|
|
2253
|
+
});
|
|
2254
|
+
response.statusCode = result.ok ? 200 : 400;
|
|
2255
|
+
response.setHeader("content-type", "application/json");
|
|
2256
|
+
response.setHeader("cache-control", "no-store");
|
|
2257
|
+
response.end(JSON.stringify(result));
|
|
2258
|
+
});
|
|
2259
|
+
registerWritebackRoutes(nextServer, {
|
|
2260
|
+
projectRoot,
|
|
2261
|
+
pandaConfigPath: options.panda?.configPath,
|
|
2262
|
+
cssImportSources: options.panda?.cssImportSources,
|
|
2263
|
+
sourceSyntax: options.sourceSyntax,
|
|
2264
|
+
attributes,
|
|
2265
|
+
manifest,
|
|
2266
|
+
onManifestEntries(filePath, entries) {
|
|
2267
|
+
manifestByFile.set(filePath, entries);
|
|
2268
|
+
}
|
|
2269
|
+
});
|
|
2270
|
+
registerStyleModuleRoute(nextServer, {
|
|
2271
|
+
endpoint: DEFAULT_STYLE_MODULE_ENDPOINT,
|
|
2272
|
+
projectRoot,
|
|
2273
|
+
cssImportSources: options.panda?.cssImportSources
|
|
2274
|
+
});
|
|
2275
|
+
registerRuntimeModuleRoutes(nextServer, {
|
|
2276
|
+
manifestEndpoint: endpoint,
|
|
2277
|
+
editorMetadataEndpoint,
|
|
2278
|
+
globalName: options.runtime?.globalName,
|
|
2279
|
+
runtimeBootstrapEndpoint,
|
|
2280
|
+
runtimeModuleEndpoint,
|
|
2281
|
+
uiModuleEndpoint,
|
|
2282
|
+
runtimeChunkEndpoint
|
|
2283
|
+
});
|
|
2284
|
+
},
|
|
2285
|
+
transformIndexHtml() {
|
|
2286
|
+
if (!devEnabled || options.runtime?.inject === false) return void 0;
|
|
2287
|
+
return [{
|
|
2288
|
+
tag: "script",
|
|
2289
|
+
attrs: {
|
|
2290
|
+
type: "module",
|
|
2291
|
+
src: runtimeBootstrapEndpoint
|
|
2292
|
+
},
|
|
2293
|
+
injectTo: "body"
|
|
2294
|
+
}];
|
|
2295
|
+
},
|
|
2296
|
+
transform(code, id) {
|
|
2297
|
+
const filePath = normalizePath$1(stripViteQuery(id));
|
|
2298
|
+
if (!devEnabled || !shouldTransform(filePath, options)) {
|
|
2299
|
+
manifestByFile.delete(filePath);
|
|
2300
|
+
return null;
|
|
2301
|
+
}
|
|
2302
|
+
const result = transformTsxSource({
|
|
2303
|
+
sourceText: code,
|
|
2304
|
+
filePath,
|
|
2305
|
+
projectRoot,
|
|
2306
|
+
attributes,
|
|
2307
|
+
cssImportSources: options.panda?.cssImportSources,
|
|
2308
|
+
sourceSyntax: options.sourceSyntax
|
|
2309
|
+
});
|
|
2310
|
+
manifestByFile.set(filePath, result.entries);
|
|
2311
|
+
if (result.entries.length > 0) server?.ws?.send(PANDA_INSPECTOR_EVENTS.manifestUpdate, {
|
|
2312
|
+
version: 1,
|
|
2313
|
+
changedFiles: [toRelativeProjectPath$1(filePath, projectRoot)],
|
|
2314
|
+
entryIds: result.entries.map((entry) => entry.id)
|
|
2315
|
+
});
|
|
2316
|
+
if (result.code === code) return null;
|
|
2317
|
+
return {
|
|
2318
|
+
code: result.code,
|
|
2319
|
+
map: null
|
|
2320
|
+
};
|
|
2321
|
+
}
|
|
2322
|
+
};
|
|
2323
|
+
}
|
|
2324
|
+
//#endregion
|
|
2325
|
+
export { preactPandaInspector };
|