@weapp-vite/web 1.3.3 → 1.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/plugin.mjs CHANGED
@@ -1,1932 +1,1555 @@
1
- // src/plugin/index.ts
2
- import process2 from "process";
3
- import { extname as extname4, resolve as resolve3 } from "pathe";
4
-
5
- // src/compiler/wxml/compile.ts
6
- import { readFileSync } from "fs";
7
-
8
- // src/compiler/wxml/dependency.ts
1
+ import process from "node:process";
2
+ import { dirname, extname, join, normalize, posix, relative, resolve } from "pathe";
3
+ import { readFileSync } from "node:fs";
4
+ import { parseDocument } from "htmlparser2";
5
+ import fs from "fs-extra";
6
+ import { parse } from "@babel/parser";
7
+ import _babelTraverse from "@babel/traverse";
8
+ import * as t from "@babel/types";
9
+ import MagicString from "magic-string";
10
+ import { bundleRequire } from "rolldown-require";
11
+ //#region src/compiler/wxml/dependency.ts
9
12
  function createDependencyContext() {
10
- return {
11
- warnings: [],
12
- dependencies: [],
13
- dependencySet: /* @__PURE__ */ new Set(),
14
- visited: /* @__PURE__ */ new Set(),
15
- active: /* @__PURE__ */ new Set(),
16
- circularWarnings: /* @__PURE__ */ new Set()
17
- };
13
+ return {
14
+ warnings: [],
15
+ dependencies: [],
16
+ dependencySet: /* @__PURE__ */ new Set(),
17
+ visited: /* @__PURE__ */ new Set(),
18
+ active: /* @__PURE__ */ new Set(),
19
+ circularWarnings: /* @__PURE__ */ new Set()
20
+ };
18
21
  }
19
22
  function addDependency(value, context, direct) {
20
- if (!context.dependencySet.has(value)) {
21
- context.dependencySet.add(value);
22
- context.dependencies.push(value);
23
- direct?.push(value);
24
- }
23
+ if (!context.dependencySet.has(value)) {
24
+ context.dependencySet.add(value);
25
+ context.dependencies.push(value);
26
+ direct?.push(value);
27
+ }
25
28
  }
26
29
  function warnReadTemplate(context, target) {
27
- context.warnings.push(`[web] \u65E0\u6CD5\u8BFB\u53D6\u6A21\u677F\u4F9D\u8D56: ${target}`);
30
+ context.warnings.push(`[web] 无法读取模板依赖: ${target}`);
28
31
  }
29
32
  function warnCircularTemplate(context, from, target) {
30
- const key = `${from}=>${target}`;
31
- if (context.circularWarnings.has(key)) {
32
- return;
33
- }
34
- context.circularWarnings.add(key);
35
- context.warnings.push(`[web] WXML \u5FAA\u73AF\u5F15\u7528: ${from} -> ${target}`);
36
- }
37
-
38
- // src/compiler/wxml/navigation.ts
39
- var NAVIGATION_BAR_ATTRS = /* @__PURE__ */ new Set([
40
- "title",
41
- "background-color",
42
- "text-style",
43
- "front-color",
44
- "loading"
33
+ const key = `${from}=>${target}`;
34
+ if (context.circularWarnings.has(key)) return;
35
+ context.circularWarnings.add(key);
36
+ context.warnings.push(`[web] WXML 循环引用: ${from} -> ${target}`);
37
+ }
38
+ //#endregion
39
+ //#region src/compiler/wxml/navigation.ts
40
+ const NAVIGATION_BAR_ATTRS = new Set([
41
+ "title",
42
+ "background-color",
43
+ "text-style",
44
+ "front-color",
45
+ "loading"
45
46
  ]);
46
47
  function stripPageMetaNodes(nodes) {
47
- const stripped = [];
48
- for (const node of nodes) {
49
- if (node.type === "element" && node.name === "page-meta") {
50
- continue;
51
- }
52
- if (node.type === "element" && node.children?.length) {
53
- const nextChildren = stripPageMetaNodes(node.children);
54
- if (nextChildren !== node.children) {
55
- stripped.push({ ...node, children: nextChildren });
56
- continue;
57
- }
58
- }
59
- stripped.push(node);
60
- }
61
- return stripped;
48
+ const stripped = [];
49
+ for (const node of nodes) {
50
+ if (node.type === "element" && node.name === "page-meta") continue;
51
+ if (node.type === "element" && node.children?.length) {
52
+ const nextChildren = stripPageMetaNodes(node.children);
53
+ if (nextChildren !== node.children) {
54
+ stripped.push({
55
+ ...node,
56
+ children: nextChildren
57
+ });
58
+ continue;
59
+ }
60
+ }
61
+ stripped.push(node);
62
+ }
63
+ return stripped;
62
64
  }
63
65
  function pickNavigationBarAttrs(attribs) {
64
- if (!attribs) {
65
- return void 0;
66
- }
67
- const picked = {};
68
- for (const [key, value] of Object.entries(attribs)) {
69
- if (NAVIGATION_BAR_ATTRS.has(key)) {
70
- picked[key] = value;
71
- }
72
- }
73
- return Object.keys(picked).length > 0 ? picked : void 0;
66
+ if (!attribs) return;
67
+ const picked = {};
68
+ for (const [key, value] of Object.entries(attribs)) if (NAVIGATION_BAR_ATTRS.has(key)) picked[key] = value;
69
+ return Object.keys(picked).length > 0 ? picked : void 0;
74
70
  }
75
71
  function findNavigationBarInPageMeta(node) {
76
- const children = node.children ?? [];
77
- for (const child of children) {
78
- if (child.type === "element" && child.name === "navigation-bar") {
79
- return child;
80
- }
81
- }
82
- return void 0;
72
+ const children = node.children ?? [];
73
+ for (const child of children) if (child.type === "element" && child.name === "navigation-bar") return child;
83
74
  }
84
75
  function extractNavigationBarFromPageMeta(nodes) {
85
- let pageMetaIndex = -1;
86
- let navigationBar;
87
- for (let i = 0; i < nodes.length; i += 1) {
88
- const node = nodes[i];
89
- if (node.type === "element" && node.name === "page-meta") {
90
- if (pageMetaIndex === -1) {
91
- pageMetaIndex = i;
92
- }
93
- if (!navigationBar) {
94
- navigationBar = findNavigationBarInPageMeta(node);
95
- }
96
- }
97
- }
98
- const warnings = [];
99
- if (pageMetaIndex > 0) {
100
- warnings.push("[web] page-meta \u9700\u8981\u4F5C\u4E3A\u9875\u9762\u7B2C\u4E00\u4E2A\u8282\u70B9\uFF0C\u5DF2\u5FFD\u7565\u5176\u4F4D\u7F6E\u7EA6\u675F\u3002");
101
- }
102
- const cleaned = pageMetaIndex === -1 ? nodes : stripPageMetaNodes(nodes);
103
- const attrs = navigationBar ? pickNavigationBarAttrs(navigationBar.attribs) : void 0;
104
- return { nodes: cleaned, attrs, warnings };
76
+ let pageMetaIndex = -1;
77
+ let navigationBar;
78
+ for (let i = 0; i < nodes.length; i += 1) {
79
+ const node = nodes[i];
80
+ if (node.type === "element" && node.name === "page-meta") {
81
+ if (pageMetaIndex === -1) pageMetaIndex = i;
82
+ if (!navigationBar) navigationBar = findNavigationBarInPageMeta(node);
83
+ }
84
+ }
85
+ const warnings = [];
86
+ if (pageMetaIndex > 0) warnings.push("[web] page-meta 需要作为页面第一个节点,已忽略其位置约束。");
87
+ return {
88
+ nodes: pageMetaIndex === -1 ? nodes : stripPageMetaNodes(nodes),
89
+ attrs: navigationBar ? pickNavigationBarAttrs(navigationBar.attribs) : void 0,
90
+ warnings
91
+ };
105
92
  }
106
93
  function toAttributeValue(value) {
107
- if (value == null) {
108
- return void 0;
109
- }
110
- if (typeof value === "string") {
111
- return value;
112
- }
113
- if (typeof value === "number" || typeof value === "boolean") {
114
- return String(value);
115
- }
116
- return void 0;
94
+ if (value == null) return;
95
+ if (typeof value === "string") return value;
96
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
117
97
  }
118
98
  function buildNavigationBarAttrs(config, overrides) {
119
- const attrs = {};
120
- if (config?.title !== void 0) {
121
- const value = toAttributeValue(config.title);
122
- if (value !== void 0) {
123
- attrs.title = value;
124
- }
125
- }
126
- if (config?.backgroundColor !== void 0) {
127
- const value = toAttributeValue(config.backgroundColor);
128
- if (value !== void 0) {
129
- attrs["background-color"] = value;
130
- }
131
- }
132
- if (config?.textStyle !== void 0) {
133
- const value = toAttributeValue(config.textStyle);
134
- if (value !== void 0) {
135
- attrs["text-style"] = value;
136
- }
137
- }
138
- if (config?.frontColor !== void 0) {
139
- const value = toAttributeValue(config.frontColor);
140
- if (value !== void 0) {
141
- attrs["front-color"] = value;
142
- }
143
- }
144
- if (config?.loading) {
145
- attrs.loading = "true";
146
- }
147
- if (overrides) {
148
- for (const [key, value] of Object.entries(overrides)) {
149
- attrs[key] = value;
150
- }
151
- }
152
- return attrs;
153
- }
154
-
155
- // src/compiler/wxml/parser.ts
156
- import { parseDocument } from "htmlparser2";
99
+ const attrs = {};
100
+ if (config?.title !== void 0) {
101
+ const value = toAttributeValue(config.title);
102
+ if (value !== void 0) attrs.title = value;
103
+ }
104
+ if (config?.backgroundColor !== void 0) {
105
+ const value = toAttributeValue(config.backgroundColor);
106
+ if (value !== void 0) attrs["background-color"] = value;
107
+ }
108
+ if (config?.textStyle !== void 0) {
109
+ const value = toAttributeValue(config.textStyle);
110
+ if (value !== void 0) attrs["text-style"] = value;
111
+ }
112
+ if (config?.frontColor !== void 0) {
113
+ const value = toAttributeValue(config.frontColor);
114
+ if (value !== void 0) attrs["front-color"] = value;
115
+ }
116
+ if (config?.loading) attrs.loading = "true";
117
+ if (overrides) for (const [key, value] of Object.entries(overrides)) attrs[key] = value;
118
+ return attrs;
119
+ }
120
+ //#endregion
121
+ //#region src/compiler/wxml/parser.ts
157
122
  function isRenderableNode(node) {
158
- if (node.type === "directive" || node.type === "comment") {
159
- return false;
160
- }
161
- if (node.type === "text") {
162
- const data = node.data ?? "";
163
- return data.trim().length > 0;
164
- }
165
- return true;
123
+ if (node.type === "directive" || node.type === "comment") return false;
124
+ if (node.type === "text") return (node.data ?? "").trim().length > 0;
125
+ return true;
166
126
  }
167
127
  function hasChildren(node) {
168
- return Array.isArray(node.children);
128
+ return Array.isArray(node.children);
169
129
  }
170
130
  function toRenderNode(node, children) {
171
- if (node.type === "text") {
172
- const data = node.data ?? "";
173
- return { type: "text", data };
174
- }
175
- if (node.type === "tag" || node.type === "script" || node.type === "style") {
176
- const element = node;
177
- return {
178
- type: "element",
179
- name: element.name,
180
- attribs: element.attribs ?? {},
181
- children
182
- };
183
- }
184
- return void 0;
131
+ if (node.type === "text") return {
132
+ type: "text",
133
+ data: node.data ?? ""
134
+ };
135
+ if (node.type === "tag" || node.type === "script" || node.type === "style") {
136
+ const element = node;
137
+ return {
138
+ type: "element",
139
+ name: element.name,
140
+ attribs: element.attribs ?? {},
141
+ children
142
+ };
143
+ }
185
144
  }
186
145
  function convertNode(node) {
187
- if (!isRenderableNode(node)) {
188
- return void 0;
189
- }
190
- const children = hasChildren(node) && node.children.length > 0 ? node.children.map((child) => convertNode(child)).filter((child) => Boolean(child)) : void 0;
191
- return toRenderNode(node, children);
146
+ if (!isRenderableNode(node)) return;
147
+ return toRenderNode(node, hasChildren(node) && node.children.length > 0 ? node.children.map((child) => convertNode(child)).filter((child) => Boolean(child)) : void 0);
192
148
  }
193
149
  function parseWxml(source) {
194
- const document = parseDocument(source, {
195
- xmlMode: true,
196
- decodeEntities: true,
197
- recognizeSelfClosing: true
198
- });
199
- const nodes = (document.children ?? []).filter(isRenderableNode);
200
- return nodes.map((node) => convertNode(node)).filter((node) => Boolean(node));
201
- }
202
-
203
- // src/shared/wxml.ts
204
- var CONTROL_ATTRS = /* @__PURE__ */ new Set([
205
- "wx:if",
206
- "wx:elif",
207
- "wx:else",
208
- "wx:for",
209
- "wx:for-item",
210
- "wx:for-index",
211
- "wx:key"
150
+ return (parseDocument(source, {
151
+ xmlMode: true,
152
+ decodeEntities: true,
153
+ recognizeSelfClosing: true
154
+ }).children ?? []).filter(isRenderableNode).map((node) => convertNode(node)).filter((node) => Boolean(node));
155
+ }
156
+ //#endregion
157
+ //#region src/shared/wxml.ts
158
+ const CONTROL_ATTRS = new Set([
159
+ "wx:if",
160
+ "wx:elif",
161
+ "wx:else",
162
+ "wx:for",
163
+ "wx:for-item",
164
+ "wx:for-index",
165
+ "wx:key"
212
166
  ]);
213
- var EVENT_PREFIX_RE = /^(?:bind|catch|mut-bind|capture-bind|capture-catch)([\w-]+)$/;
214
- var EVENT_KIND_ALIAS = {
215
- tap: "click"
216
- };
217
- var SELF_CLOSING_TAGS = /* @__PURE__ */ new Set([
218
- "area",
219
- "base",
220
- "br",
221
- "col",
222
- "embed",
223
- "hr",
224
- "img",
225
- "image",
226
- "input",
227
- "link",
228
- "meta",
229
- "param",
230
- "source",
231
- "track",
232
- "wbr"
167
+ const EVENT_PREFIX_RE = /^(?:bind|catch|mut-bind|capture-bind|capture-catch)([\w-]+)$/;
168
+ const EVENT_KIND_ALIAS = { tap: "click" };
169
+ const SELF_CLOSING_TAGS = new Set([
170
+ "area",
171
+ "base",
172
+ "br",
173
+ "col",
174
+ "embed",
175
+ "hr",
176
+ "img",
177
+ "image",
178
+ "input",
179
+ "link",
180
+ "meta",
181
+ "param",
182
+ "source",
183
+ "track",
184
+ "wbr"
233
185
  ]);
234
186
  function normalizeTagName(name) {
235
- switch (name) {
236
- case "view":
237
- case "cover-view":
238
- case "navigator":
239
- case "scroll-view":
240
- case "swiper":
241
- case "swiper-item":
242
- case "movable-area":
243
- case "movable-view":
244
- case "cover-image":
245
- return "div";
246
- case "text":
247
- case "icon":
248
- return "span";
249
- case "image":
250
- return "img";
251
- case "button":
252
- return "weapp-button";
253
- case "input":
254
- return "input";
255
- case "textarea":
256
- return "textarea";
257
- case "form":
258
- return "form";
259
- case "label":
260
- return "label";
261
- case "picker":
262
- case "picker-view":
263
- return "select";
264
- case "block":
265
- return "#fragment";
266
- case "slot":
267
- return "slot";
268
- default:
269
- return name || "div";
270
- }
187
+ switch (name) {
188
+ case "view":
189
+ case "cover-view":
190
+ case "navigator":
191
+ case "scroll-view":
192
+ case "swiper":
193
+ case "swiper-item":
194
+ case "movable-area":
195
+ case "movable-view":
196
+ case "cover-image": return "div";
197
+ case "text":
198
+ case "icon": return "span";
199
+ case "image": return "img";
200
+ case "button": return "weapp-button";
201
+ case "input": return "input";
202
+ case "textarea": return "textarea";
203
+ case "form": return "form";
204
+ case "label": return "label";
205
+ case "picker":
206
+ case "picker-view": return "select";
207
+ case "block": return "#fragment";
208
+ case "slot": return "slot";
209
+ default: return name || "div";
210
+ }
271
211
  }
272
212
  function normalizeAttributeName(name) {
273
- if (name === "class" || name === "style" || name.startsWith("data-")) {
274
- return name;
275
- }
276
- if (name === "hover-class") {
277
- return "data-hover-class";
278
- }
279
- return name.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
280
- }
281
-
282
- // src/compiler/wxml/interpolation.ts
213
+ if (name === "class" || name === "style" || name.startsWith("data-")) return name;
214
+ if (name === "hover-class") return "data-hover-class";
215
+ return name.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
216
+ }
217
+ //#endregion
218
+ //#region src/compiler/wxml/interpolation.ts
283
219
  function parseInterpolations(value) {
284
- const parts = [];
285
- if (!value.includes("{{")) {
286
- return [{ type: "text", value }];
287
- }
288
- let cursor = 0;
289
- while (cursor < value.length) {
290
- const start = value.indexOf("{{", cursor);
291
- if (start === -1) {
292
- parts.push({ type: "text", value: value.slice(cursor) });
293
- break;
294
- }
295
- if (start > cursor) {
296
- parts.push({ type: "text", value: value.slice(cursor, start) });
297
- }
298
- const end = value.indexOf("}}", start + 2);
299
- if (end === -1) {
300
- parts.push({ type: "text", value: value.slice(start) });
301
- break;
302
- }
303
- const expr = value.slice(start + 2, end).trim();
304
- if (expr) {
305
- parts.push({ type: "expr", value: expr });
306
- }
307
- cursor = end + 2;
308
- }
309
- return parts;
220
+ const parts = [];
221
+ if (!value.includes("{{")) return [{
222
+ type: "text",
223
+ value
224
+ }];
225
+ let cursor = 0;
226
+ while (cursor < value.length) {
227
+ const start = value.indexOf("{{", cursor);
228
+ if (start === -1) {
229
+ parts.push({
230
+ type: "text",
231
+ value: value.slice(cursor)
232
+ });
233
+ break;
234
+ }
235
+ if (start > cursor) parts.push({
236
+ type: "text",
237
+ value: value.slice(cursor, start)
238
+ });
239
+ const end = value.indexOf("}}", start + 2);
240
+ if (end === -1) {
241
+ parts.push({
242
+ type: "text",
243
+ value: value.slice(start)
244
+ });
245
+ break;
246
+ }
247
+ const expr = value.slice(start + 2, end).trim();
248
+ if (expr) parts.push({
249
+ type: "expr",
250
+ value: expr
251
+ });
252
+ cursor = end + 2;
253
+ }
254
+ return parts;
310
255
  }
311
256
  function buildExpression(parts, scopeVar, wxsVar) {
312
- if (parts.length === 0) {
313
- return '""';
314
- }
315
- if (parts.length === 1 && parts[0]?.type === "text") {
316
- return JSON.stringify(parts[0].value);
317
- }
318
- if (parts.length === 1 && parts[0]?.type === "expr") {
319
- return `ctx.eval(${JSON.stringify(parts[0].value)}, ${scopeVar}, ${wxsVar})`;
320
- }
321
- const segments = parts.map((part) => {
322
- if (part.type === "text") {
323
- return JSON.stringify(part.value);
324
- }
325
- return `ctx.eval(${JSON.stringify(part.value)}, ${scopeVar}, ${wxsVar})`;
326
- });
327
- return `(${segments.join(" + ")})`;
257
+ if (parts.length === 0) return "\"\"";
258
+ if (parts.length === 1 && parts[0]?.type === "text") return JSON.stringify(parts[0].value);
259
+ if (parts.length === 1 && parts[0]?.type === "expr") return `ctx.eval(${JSON.stringify(parts[0].value)}, ${scopeVar}, ${wxsVar})`;
260
+ return `(${parts.map((part) => {
261
+ if (part.type === "text") return JSON.stringify(part.value);
262
+ return `ctx.eval(${JSON.stringify(part.value)}, ${scopeVar}, ${wxsVar})`;
263
+ }).join(" + ")})`;
328
264
  }
329
265
  function hasTopLevelColon(expression) {
330
- let depth = 0;
331
- let inSingleQuote = false;
332
- let inDoubleQuote = false;
333
- let inTemplate = false;
334
- let escaped = false;
335
- let sawTopLevelQuestion = false;
336
- for (let index = 0; index < expression.length; index += 1) {
337
- const char = expression[index];
338
- if (inSingleQuote) {
339
- if (escaped) {
340
- escaped = false;
341
- continue;
342
- }
343
- if (char === "\\") {
344
- escaped = true;
345
- continue;
346
- }
347
- if (char === "'") {
348
- inSingleQuote = false;
349
- }
350
- continue;
351
- }
352
- if (inDoubleQuote) {
353
- if (escaped) {
354
- escaped = false;
355
- continue;
356
- }
357
- if (char === "\\") {
358
- escaped = true;
359
- continue;
360
- }
361
- if (char === '"') {
362
- inDoubleQuote = false;
363
- }
364
- continue;
365
- }
366
- if (inTemplate) {
367
- if (escaped) {
368
- escaped = false;
369
- continue;
370
- }
371
- if (char === "\\") {
372
- escaped = true;
373
- continue;
374
- }
375
- if (char === "`") {
376
- inTemplate = false;
377
- }
378
- continue;
379
- }
380
- if (char === "'") {
381
- inSingleQuote = true;
382
- continue;
383
- }
384
- if (char === '"') {
385
- inDoubleQuote = true;
386
- continue;
387
- }
388
- if (char === "`") {
389
- inTemplate = true;
390
- continue;
391
- }
392
- if (char === "(" || char === "[" || char === "{") {
393
- depth += 1;
394
- continue;
395
- }
396
- if (char === ")" || char === "]" || char === "}") {
397
- depth = Math.max(0, depth - 1);
398
- continue;
399
- }
400
- if (depth !== 0) {
401
- continue;
402
- }
403
- if (char === "?") {
404
- sawTopLevelQuestion = true;
405
- continue;
406
- }
407
- if (char === ":") {
408
- return !sawTopLevelQuestion;
409
- }
410
- }
411
- return false;
266
+ let depth = 0;
267
+ let inSingleQuote = false;
268
+ let inDoubleQuote = false;
269
+ let inTemplate = false;
270
+ let escaped = false;
271
+ let sawTopLevelQuestion = false;
272
+ for (let index = 0; index < expression.length; index += 1) {
273
+ const char = expression[index];
274
+ if (inSingleQuote) {
275
+ if (escaped) {
276
+ escaped = false;
277
+ continue;
278
+ }
279
+ if (char === "\\") {
280
+ escaped = true;
281
+ continue;
282
+ }
283
+ if (char === "'") inSingleQuote = false;
284
+ continue;
285
+ }
286
+ if (inDoubleQuote) {
287
+ if (escaped) {
288
+ escaped = false;
289
+ continue;
290
+ }
291
+ if (char === "\\") {
292
+ escaped = true;
293
+ continue;
294
+ }
295
+ if (char === "\"") inDoubleQuote = false;
296
+ continue;
297
+ }
298
+ if (inTemplate) {
299
+ if (escaped) {
300
+ escaped = false;
301
+ continue;
302
+ }
303
+ if (char === "\\") {
304
+ escaped = true;
305
+ continue;
306
+ }
307
+ if (char === "`") inTemplate = false;
308
+ continue;
309
+ }
310
+ if (char === "'") {
311
+ inSingleQuote = true;
312
+ continue;
313
+ }
314
+ if (char === "\"") {
315
+ inDoubleQuote = true;
316
+ continue;
317
+ }
318
+ if (char === "`") {
319
+ inTemplate = true;
320
+ continue;
321
+ }
322
+ if (char === "(" || char === "[" || char === "{") {
323
+ depth += 1;
324
+ continue;
325
+ }
326
+ if (char === ")" || char === "]" || char === "}") {
327
+ depth = Math.max(0, depth - 1);
328
+ continue;
329
+ }
330
+ if (depth !== 0) continue;
331
+ if (char === "?") {
332
+ sawTopLevelQuestion = true;
333
+ continue;
334
+ }
335
+ if (char === ":") return !sawTopLevelQuestion;
336
+ }
337
+ return false;
412
338
  }
413
339
  function shouldWrapShorthandObject(expression) {
414
- const trimmed = expression.trim();
415
- if (!trimmed) {
416
- return false;
417
- }
418
- if (trimmed.startsWith("{") || trimmed.startsWith("[") || trimmed.startsWith("(")) {
419
- return false;
420
- }
421
- return hasTopLevelColon(trimmed);
340
+ const trimmed = expression.trim();
341
+ if (!trimmed) return false;
342
+ if (trimmed.startsWith("{") || trimmed.startsWith("[") || trimmed.startsWith("(")) return false;
343
+ return hasTopLevelColon(trimmed);
422
344
  }
423
345
  function buildTemplateDataExpression(raw, scopeVar, wxsVar) {
424
- const trimmed = raw.trim();
425
- const parts = parseInterpolations(trimmed);
426
- if (parts.length === 1 && parts[0]?.type === "expr") {
427
- const expr = parts[0].value.trim();
428
- if (expr) {
429
- const normalizedExpr = shouldWrapShorthandObject(expr) ? `{ ${expr} }` : expr;
430
- return buildExpression([{ type: "expr", value: normalizedExpr }], scopeVar, wxsVar);
431
- }
432
- }
433
- return buildExpression(parseInterpolations(raw), scopeVar, wxsVar);
434
- }
435
-
436
- // src/compiler/wxml/attributes.ts
346
+ const parts = parseInterpolations(raw.trim());
347
+ if (parts.length === 1 && parts[0]?.type === "expr") {
348
+ const expr = parts[0].value.trim();
349
+ if (expr) return buildExpression([{
350
+ type: "expr",
351
+ value: shouldWrapShorthandObject(expr) ? `{ ${expr} }` : expr
352
+ }], scopeVar, wxsVar);
353
+ }
354
+ return buildExpression(parseInterpolations(raw), scopeVar, wxsVar);
355
+ }
356
+ //#endregion
357
+ //#region src/compiler/wxml/attributes.ts
437
358
  function extractFor(attribs) {
438
- const expr = attribs["wx:for"];
439
- const itemName = attribs["wx:for-item"]?.trim() || "item";
440
- let indexName = attribs["wx:for-index"]?.trim() || "index";
441
- const key = attribs["wx:key"];
442
- const restAttribs = {};
443
- for (const [name, value] of Object.entries(attribs)) {
444
- if (CONTROL_ATTRS.has(name)) {
445
- continue;
446
- }
447
- restAttribs[name] = value;
448
- }
449
- if (itemName === indexName) {
450
- indexName = `${indexName}Index`;
451
- }
452
- return { expr, itemName, indexName, key, restAttribs };
359
+ const expr = attribs["wx:for"];
360
+ const itemName = attribs["wx:for-item"]?.trim() || "item";
361
+ let indexName = attribs["wx:for-index"]?.trim() || "index";
362
+ const key = attribs["wx:key"];
363
+ const restAttribs = {};
364
+ for (const [name, value] of Object.entries(attribs)) {
365
+ if (CONTROL_ATTRS.has(name)) continue;
366
+ restAttribs[name] = value;
367
+ }
368
+ if (itemName === indexName) indexName = `${indexName}Index`;
369
+ return {
370
+ expr,
371
+ itemName,
372
+ indexName,
373
+ key,
374
+ restAttribs
375
+ };
453
376
  }
454
377
  function isConditionalElement(node) {
455
- if (node.type !== "element") {
456
- return false;
457
- }
458
- const attribs = node.attribs ?? {};
459
- return "wx:if" in attribs || "wx:elif" in attribs || "wx:else" in attribs;
378
+ if (node.type !== "element") return false;
379
+ const attribs = node.attribs ?? {};
380
+ return "wx:if" in attribs || "wx:elif" in attribs || "wx:else" in attribs;
460
381
  }
461
382
  function stripControlAttributes(attribs) {
462
- const result = {};
463
- for (const [name, value] of Object.entries(attribs)) {
464
- if (!CONTROL_ATTRS.has(name)) {
465
- result[name] = value;
466
- }
467
- }
468
- return result;
383
+ const result = {};
384
+ for (const [name, value] of Object.entries(attribs)) if (!CONTROL_ATTRS.has(name)) result[name] = value;
385
+ return result;
469
386
  }
470
387
  function parseEventAttribute(name) {
471
- if (name.includes(":")) {
472
- const [prefix, rawEvent] = name.split(":", 2);
473
- return { prefix, rawEvent };
474
- }
475
- const match = EVENT_PREFIX_RE.exec(name);
476
- if (!match) {
477
- return void 0;
478
- }
479
- return { prefix: name.slice(0, name.length - match[1].length), rawEvent: match[1] };
388
+ if (name.includes(":")) {
389
+ const [prefix, rawEvent] = name.split(":", 2);
390
+ return {
391
+ prefix,
392
+ rawEvent
393
+ };
394
+ }
395
+ const match = EVENT_PREFIX_RE.exec(name);
396
+ if (!match) return;
397
+ return {
398
+ prefix: name.slice(0, name.length - match[1].length),
399
+ rawEvent: match[1]
400
+ };
480
401
  }
481
402
  function resolveComponentTagName(name, componentTags) {
482
- if (!componentTags) {
483
- return void 0;
484
- }
485
- return componentTags[name] ?? componentTags[name.toLowerCase()];
486
- }
487
- var PROPERTY_BIND_EXCLUSIONS = /* @__PURE__ */ new Set(["class", "style", "id", "slot"]);
403
+ if (!componentTags) return;
404
+ return componentTags[name] ?? componentTags[name.toLowerCase()];
405
+ }
406
+ const PROPERTY_BIND_EXCLUSIONS = new Set([
407
+ "class",
408
+ "style",
409
+ "id",
410
+ "slot"
411
+ ]);
488
412
  function shouldBindAsProperty(name) {
489
- if (PROPERTY_BIND_EXCLUSIONS.has(name)) {
490
- return false;
491
- }
492
- if (name.startsWith("data-") || name.startsWith("aria-")) {
493
- return false;
494
- }
495
- return true;
413
+ if (PROPERTY_BIND_EXCLUSIONS.has(name)) return false;
414
+ if (name.startsWith("data-") || name.startsWith("aria-")) return false;
415
+ return true;
496
416
  }
497
417
  function normalizePropertyName(name) {
498
- return name.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
418
+ return name.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
499
419
  }
500
420
  function renderAttributes(attribs, scopeVar, wxsVar, options) {
501
- let buffer = "";
502
- for (const [rawName, rawValue] of Object.entries(attribs)) {
503
- if (options?.skipControl && CONTROL_ATTRS.has(rawName)) {
504
- continue;
505
- }
506
- const eventInfo = parseEventAttribute(rawName);
507
- if (eventInfo) {
508
- const event = eventInfo.rawEvent.toLowerCase();
509
- const handlerExpr = buildExpression(parseInterpolations(rawValue ?? ""), scopeVar, wxsVar);
510
- const domEvent = EVENT_KIND_ALIAS[event] ?? event;
511
- const flags = {
512
- catch: eventInfo.prefix.includes("catch"),
513
- capture: eventInfo.prefix.includes("capture")
514
- };
515
- buffer += ` @${domEvent}=\${ctx.event(${JSON.stringify(event)}, ${handlerExpr}, ${scopeVar}, ${wxsVar}, ${JSON.stringify(flags)})}`;
516
- continue;
517
- }
518
- const useProperty = options?.preferProperty && shouldBindAsProperty(rawName);
519
- const name = useProperty ? normalizePropertyName(rawName) : normalizeAttributeName(rawName);
520
- const expr = buildExpression(parseInterpolations(rawValue ?? ""), scopeVar, wxsVar);
521
- buffer += ` ${useProperty ? "." : ""}${name}=\${${expr}}`;
522
- }
523
- return buffer;
524
- }
525
-
526
- // src/compiler/wxml/renderer.ts
421
+ let buffer = "";
422
+ for (const [rawName, rawValue] of Object.entries(attribs)) {
423
+ if (options?.skipControl && CONTROL_ATTRS.has(rawName)) continue;
424
+ const eventInfo = parseEventAttribute(rawName);
425
+ if (eventInfo) {
426
+ const event = eventInfo.rawEvent.toLowerCase();
427
+ const handlerExpr = buildExpression(parseInterpolations(rawValue ?? ""), scopeVar, wxsVar);
428
+ const domEvent = EVENT_KIND_ALIAS[event] ?? event;
429
+ const flags = {
430
+ catch: eventInfo.prefix.includes("catch"),
431
+ capture: eventInfo.prefix.includes("capture")
432
+ };
433
+ buffer += ` @${domEvent}=\${ctx.event(${JSON.stringify(event)}, ${handlerExpr}, ${scopeVar}, ${wxsVar}, ${JSON.stringify(flags)})}`;
434
+ continue;
435
+ }
436
+ const useProperty = options?.preferProperty && shouldBindAsProperty(rawName);
437
+ const name = useProperty ? normalizePropertyName(rawName) : normalizeAttributeName(rawName);
438
+ const expr = buildExpression(parseInterpolations(rawValue ?? ""), scopeVar, wxsVar);
439
+ buffer += ` ${useProperty ? "." : ""}${name}=\${${expr}}`;
440
+ }
441
+ return buffer;
442
+ }
443
+ //#endregion
444
+ //#region src/compiler/wxml/renderer.ts
527
445
  var Renderer = class {
528
- renderNodes(nodes, scopeVar, wxsVar, componentTags) {
529
- const parts = [];
530
- for (let index = 0; index < nodes.length; index += 1) {
531
- const node = nodes[index];
532
- if (isConditionalElement(node)) {
533
- const { rendered, endIndex } = this.renderConditionalSequence(
534
- nodes,
535
- index,
536
- scopeVar,
537
- wxsVar,
538
- componentTags
539
- );
540
- parts.push(rendered);
541
- index = endIndex;
542
- continue;
543
- }
544
- parts.push(this.renderNode(node, scopeVar, wxsVar, componentTags));
545
- }
546
- if (parts.length === 0) {
547
- return '""';
548
- }
549
- if (parts.length === 1) {
550
- return parts[0];
551
- }
552
- return `[${parts.join(", ")}]`;
553
- }
554
- renderConditionalSequence(nodes, startIndex, scopeVar, wxsVar, componentTags) {
555
- const branches = [];
556
- let cursor = startIndex;
557
- while (cursor < nodes.length) {
558
- const candidate = nodes[cursor];
559
- if (!isConditionalElement(candidate)) {
560
- break;
561
- }
562
- const attribs = candidate.attribs ?? {};
563
- if (branches.length === 0 && !("wx:if" in attribs)) {
564
- break;
565
- }
566
- if (branches.length > 0 && !("wx:elif" in attribs) && !("wx:else" in attribs)) {
567
- break;
568
- }
569
- branches.push({ node: candidate, attribs });
570
- cursor += 1;
571
- if ("wx:else" in attribs) {
572
- break;
573
- }
574
- }
575
- if (!branches.length) {
576
- const node = nodes[startIndex];
577
- if (!node) {
578
- return { rendered: '""', endIndex: startIndex };
579
- }
580
- return { rendered: this.renderNode(node, scopeVar, wxsVar, componentTags), endIndex: startIndex };
581
- }
582
- let expr = '""';
583
- for (let index = branches.length - 1; index >= 0; index -= 1) {
584
- const { node, attribs } = branches[index];
585
- const cleanedAttribs = stripControlAttributes(attribs);
586
- if ("wx:else" in attribs) {
587
- expr = this.renderElement(node, scopeVar, wxsVar, componentTags, { overrideAttribs: cleanedAttribs });
588
- continue;
589
- }
590
- const conditionExpr = attribs["wx:if"] ?? attribs["wx:elif"] ?? "";
591
- const rendered = this.renderElement(node, scopeVar, wxsVar, componentTags, { overrideAttribs: cleanedAttribs });
592
- const condition = buildExpression(parseInterpolations(conditionExpr), scopeVar, wxsVar);
593
- expr = `(${condition} ? ${rendered} : ${expr})`;
594
- }
595
- return { rendered: expr, endIndex: startIndex + branches.length - 1 };
596
- }
597
- renderNode(node, scopeVar, wxsVar, componentTags) {
598
- if (node.type === "text") {
599
- const parts = parseInterpolations(node.data ?? "");
600
- return buildExpression(parts, scopeVar, wxsVar);
601
- }
602
- if (node.type === "element") {
603
- if (node.name === "template" && node.attribs?.is) {
604
- return this.renderTemplateInvoke(node, scopeVar, wxsVar);
605
- }
606
- return this.renderElement(node, scopeVar, wxsVar, componentTags);
607
- }
608
- return '""';
609
- }
610
- renderTemplateInvoke(node, scopeVar, wxsVar) {
611
- const attribs = node.attribs ?? {};
612
- const isExpr = buildExpression(parseInterpolations(attribs.is ?? ""), scopeVar, wxsVar);
613
- const dataExpr = attribs.data ? buildTemplateDataExpression(attribs.data, scopeVar, wxsVar) : void 0;
614
- const scopeExpr = dataExpr ? `ctx.mergeScope(${scopeVar}, ${dataExpr})` : scopeVar;
615
- return `ctx.renderTemplate(__templates, ${isExpr}, ${scopeExpr}, ctx)`;
616
- }
617
- renderElement(node, scopeVar, wxsVar, componentTags, options = {}) {
618
- const attribs = options.overrideAttribs ?? node.attribs ?? {};
619
- if (!options.skipFor) {
620
- const forInfo = extractFor(node.attribs ?? {});
621
- if (forInfo.expr) {
622
- const listExpression = buildExpression(parseInterpolations(forInfo.expr), scopeVar, wxsVar);
623
- const listExpr = `ctx.normalizeList(${listExpression})`;
624
- const itemVar = forInfo.itemName;
625
- const indexVar = forInfo.indexName;
626
- const scopeExpr = `ctx.createScope(${scopeVar}, { ${itemVar}: ${itemVar}, ${indexVar}: ${indexVar} })`;
627
- const itemRender = this.renderElement(
628
- node,
629
- "__scope",
630
- wxsVar,
631
- componentTags,
632
- { skipFor: true, overrideAttribs: forInfo.restAttribs }
633
- );
634
- const keyExpr = `ctx.key(${JSON.stringify(forInfo.key ?? "")}, ${itemVar}, ${indexVar}, ${scopeExpr}, ${wxsVar})`;
635
- return `repeat(${listExpr}, (${itemVar}, ${indexVar}) => ${keyExpr}, (${itemVar}, ${indexVar}) => { const __scope = ${scopeExpr}; return ${itemRender}; })`;
636
- }
637
- }
638
- const customTag = resolveComponentTagName(node.name ?? "", componentTags);
639
- const tagName = customTag ?? normalizeTagName(node.name ?? "");
640
- if (tagName === "#fragment") {
641
- return this.renderNodes(node.children ?? [], scopeVar, wxsVar, componentTags);
642
- }
643
- const attrs = renderAttributes(attribs, scopeVar, wxsVar, {
644
- skipControl: true,
645
- preferProperty: Boolean(customTag)
646
- });
647
- const childNodes = node.children ?? [];
648
- const children = childNodes.map((child) => `\${${this.renderNode(child, scopeVar, wxsVar, componentTags)}}`).join("");
649
- if (SELF_CLOSING_TAGS.has(tagName) && childNodes.length === 0) {
650
- return `html\`<${tagName}${attrs} />\``;
651
- }
652
- return `html\`<${tagName}${attrs}>${children}</${tagName}>\``;
653
- }
446
+ renderNodes(nodes, scopeVar, wxsVar, componentTags) {
447
+ const parts = [];
448
+ for (let index = 0; index < nodes.length; index += 1) {
449
+ const node = nodes[index];
450
+ if (isConditionalElement(node)) {
451
+ const { rendered, endIndex } = this.renderConditionalSequence(nodes, index, scopeVar, wxsVar, componentTags);
452
+ parts.push(rendered);
453
+ index = endIndex;
454
+ continue;
455
+ }
456
+ parts.push(this.renderNode(node, scopeVar, wxsVar, componentTags));
457
+ }
458
+ if (parts.length === 0) return "\"\"";
459
+ if (parts.length === 1) return parts[0];
460
+ return `[${parts.join(", ")}]`;
461
+ }
462
+ renderConditionalSequence(nodes, startIndex, scopeVar, wxsVar, componentTags) {
463
+ const branches = [];
464
+ let cursor = startIndex;
465
+ while (cursor < nodes.length) {
466
+ const candidate = nodes[cursor];
467
+ if (!isConditionalElement(candidate)) break;
468
+ const attribs = candidate.attribs ?? {};
469
+ if (branches.length === 0 && !("wx:if" in attribs)) break;
470
+ if (branches.length > 0 && !("wx:elif" in attribs) && !("wx:else" in attribs)) break;
471
+ branches.push({
472
+ node: candidate,
473
+ attribs
474
+ });
475
+ cursor += 1;
476
+ if ("wx:else" in attribs) break;
477
+ }
478
+ if (!branches.length) {
479
+ const node = nodes[startIndex];
480
+ if (!node) return {
481
+ rendered: "\"\"",
482
+ endIndex: startIndex
483
+ };
484
+ return {
485
+ rendered: this.renderNode(node, scopeVar, wxsVar, componentTags),
486
+ endIndex: startIndex
487
+ };
488
+ }
489
+ let expr = "\"\"";
490
+ for (let index = branches.length - 1; index >= 0; index -= 1) {
491
+ const { node, attribs } = branches[index];
492
+ const cleanedAttribs = stripControlAttributes(attribs);
493
+ if ("wx:else" in attribs) {
494
+ expr = this.renderElement(node, scopeVar, wxsVar, componentTags, { overrideAttribs: cleanedAttribs });
495
+ continue;
496
+ }
497
+ const conditionExpr = attribs["wx:if"] ?? attribs["wx:elif"] ?? "";
498
+ const rendered = this.renderElement(node, scopeVar, wxsVar, componentTags, { overrideAttribs: cleanedAttribs });
499
+ expr = `(${buildExpression(parseInterpolations(conditionExpr), scopeVar, wxsVar)} ? ${rendered} : ${expr})`;
500
+ }
501
+ return {
502
+ rendered: expr,
503
+ endIndex: startIndex + branches.length - 1
504
+ };
505
+ }
506
+ renderNode(node, scopeVar, wxsVar, componentTags) {
507
+ if (node.type === "text") return buildExpression(parseInterpolations(node.data ?? ""), scopeVar, wxsVar);
508
+ if (node.type === "element") {
509
+ if (node.name === "template" && node.attribs?.is) return this.renderTemplateInvoke(node, scopeVar, wxsVar);
510
+ return this.renderElement(node, scopeVar, wxsVar, componentTags);
511
+ }
512
+ return "\"\"";
513
+ }
514
+ renderTemplateInvoke(node, scopeVar, wxsVar) {
515
+ const attribs = node.attribs ?? {};
516
+ const isExpr = buildExpression(parseInterpolations(attribs.is ?? ""), scopeVar, wxsVar);
517
+ const dataExpr = attribs.data ? buildTemplateDataExpression(attribs.data, scopeVar, wxsVar) : void 0;
518
+ return `ctx.renderTemplate(__templates, ${isExpr}, ${dataExpr ? `ctx.mergeScope(${scopeVar}, ${dataExpr})` : scopeVar}, ctx)`;
519
+ }
520
+ renderElement(node, scopeVar, wxsVar, componentTags, options = {}) {
521
+ const attribs = options.overrideAttribs ?? node.attribs ?? {};
522
+ if (!options.skipFor) {
523
+ const forInfo = extractFor(node.attribs ?? {});
524
+ if (forInfo.expr) {
525
+ const listExpr = `ctx.normalizeList(${buildExpression(parseInterpolations(forInfo.expr), scopeVar, wxsVar)})`;
526
+ const itemVar = forInfo.itemName;
527
+ const indexVar = forInfo.indexName;
528
+ const scopeExpr = `ctx.createScope(${scopeVar}, { ${itemVar}: ${itemVar}, ${indexVar}: ${indexVar} })`;
529
+ const itemRender = this.renderElement(node, "__scope", wxsVar, componentTags, {
530
+ skipFor: true,
531
+ overrideAttribs: forInfo.restAttribs
532
+ });
533
+ return `repeat(${listExpr}, (${itemVar}, ${indexVar}) => ${`ctx.key(${JSON.stringify(forInfo.key ?? "")}, ${itemVar}, ${indexVar}, ${scopeExpr}, ${wxsVar})`}, (${itemVar}, ${indexVar}) => { const __scope = ${scopeExpr}; return ${itemRender}; })`;
534
+ }
535
+ }
536
+ const customTag = resolveComponentTagName(node.name ?? "", componentTags);
537
+ const tagName = customTag ?? normalizeTagName(node.name ?? "");
538
+ if (tagName === "#fragment") return this.renderNodes(node.children ?? [], scopeVar, wxsVar, componentTags);
539
+ const attrs = renderAttributes(attribs, scopeVar, wxsVar, {
540
+ skipControl: true,
541
+ preferProperty: Boolean(customTag)
542
+ });
543
+ const childNodes = node.children ?? [];
544
+ const children = childNodes.map((child) => `\${${this.renderNode(child, scopeVar, wxsVar, componentTags)}}`).join("");
545
+ if (SELF_CLOSING_TAGS.has(tagName) && childNodes.length === 0) return `html\`<${tagName}${attrs} />\``;
546
+ return `html\`<${tagName}${attrs}>${children}</${tagName}>\``;
547
+ }
654
548
  };
655
- var renderer = new Renderer();
656
-
657
- // src/compiler/wxml/specialNodes.ts
658
- import { dirname, relative } from "pathe";
549
+ const renderer = new Renderer();
550
+ //#endregion
551
+ //#region src/compiler/wxml/specialNodes.ts
659
552
  function shouldMarkWxsImport(pathname) {
660
- const lower = pathname.toLowerCase();
661
- if (lower.endsWith(".wxs") || lower.endsWith(".wxs.ts") || lower.endsWith(".wxs.js")) {
662
- return false;
663
- }
664
- return lower.endsWith(".ts") || lower.endsWith(".js");
553
+ const lower = pathname.toLowerCase();
554
+ if (lower.endsWith(".wxs") || lower.endsWith(".wxs.ts") || lower.endsWith(".wxs.js")) return false;
555
+ return lower.endsWith(".ts") || lower.endsWith(".js");
665
556
  }
666
557
  function collectSpecialNodes(nodes, context) {
667
- const renderable = [];
668
- for (const node of nodes) {
669
- if (node.type === "element") {
670
- const name = node.name ?? "";
671
- if (name === "template" && node.attribs?.name) {
672
- context.templates.push({
673
- name: node.attribs.name,
674
- nodes: collectSpecialNodes(node.children ?? [], context)
675
- });
676
- continue;
677
- }
678
- if ((name === "import" || name === "wx-import") && node.attribs?.src) {
679
- const resolved = context.resolveTemplate(node.attribs.src);
680
- if (resolved) {
681
- context.imports.push({
682
- id: resolved,
683
- importName: `__wxml_import_${context.imports.length}`
684
- });
685
- } else {
686
- context.warnings.push(`[web] \u65E0\u6CD5\u89E3\u6790\u6A21\u677F\u4F9D\u8D56: ${node.attribs.src} (from ${context.sourceId})`);
687
- }
688
- continue;
689
- }
690
- if ((name === "include" || name === "wx-include") && node.attribs?.src) {
691
- const resolved = context.resolveTemplate(node.attribs.src);
692
- if (resolved) {
693
- context.includes.push({
694
- id: resolved,
695
- importName: `__wxml_include_${context.includes.length}`
696
- });
697
- } else {
698
- context.warnings.push(`[web] \u65E0\u6CD5\u89E3\u6790\u6A21\u677F\u4F9D\u8D56: ${node.attribs.src} (from ${context.sourceId})`);
699
- }
700
- continue;
701
- }
702
- if (name === "wxs") {
703
- const moduleName = node.attribs?.module?.trim();
704
- if (moduleName) {
705
- const previousSource = context.wxsModules.get(moduleName);
706
- if (previousSource) {
707
- context.warnings.push(`[web] WXS \u6A21\u5757\u540D\u91CD\u590D: ${moduleName} (from ${context.sourceId})`);
708
- }
709
- context.wxsModules.set(moduleName, context.sourceId);
710
- if (node.attribs?.src) {
711
- const resolved = context.resolveWxs(node.attribs.src);
712
- if (resolved) {
713
- context.wxs.push({
714
- module: moduleName,
715
- kind: "src",
716
- importName: `__wxs_${context.wxs.length}`,
717
- value: resolved
718
- });
719
- }
720
- } else {
721
- const inlineCode = (node.children ?? []).filter((child) => child.type === "text").map((child) => child.data ?? "").join("");
722
- context.wxs.push({
723
- module: moduleName,
724
- kind: "inline",
725
- importName: `__wxs_${context.wxs.length}`,
726
- value: inlineCode
727
- });
728
- }
729
- }
730
- continue;
731
- }
732
- if (node.children?.length) {
733
- node.children = collectSpecialNodes(node.children, context);
734
- }
735
- }
736
- renderable.push(node);
737
- }
738
- return renderable;
739
- }
740
- function toRelativeImport(from, target) {
741
- const fromDir = dirname(from);
742
- const rel = relative(fromDir, target);
743
- if (!rel || rel.startsWith(".")) {
744
- const fallback = normalizeTemplatePath(target).split("/").pop() ?? "";
745
- return rel || `./${fallback}`;
746
- }
747
- return `./${rel}`;
558
+ const renderable = [];
559
+ for (const node of nodes) {
560
+ if (node.type === "element") {
561
+ const name = node.name ?? "";
562
+ if (name === "template" && node.attribs?.name) {
563
+ context.templates.push({
564
+ name: node.attribs.name,
565
+ nodes: collectSpecialNodes(node.children ?? [], context)
566
+ });
567
+ continue;
568
+ }
569
+ if ((name === "import" || name === "wx-import") && node.attribs?.src) {
570
+ const resolved = context.resolveTemplate(node.attribs.src);
571
+ if (resolved) context.imports.push({
572
+ id: resolved,
573
+ importName: `__wxml_import_${context.imports.length}`
574
+ });
575
+ else context.warnings.push(`[web] 无法解析模板依赖: ${node.attribs.src} (from ${context.sourceId})`);
576
+ continue;
577
+ }
578
+ if ((name === "include" || name === "wx-include") && node.attribs?.src) {
579
+ const resolved = context.resolveTemplate(node.attribs.src);
580
+ if (resolved) context.includes.push({
581
+ id: resolved,
582
+ importName: `__wxml_include_${context.includes.length}`
583
+ });
584
+ else context.warnings.push(`[web] 无法解析模板依赖: ${node.attribs.src} (from ${context.sourceId})`);
585
+ continue;
586
+ }
587
+ if (name === "wxs") {
588
+ const moduleName = node.attribs?.module?.trim();
589
+ if (moduleName) {
590
+ if (context.wxsModules.get(moduleName)) context.warnings.push(`[web] WXS 模块名重复: ${moduleName} (from ${context.sourceId})`);
591
+ context.wxsModules.set(moduleName, context.sourceId);
592
+ if (node.attribs?.src) {
593
+ const resolved = context.resolveWxs(node.attribs.src);
594
+ if (resolved) context.wxs.push({
595
+ module: moduleName,
596
+ kind: "src",
597
+ importName: `__wxs_${context.wxs.length}`,
598
+ value: resolved
599
+ });
600
+ } else {
601
+ const inlineCode = (node.children ?? []).filter((child) => child.type === "text").map((child) => child.data ?? "").join("");
602
+ context.wxs.push({
603
+ module: moduleName,
604
+ kind: "inline",
605
+ importName: `__wxs_${context.wxs.length}`,
606
+ value: inlineCode
607
+ });
608
+ }
609
+ }
610
+ continue;
611
+ }
612
+ if (node.children?.length) node.children = collectSpecialNodes(node.children, context);
613
+ }
614
+ renderable.push(node);
615
+ }
616
+ return renderable;
617
+ }
618
+ function toRelativeImport$1(from, target) {
619
+ const rel = relative(dirname(from), target);
620
+ if (!rel || rel.startsWith(".")) {
621
+ const fallback = normalizeTemplatePath(target).split("/").pop() ?? "";
622
+ return rel || `./${fallback}`;
623
+ }
624
+ return `./${rel}`;
748
625
  }
749
626
  function normalizeTemplatePath(pathname) {
750
- return pathname.split("\\").join("/");
627
+ return pathname.split("\\").join("/");
751
628
  }
752
-
753
- // src/compiler/wxml/compile.ts
629
+ //#endregion
630
+ //#region src/compiler/wxml/compile.ts
754
631
  function compileWxml(options) {
755
- const dependencyContext = options.dependencyContext ?? createDependencyContext();
756
- const expandDependencies = options.expandDependencies ?? !options.dependencyContext;
757
- const warnings = dependencyContext.warnings;
758
- const expandDependencyTree = (dependencies2, importer) => {
759
- for (const target of dependencies2) {
760
- if (!target) {
761
- continue;
762
- }
763
- if (dependencyContext.active.has(target)) {
764
- warnCircularTemplate(dependencyContext, importer, target);
765
- continue;
766
- }
767
- if (dependencyContext.visited.has(target)) {
768
- continue;
769
- }
770
- dependencyContext.visited.add(target);
771
- dependencyContext.active.add(target);
772
- let source;
773
- try {
774
- source = readFileSync(target, "utf8");
775
- } catch {
776
- warnReadTemplate(dependencyContext, target);
777
- dependencyContext.active.delete(target);
778
- continue;
779
- }
780
- try {
781
- const result = compileWxml({
782
- id: target,
783
- source,
784
- resolveTemplatePath: options.resolveTemplatePath,
785
- resolveWxsPath: options.resolveWxsPath,
786
- dependencyContext,
787
- expandDependencies: false
788
- });
789
- expandDependencyTree(result.dependencies, target);
790
- } catch (error) {
791
- if (error instanceof Error && error.message) {
792
- warnings.push(`[web] \u65E0\u6CD5\u89E3\u6790\u6A21\u677F\u4F9D\u8D56: ${target} ${error.message}`);
793
- }
794
- }
795
- dependencyContext.active.delete(target);
796
- }
797
- };
798
- let nodes = parseWxml(options.source);
799
- let navigationBarAttrs;
800
- if (options.navigationBar) {
801
- const extracted = extractNavigationBarFromPageMeta(nodes);
802
- nodes = extracted.nodes;
803
- if (extracted.warnings.length > 0) {
804
- warnings.push(...extracted.warnings);
805
- }
806
- navigationBarAttrs = extracted.attrs;
807
- }
808
- const templates = [];
809
- const includes = [];
810
- const imports = [];
811
- const wxs = [];
812
- const wxsModules = /* @__PURE__ */ new Map();
813
- const renderNodesList = collectSpecialNodes(nodes, {
814
- templates,
815
- includes,
816
- imports,
817
- wxs,
818
- wxsModules,
819
- warnings,
820
- sourceId: options.id,
821
- resolveTemplate: (raw) => options.resolveTemplatePath(raw, options.id),
822
- resolveWxs: (raw) => options.resolveWxsPath(raw, options.id)
823
- });
824
- if (options.navigationBar && options.navigationBar.config.navigationStyle !== "custom") {
825
- const attrs = buildNavigationBarAttrs(options.navigationBar.config, navigationBarAttrs);
826
- renderNodesList.unshift({
827
- type: "element",
828
- name: "weapp-navigation-bar",
829
- attribs: attrs
830
- });
831
- }
832
- const importLines = [
833
- `import { html } from 'lit'`,
834
- `import { repeat } from 'lit/directives/repeat.js'`
835
- ];
836
- const bodyLines = [];
837
- const directDependencies = [];
838
- for (const entry of imports) {
839
- const importPath = normalizeTemplatePath(toRelativeImport(options.id, entry.id));
840
- importLines.push(`import { templates as ${entry.importName} } from '${importPath}'`);
841
- addDependency(entry.id, dependencyContext, directDependencies);
842
- }
843
- for (const entry of includes) {
844
- const importPath = normalizeTemplatePath(toRelativeImport(options.id, entry.id));
845
- importLines.push(`import { render as ${entry.importName} } from '${importPath}'`);
846
- addDependency(entry.id, dependencyContext, directDependencies);
847
- }
848
- for (const entry of wxs) {
849
- if (entry.kind === "src") {
850
- const baseImport = normalizeTemplatePath(toRelativeImport(options.id, entry.value));
851
- const importPath = shouldMarkWxsImport(entry.value) ? `${baseImport}?wxs` : baseImport;
852
- importLines.push(`import ${entry.importName} from '${importPath}'`);
853
- addDependency(entry.value, dependencyContext, directDependencies);
854
- }
855
- }
856
- if (templates.length > 0 || imports.length > 0) {
857
- const templatePairs = [];
858
- for (const entry of imports) {
859
- templatePairs.push(`...${entry.importName}`);
860
- }
861
- for (const template of templates) {
862
- const rendered = renderer.renderNodes(template.nodes, "scope", "__wxs_modules", options.componentTags);
863
- templatePairs.push(`${JSON.stringify(template.name)}: (scope, ctx) => ${rendered}`);
864
- }
865
- bodyLines.push(`const __templates = { ${templatePairs.join(", ")} }`);
866
- } else {
867
- bodyLines.push(`const __templates = {}`);
868
- }
869
- if (wxs.length > 0) {
870
- bodyLines.push(`const __wxs_inline_cache = Object.create(null)`);
871
- bodyLines.push(`let __wxs_modules = {}`);
872
- const wxsMapEntries = [];
873
- for (const entry of wxs) {
874
- if (entry.kind === "inline") {
875
- const inlineCode = entry.value.trim();
876
- const cacheKey = JSON.stringify(entry.module);
877
- if (inlineCode) {
878
- bodyLines.push(`function ${entry.importName}(ctx) {`);
879
- bodyLines.push(` if (!__wxs_inline_cache[${cacheKey}]) {`);
880
- bodyLines.push(` __wxs_inline_cache[${cacheKey}] = ctx.createWxsModule(${JSON.stringify(inlineCode)}, ${JSON.stringify(options.id)})`);
881
- bodyLines.push(` }`);
882
- bodyLines.push(` return __wxs_inline_cache[${cacheKey}]`);
883
- bodyLines.push(`}`);
884
- } else {
885
- bodyLines.push(`function ${entry.importName}() { return {} }`);
886
- }
887
- wxsMapEntries.push(`${JSON.stringify(entry.module)}: ${entry.importName}(ctx)`);
888
- continue;
889
- }
890
- wxsMapEntries.push(`${JSON.stringify(entry.module)}: ${entry.importName}`);
891
- }
892
- bodyLines.push(`function __resolveWxsModules(ctx) {`);
893
- bodyLines.push(` return { ${wxsMapEntries.join(", ")} }`);
894
- bodyLines.push(`}`);
895
- } else {
896
- bodyLines.push(`const __wxs_modules = {}`);
897
- }
898
- const includesRender = includes.map((entry) => `${entry.importName}(scope, ctx)`);
899
- const renderContent = renderer.renderNodes(renderNodesList, "scope", "__wxs_modules", options.componentTags);
900
- const contentExpr = includesRender.length > 0 ? `[${[...includesRender, renderContent].join(", ")}]` : renderContent;
901
- bodyLines.push(`export function render(scope, ctx) {`);
902
- if (wxs.length > 0) {
903
- bodyLines.push(` __wxs_modules = __resolveWxsModules(ctx)`);
904
- }
905
- bodyLines.push(` return ${contentExpr}`);
906
- bodyLines.push(`}`);
907
- bodyLines.push(`export const templates = __templates`);
908
- bodyLines.push(`export default render`);
909
- if (expandDependencies) {
910
- dependencyContext.visited.add(options.id);
911
- dependencyContext.active.add(options.id);
912
- expandDependencyTree(directDependencies, options.id);
913
- dependencyContext.active.delete(options.id);
914
- }
915
- const code = [...importLines, "", ...bodyLines].join("\n");
916
- const dependencies = expandDependencies ? dependencyContext.dependencies : directDependencies;
917
- return {
918
- code,
919
- dependencies,
920
- warnings: warnings.length > 0 ? warnings : void 0
921
- };
922
- }
923
-
924
- // src/compiler/wxs.ts
925
- var REQUIRE_RE = /require\(\s*['"]([^'"]+)['"]\s*\)/g;
926
- function normalizePath(p) {
927
- return p.split("\\\\").join("/");
632
+ const dependencyContext = options.dependencyContext ?? createDependencyContext();
633
+ const expandDependencies = options.expandDependencies ?? !options.dependencyContext;
634
+ const warnings = dependencyContext.warnings;
635
+ const expandDependencyTree = (dependencies, importer) => {
636
+ for (const target of dependencies) {
637
+ if (!target) continue;
638
+ if (dependencyContext.active.has(target)) {
639
+ warnCircularTemplate(dependencyContext, importer, target);
640
+ continue;
641
+ }
642
+ if (dependencyContext.visited.has(target)) continue;
643
+ dependencyContext.visited.add(target);
644
+ dependencyContext.active.add(target);
645
+ let source;
646
+ try {
647
+ source = readFileSync(target, "utf8");
648
+ } catch {
649
+ warnReadTemplate(dependencyContext, target);
650
+ dependencyContext.active.delete(target);
651
+ continue;
652
+ }
653
+ try {
654
+ expandDependencyTree(compileWxml({
655
+ id: target,
656
+ source,
657
+ resolveTemplatePath: options.resolveTemplatePath,
658
+ resolveWxsPath: options.resolveWxsPath,
659
+ dependencyContext,
660
+ expandDependencies: false
661
+ }).dependencies, target);
662
+ } catch (error) {
663
+ if (error instanceof Error && error.message) warnings.push(`[web] 无法解析模板依赖: ${target} ${error.message}`);
664
+ }
665
+ dependencyContext.active.delete(target);
666
+ }
667
+ };
668
+ let nodes = parseWxml(options.source);
669
+ let navigationBarAttrs;
670
+ if (options.navigationBar) {
671
+ const extracted = extractNavigationBarFromPageMeta(nodes);
672
+ nodes = extracted.nodes;
673
+ if (extracted.warnings.length > 0) warnings.push(...extracted.warnings);
674
+ navigationBarAttrs = extracted.attrs;
675
+ }
676
+ const templates = [];
677
+ const includes = [];
678
+ const imports = [];
679
+ const wxs = [];
680
+ const renderNodesList = collectSpecialNodes(nodes, {
681
+ templates,
682
+ includes,
683
+ imports,
684
+ wxs,
685
+ wxsModules: /* @__PURE__ */ new Map(),
686
+ warnings,
687
+ sourceId: options.id,
688
+ resolveTemplate: (raw) => options.resolveTemplatePath(raw, options.id),
689
+ resolveWxs: (raw) => options.resolveWxsPath(raw, options.id)
690
+ });
691
+ if (options.navigationBar && options.navigationBar.config.navigationStyle !== "custom") {
692
+ const attrs = buildNavigationBarAttrs(options.navigationBar.config, navigationBarAttrs);
693
+ renderNodesList.unshift({
694
+ type: "element",
695
+ name: "weapp-navigation-bar",
696
+ attribs: attrs
697
+ });
698
+ }
699
+ const importLines = [`import { html } from 'lit'`, `import { repeat } from 'lit/directives/repeat.js'`];
700
+ const bodyLines = [];
701
+ const directDependencies = [];
702
+ for (const entry of imports) {
703
+ const importPath = normalizeTemplatePath(toRelativeImport$1(options.id, entry.id));
704
+ importLines.push(`import { templates as ${entry.importName} } from '${importPath}'`);
705
+ addDependency(entry.id, dependencyContext, directDependencies);
706
+ }
707
+ for (const entry of includes) {
708
+ const importPath = normalizeTemplatePath(toRelativeImport$1(options.id, entry.id));
709
+ importLines.push(`import { render as ${entry.importName} } from '${importPath}'`);
710
+ addDependency(entry.id, dependencyContext, directDependencies);
711
+ }
712
+ for (const entry of wxs) if (entry.kind === "src") {
713
+ const baseImport = normalizeTemplatePath(toRelativeImport$1(options.id, entry.value));
714
+ const importPath = shouldMarkWxsImport(entry.value) ? `${baseImport}?wxs` : baseImport;
715
+ importLines.push(`import ${entry.importName} from '${importPath}'`);
716
+ addDependency(entry.value, dependencyContext, directDependencies);
717
+ }
718
+ if (templates.length > 0 || imports.length > 0) {
719
+ const templatePairs = [];
720
+ for (const entry of imports) templatePairs.push(`...${entry.importName}`);
721
+ for (const template of templates) {
722
+ const rendered = renderer.renderNodes(template.nodes, "scope", "__wxs_modules", options.componentTags);
723
+ templatePairs.push(`${JSON.stringify(template.name)}: (scope, ctx) => ${rendered}`);
724
+ }
725
+ bodyLines.push(`const __templates = { ${templatePairs.join(", ")} }`);
726
+ } else bodyLines.push(`const __templates = {}`);
727
+ if (wxs.length > 0) {
728
+ bodyLines.push(`const __wxs_inline_cache = Object.create(null)`);
729
+ bodyLines.push(`let __wxs_modules = {}`);
730
+ const wxsMapEntries = [];
731
+ for (const entry of wxs) {
732
+ if (entry.kind === "inline") {
733
+ const inlineCode = entry.value.trim();
734
+ const cacheKey = JSON.stringify(entry.module);
735
+ if (inlineCode) {
736
+ bodyLines.push(`function ${entry.importName}(ctx) {`);
737
+ bodyLines.push(` if (!__wxs_inline_cache[${cacheKey}]) {`);
738
+ bodyLines.push(` __wxs_inline_cache[${cacheKey}] = ctx.createWxsModule(${JSON.stringify(inlineCode)}, ${JSON.stringify(options.id)})`);
739
+ bodyLines.push(` }`);
740
+ bodyLines.push(` return __wxs_inline_cache[${cacheKey}]`);
741
+ bodyLines.push(`}`);
742
+ } else bodyLines.push(`function ${entry.importName}() { return {} }`);
743
+ wxsMapEntries.push(`${JSON.stringify(entry.module)}: ${entry.importName}(ctx)`);
744
+ continue;
745
+ }
746
+ wxsMapEntries.push(`${JSON.stringify(entry.module)}: ${entry.importName}`);
747
+ }
748
+ bodyLines.push(`function __resolveWxsModules(ctx) {`);
749
+ bodyLines.push(` return { ${wxsMapEntries.join(", ")} }`);
750
+ bodyLines.push(`}`);
751
+ } else bodyLines.push(`const __wxs_modules = {}`);
752
+ const includesRender = includes.map((entry) => `${entry.importName}(scope, ctx)`);
753
+ const renderContent = renderer.renderNodes(renderNodesList, "scope", "__wxs_modules", options.componentTags);
754
+ const contentExpr = includesRender.length > 0 ? `[${[...includesRender, renderContent].join(", ")}]` : renderContent;
755
+ bodyLines.push(`export function render(scope, ctx) {`);
756
+ if (wxs.length > 0) bodyLines.push(` __wxs_modules = __resolveWxsModules(ctx)`);
757
+ bodyLines.push(` return ${contentExpr}`);
758
+ bodyLines.push(`}`);
759
+ bodyLines.push(`export const templates = __templates`);
760
+ bodyLines.push(`export default render`);
761
+ if (expandDependencies) {
762
+ dependencyContext.visited.add(options.id);
763
+ dependencyContext.active.add(options.id);
764
+ expandDependencyTree(directDependencies, options.id);
765
+ dependencyContext.active.delete(options.id);
766
+ }
767
+ return {
768
+ code: [
769
+ ...importLines,
770
+ "",
771
+ ...bodyLines
772
+ ].join("\n"),
773
+ dependencies: expandDependencies ? dependencyContext.dependencies : directDependencies,
774
+ warnings: warnings.length > 0 ? warnings : void 0
775
+ };
776
+ }
777
+ //#endregion
778
+ //#region src/compiler/wxs.ts
779
+ const REQUIRE_RE = /require\(\s*['"]([^'"]+)['"]\s*\)/g;
780
+ function normalizePath$1(p) {
781
+ return p.split("\\\\").join("/");
928
782
  }
929
783
  function isPlainWxsScript(pathname) {
930
- const lower = pathname.toLowerCase();
931
- if (lower.endsWith(".wxs") || lower.endsWith(".wxs.ts") || lower.endsWith(".wxs.js")) {
932
- return false;
933
- }
934
- return lower.endsWith(".ts") || lower.endsWith(".js");
784
+ const lower = pathname.toLowerCase();
785
+ if (lower.endsWith(".wxs") || lower.endsWith(".wxs.ts") || lower.endsWith(".wxs.js")) return false;
786
+ return lower.endsWith(".ts") || lower.endsWith(".js");
935
787
  }
936
788
  function appendWxsQuery(pathname) {
937
- if (pathname.includes("?wxs") || pathname.includes("&wxs")) {
938
- return pathname;
939
- }
940
- return `${pathname}${pathname.includes("?") ? "&" : "?"}wxs`;
789
+ if (pathname.includes("?wxs") || pathname.includes("&wxs")) return pathname;
790
+ return `${pathname}${pathname.includes("?") ? "&" : "?"}wxs`;
941
791
  }
942
792
  function isSupportedRequirePath(request) {
943
- const normalized = request.replace(/\\/g, "/");
944
- return normalized.startsWith(".") || normalized.startsWith("/");
793
+ const normalized = request.replace(/\\/g, "/");
794
+ return normalized.startsWith(".") || normalized.startsWith("/");
945
795
  }
946
796
  function transformWxsToEsm(code, id, options) {
947
- const dependencies = [];
948
- const importLines = [];
949
- const mapEntries = [];
950
- const warnings = [];
951
- const seen = /* @__PURE__ */ new Set();
952
- while (true) {
953
- const match = REQUIRE_RE.exec(code);
954
- if (!match) {
955
- break;
956
- }
957
- const request = match[1];
958
- if (!request || seen.has(request)) {
959
- continue;
960
- }
961
- seen.add(request);
962
- if (!isSupportedRequirePath(request)) {
963
- warnings.push(`[@weapp-vite/web] WXS require \u4EC5\u652F\u6301\u76F8\u5BF9\u6216\u7EDD\u5BF9\u8DEF\u5F84: ${request} (from ${id})`);
964
- continue;
965
- }
966
- const normalizedRequest = request.replace(/\\/g, "/");
967
- const resolved = options.resolvePath(normalizedRequest, id);
968
- if (!resolved) {
969
- warnings.push(`[@weapp-vite/web] \u65E0\u6CD5\u89E3\u6790 WXS require: ${request} (from ${id})`);
970
- continue;
971
- }
972
- let importPath = normalizePath(options.toImportPath?.(resolved, id) ?? resolved);
973
- if (isPlainWxsScript(resolved)) {
974
- importPath = appendWxsQuery(importPath);
975
- }
976
- const importName = `__wxs_dep_${dependencies.length}`;
977
- importLines.push(`import ${importName} from '${importPath}'`);
978
- mapEntries.push(`[${JSON.stringify(request)}, ${importName}]`);
979
- dependencies.push(resolved);
980
- }
981
- const requireMap = `const __wxs_require_map = new Map([${mapEntries.join(", ")}])`;
982
- const requireFn = [
983
- `const __wxs_require_warned = new Set()`,
984
- `function require(id) {`,
985
- ` if (__wxs_require_map.has(id)) {`,
986
- ` return __wxs_require_map.get(id)`,
987
- ` }`,
988
- ` if (!__wxs_require_warned.has(id)) {`,
989
- ` __wxs_require_warned.add(id)`,
990
- ` if (typeof console !== 'undefined' && typeof console.warn === 'function') {`,
991
- ` console.warn(\`[@weapp-vite/web] WXS require \u672A\u89E3\u6790: \${id}\`)`,
992
- ` }`,
993
- ` }`,
994
- ` return undefined`,
995
- `}`
996
- ].join("\\n");
997
- const moduleInit = `const module = { exports: {} }\\nconst exports = module.exports`;
998
- const helpers = `const getRegExp = (pattern, flags) => new RegExp(pattern, flags)\\nconst getDate = (value) => (value == null ? new Date() : new Date(value))`;
999
- const body = [
1000
- ...importLines,
1001
- requireMap,
1002
- requireFn,
1003
- moduleInit,
1004
- helpers,
1005
- code,
1006
- `export default module.exports`
1007
- ].join("\\n");
1008
- return {
1009
- code: body,
1010
- dependencies,
1011
- warnings: warnings.length > 0 ? warnings : void 0
1012
- };
1013
- }
1014
-
1015
- // src/css/wxss.ts
1016
- var RPX_RE = /(-?(?:\d+(?:\.\d+)?|\.\d+))rpx/gi;
797
+ const dependencies = [];
798
+ const importLines = [];
799
+ const mapEntries = [];
800
+ const warnings = [];
801
+ const seen = /* @__PURE__ */ new Set();
802
+ while (true) {
803
+ const match = REQUIRE_RE.exec(code);
804
+ if (!match) break;
805
+ const request = match[1];
806
+ if (!request || seen.has(request)) continue;
807
+ seen.add(request);
808
+ if (!isSupportedRequirePath(request)) {
809
+ warnings.push(`[@weapp-vite/web] WXS require 仅支持相对或绝对路径: ${request} (from ${id})`);
810
+ continue;
811
+ }
812
+ const normalizedRequest = request.replace(/\\/g, "/");
813
+ const resolved = options.resolvePath(normalizedRequest, id);
814
+ if (!resolved) {
815
+ warnings.push(`[@weapp-vite/web] 无法解析 WXS require: ${request} (from ${id})`);
816
+ continue;
817
+ }
818
+ let importPath = normalizePath$1(options.toImportPath?.(resolved, id) ?? resolved);
819
+ if (isPlainWxsScript(resolved)) importPath = appendWxsQuery(importPath);
820
+ const importName = `__wxs_dep_${dependencies.length}`;
821
+ importLines.push(`import ${importName} from '${importPath}'`);
822
+ mapEntries.push(`[${JSON.stringify(request)}, ${importName}]`);
823
+ dependencies.push(resolved);
824
+ }
825
+ const requireMap = `const __wxs_require_map = new Map([${mapEntries.join(", ")}])`;
826
+ const requireFn = [
827
+ `const __wxs_require_warned = new Set()`,
828
+ `function require(id) {`,
829
+ ` if (__wxs_require_map.has(id)) {`,
830
+ ` return __wxs_require_map.get(id)`,
831
+ ` }`,
832
+ ` if (!__wxs_require_warned.has(id)) {`,
833
+ ` __wxs_require_warned.add(id)`,
834
+ ` if (typeof console !== 'undefined' && typeof console.warn === 'function') {`,
835
+ ` console.warn(\`[@weapp-vite/web] WXS require 未解析: \${id}\`)`,
836
+ ` }`,
837
+ ` }`,
838
+ ` return undefined`,
839
+ `}`
840
+ ].join("\\n");
841
+ const moduleInit = `const module = { exports: {} }\\nconst exports = module.exports`;
842
+ const helpers = `const getRegExp = (pattern, flags) => new RegExp(pattern, flags)\\nconst getDate = (value) => (value == null ? new Date() : new Date(value))`;
843
+ return {
844
+ code: [
845
+ ...importLines,
846
+ requireMap,
847
+ requireFn,
848
+ moduleInit,
849
+ helpers,
850
+ code,
851
+ `export default module.exports`
852
+ ].join("\\n"),
853
+ dependencies,
854
+ warnings: warnings.length > 0 ? warnings : void 0
855
+ };
856
+ }
857
+ //#endregion
858
+ //#region src/css/wxss.ts
859
+ const RPX_RE = /(-?(?:\d+(?:\.\d+)?|\.\d+))rpx/gi;
1017
860
  function transformWxssToCss(source, options) {
1018
- const rpxVar = options?.rpxVar ?? "--rpx";
1019
- const useVariable = typeof options?.designWidth === "number" && Number.isFinite(options.designWidth);
1020
- const ratio = options?.pxPerRpx ?? 0.5;
1021
- const css = source.replace(RPX_RE, (_, value) => {
1022
- const numeric = Number.parseFloat(value);
1023
- if (Number.isNaN(numeric)) {
1024
- return `${value}px`;
1025
- }
1026
- if (useVariable) {
1027
- return `calc(var(${rpxVar}) * ${numeric})`;
1028
- }
1029
- const converted = Math.round(numeric * ratio * 1e3) / 1e3;
1030
- return `${converted}px`;
1031
- });
1032
- return {
1033
- css
1034
- };
1035
- }
1036
-
1037
- // src/plugin/constants.ts
1038
- var SCRIPT_EXTS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
1039
- var STYLE_EXTS = [".wxss", ".scss", ".less", ".css"];
1040
- var TRANSFORM_STYLE_EXTS = [".wxss"];
1041
- var TEMPLATE_EXTS = [".wxml", ".axml", ".swan", ".ttml", ".qml", ".ksml", ".xhsml", ".html"];
1042
- var WXS_EXTS = [".wxs", ".wxs.ts", ".wxs.js"];
1043
- var WXS_RESOLVE_EXTS = [".wxs", ".wxs.ts", ".wxs.js", ".ts", ".js"];
1044
- var ENTRY_ID = "\0@weapp-vite/web/entry";
1045
-
1046
- // src/plugin/path.ts
1047
- import fs from "fs-extra";
1048
- import { dirname as dirname2, extname, normalize, posix, relative as relative2, resolve } from "pathe";
861
+ const rpxVar = options?.rpxVar ?? "--rpx";
862
+ const useVariable = typeof options?.designWidth === "number" && Number.isFinite(options.designWidth);
863
+ const ratio = options?.pxPerRpx ?? .5;
864
+ return { css: source.replace(RPX_RE, (_, value) => {
865
+ const numeric = Number.parseFloat(value);
866
+ if (Number.isNaN(numeric)) return `${value}px`;
867
+ if (useVariable) return `calc(var(${rpxVar}) * ${numeric})`;
868
+ return `${Math.round(numeric * ratio * 1e3) / 1e3}px`;
869
+ }) };
870
+ }
871
+ //#endregion
872
+ //#region src/plugin/constants.ts
873
+ const SCRIPT_EXTS = [
874
+ ".ts",
875
+ ".tsx",
876
+ ".js",
877
+ ".jsx",
878
+ ".mjs",
879
+ ".cjs"
880
+ ];
881
+ const STYLE_EXTS = [
882
+ ".wxss",
883
+ ".scss",
884
+ ".less",
885
+ ".css"
886
+ ];
887
+ const TRANSFORM_STYLE_EXTS = [".wxss"];
888
+ const TEMPLATE_EXTS = [
889
+ ".wxml",
890
+ ".axml",
891
+ ".swan",
892
+ ".ttml",
893
+ ".qml",
894
+ ".ksml",
895
+ ".xhsml",
896
+ ".html"
897
+ ];
898
+ const WXS_EXTS = [
899
+ ".wxs",
900
+ ".wxs.ts",
901
+ ".wxs.js"
902
+ ];
903
+ const WXS_RESOLVE_EXTS = [
904
+ ".wxs",
905
+ ".wxs.ts",
906
+ ".wxs.js",
907
+ ".ts",
908
+ ".js"
909
+ ];
910
+ const ENTRY_ID = "\0@weapp-vite/web/entry";
911
+ //#endregion
912
+ //#region src/plugin/path.ts
1049
913
  function cleanUrl(url) {
1050
- const queryIndex = url.indexOf("?");
1051
- if (queryIndex >= 0) {
1052
- return url.slice(0, queryIndex);
1053
- }
1054
- return url;
914
+ const queryIndex = url.indexOf("?");
915
+ if (queryIndex >= 0) return url.slice(0, queryIndex);
916
+ return url;
1055
917
  }
1056
- function normalizePath2(p) {
1057
- return posix.normalize(p.split("\\").join("/"));
918
+ function normalizePath(p) {
919
+ return posix.normalize(p.split("\\").join("/"));
1058
920
  }
1059
921
  function isInsideDir(filePath, dir) {
1060
- const rel = relative2(dir, filePath);
1061
- return rel === "" || !rel.startsWith("..") && !posix.isAbsolute(rel);
922
+ const rel = relative(dir, filePath);
923
+ return rel === "" || !rel.startsWith("..") && !posix.isAbsolute(rel);
1062
924
  }
1063
925
  function isHtmlEntry(filePath, root) {
1064
- if (!filePath.toLowerCase().endsWith(".html")) {
1065
- return false;
1066
- }
1067
- return normalizePath2(filePath) === normalizePath2(resolve(root, "index.html"));
926
+ if (!filePath.toLowerCase().endsWith(".html")) return false;
927
+ return normalizePath(filePath) === normalizePath(resolve(root, "index.html"));
1068
928
  }
1069
929
  function toPosixId(id) {
1070
- return normalize(id).split("\\").join("/");
930
+ return normalize(id).split("\\").join("/");
1071
931
  }
1072
- function toRelativeImport2(from, target) {
1073
- const fromDir = dirname2(from);
1074
- const rel = relative2(fromDir, target);
1075
- if (!rel || rel.startsWith(".")) {
1076
- return normalizePath2(rel || `./${posix.basename(target)}`);
1077
- }
1078
- return `./${normalizePath2(rel)}`;
932
+ function toRelativeImport(from, target) {
933
+ const rel = relative(dirname(from), target);
934
+ if (!rel || rel.startsWith(".")) return normalizePath(rel || `./${posix.basename(target)}`);
935
+ return `./${normalizePath(rel)}`;
1079
936
  }
1080
937
  function appendInlineQuery(id) {
1081
- if (id.includes("?")) {
1082
- if (id.includes("?inline") || id.includes("&inline")) {
1083
- return id;
1084
- }
1085
- return `${id}&inline`;
1086
- }
1087
- return `${id}?inline`;
938
+ if (id.includes("?")) {
939
+ if (id.includes("?inline") || id.includes("&inline")) return id;
940
+ return `${id}&inline`;
941
+ }
942
+ return `${id}?inline`;
1088
943
  }
1089
944
  function relativeModuleId(root, absPath) {
1090
- const rel = relative2(root, absPath);
1091
- return `/${normalizePath2(rel)}`;
945
+ return `/${normalizePath(relative(root, absPath))}`;
1092
946
  }
1093
947
  function resolveImportBase(raw, importer, srcRoot) {
1094
- if (!raw) {
1095
- return void 0;
1096
- }
1097
- if (raw.startsWith(".")) {
1098
- return resolve(dirname2(importer), raw);
1099
- }
1100
- if (raw.startsWith("/")) {
1101
- return resolve(srcRoot, raw.slice(1));
1102
- }
1103
- return resolve(srcRoot, raw);
948
+ if (!raw) return;
949
+ if (raw.startsWith(".")) return resolve(dirname(importer), raw);
950
+ if (raw.startsWith("/")) return resolve(srcRoot, raw.slice(1));
951
+ return resolve(srcRoot, raw);
1104
952
  }
1105
953
  function resolveFileWithExtensionsSync(basePath, extensions) {
1106
- if (extname(basePath) && fs.pathExistsSync(basePath)) {
1107
- return basePath;
1108
- }
1109
- for (const ext of extensions) {
1110
- const candidate = `${basePath}${ext}`;
1111
- if (fs.pathExistsSync(candidate)) {
1112
- return candidate;
1113
- }
1114
- }
1115
- return void 0;
954
+ if (extname(basePath) && fs.pathExistsSync(basePath)) return basePath;
955
+ for (const ext of extensions) {
956
+ const candidate = `${basePath}${ext}`;
957
+ if (fs.pathExistsSync(candidate)) return candidate;
958
+ }
1116
959
  }
1117
960
  function resolveTemplatePathSync(raw, importer, srcRoot) {
1118
- const base = resolveImportBase(raw, importer, srcRoot);
1119
- if (!base) {
1120
- return void 0;
1121
- }
1122
- return resolveFileWithExtensionsSync(base, TEMPLATE_EXTS);
961
+ const base = resolveImportBase(raw, importer, srcRoot);
962
+ if (!base) return;
963
+ return resolveFileWithExtensionsSync(base, TEMPLATE_EXTS);
1123
964
  }
1124
965
  function resolveWxsPathSync(raw, importer, srcRoot) {
1125
- if (!raw) {
1126
- return void 0;
1127
- }
1128
- let base;
1129
- if (raw.startsWith(".")) {
1130
- base = resolve(dirname2(importer), raw);
1131
- } else if (raw.startsWith("/")) {
1132
- base = resolve(srcRoot, raw.slice(1));
1133
- } else {
1134
- return void 0;
1135
- }
1136
- return resolveFileWithExtensionsSync(base, WXS_RESOLVE_EXTS);
1137
- }
1138
-
1139
- // src/plugin/entry.ts
966
+ if (!raw) return;
967
+ let base;
968
+ if (raw.startsWith(".")) base = resolve(dirname(importer), raw);
969
+ else if (raw.startsWith("/")) base = resolve(srcRoot, raw.slice(1));
970
+ else return;
971
+ return resolveFileWithExtensionsSync(base, WXS_RESOLVE_EXTS);
972
+ }
973
+ //#endregion
974
+ //#region src/plugin/entry.ts
1140
975
  function generateEntryModule(result, root, wxssOptions, pluginOptions) {
1141
- const importLines = [`import { initializePageRoutes } from '@weapp-vite/web/runtime/polyfill'`];
1142
- const bodyLines = [];
1143
- for (const page of result.pages) {
1144
- importLines.push(`import '${relativeModuleId(root, page.script)}'`);
1145
- }
1146
- for (const component of result.components) {
1147
- importLines.push(`import '${relativeModuleId(root, component.script)}'`);
1148
- }
1149
- if (result.app) {
1150
- importLines.push(`import '${relativeModuleId(root, result.app)}'`);
1151
- }
1152
- const pageOrder = result.pages.map((page) => page.id);
1153
- const rpxConfig = wxssOptions?.designWidth ? { designWidth: wxssOptions.designWidth, varName: wxssOptions.rpxVar } : void 0;
1154
- const initOptions = {};
1155
- if (rpxConfig) {
1156
- initOptions.rpx = rpxConfig;
1157
- }
1158
- if (pluginOptions?.form?.preventDefault !== void 0) {
1159
- initOptions.form = { preventDefault: pluginOptions.form.preventDefault };
1160
- }
1161
- const runtimeOptions = {};
1162
- if (pluginOptions?.runtime?.executionMode) {
1163
- runtimeOptions.executionMode = pluginOptions.runtime.executionMode;
1164
- }
1165
- if (pluginOptions?.runtime?.warnings) {
1166
- runtimeOptions.warnings = pluginOptions.runtime.warnings;
1167
- }
1168
- if (Object.keys(runtimeOptions).length > 0) {
1169
- initOptions.runtime = runtimeOptions;
1170
- }
1171
- const initOptionsCode = Object.keys(initOptions).length > 0 ? `, ${JSON.stringify(initOptions)}` : "";
1172
- bodyLines.push(`initializePageRoutes(${JSON.stringify(pageOrder)}${initOptionsCode})`);
1173
- return [...importLines, ...bodyLines].join("\n");
1174
- }
1175
-
1176
- // src/plugin/register.ts
1177
- import { parse } from "@babel/parser";
1178
- import _babelTraverse from "@babel/traverse";
1179
- import * as t from "@babel/types";
1180
- import MagicString from "magic-string";
1181
- var traverseCandidate = (() => {
1182
- const mod = _babelTraverse;
1183
- if (typeof mod === "function") {
1184
- return mod;
1185
- }
1186
- if (mod?.default && typeof mod.default === "function") {
1187
- return mod.default;
1188
- }
1189
- if (mod?.traverse && typeof mod.traverse === "function") {
1190
- return mod.traverse;
1191
- }
1192
- return void 0;
976
+ const importLines = [`import { initializePageRoutes } from '@weapp-vite/web/runtime/polyfill'`];
977
+ const bodyLines = [];
978
+ for (const page of result.pages) importLines.push(`import '${relativeModuleId(root, page.script)}'`);
979
+ for (const component of result.components) importLines.push(`import '${relativeModuleId(root, component.script)}'`);
980
+ if (result.app) importLines.push(`import '${relativeModuleId(root, result.app)}'`);
981
+ const pageOrder = result.pages.map((page) => page.id);
982
+ const rpxConfig = wxssOptions?.designWidth ? {
983
+ designWidth: wxssOptions.designWidth,
984
+ varName: wxssOptions.rpxVar
985
+ } : void 0;
986
+ const initOptions = {};
987
+ if (rpxConfig) initOptions.rpx = rpxConfig;
988
+ if (pluginOptions?.form?.preventDefault !== void 0) initOptions.form = { preventDefault: pluginOptions.form.preventDefault };
989
+ const runtimeOptions = {};
990
+ if (pluginOptions?.runtime?.executionMode) runtimeOptions.executionMode = pluginOptions.runtime.executionMode;
991
+ if (pluginOptions?.runtime?.warnings) runtimeOptions.warnings = pluginOptions.runtime.warnings;
992
+ if (Object.keys(runtimeOptions).length > 0) initOptions.runtime = runtimeOptions;
993
+ const initOptionsCode = Object.keys(initOptions).length > 0 ? `, ${JSON.stringify(initOptions)}` : "";
994
+ bodyLines.push(`initializePageRoutes(${JSON.stringify(pageOrder)}${initOptionsCode})`);
995
+ return [...importLines, ...bodyLines].join("\n");
996
+ }
997
+ //#endregion
998
+ //#region src/plugin/register.ts
999
+ const traverseCandidate = (() => {
1000
+ const mod = _babelTraverse;
1001
+ if (typeof mod === "function") return mod;
1002
+ if (mod?.default && typeof mod.default === "function") return mod.default;
1003
+ if (mod?.traverse && typeof mod.traverse === "function") return mod.traverse;
1193
1004
  })();
1194
- if (typeof traverseCandidate !== "function") {
1195
- throw new TypeError("[@weapp-vite/web] Failed to resolve @babel/traverse export.");
1196
- }
1197
- var traverse = traverseCandidate;
1005
+ if (typeof traverseCandidate !== "function") throw new TypeError("[@weapp-vite/web] Failed to resolve @babel/traverse export.");
1006
+ const traverse = traverseCandidate;
1198
1007
  function mapRegisterIdentifier(kind) {
1199
- if (kind === "page") {
1200
- return "Page";
1201
- }
1202
- if (kind === "component") {
1203
- return "Component";
1204
- }
1205
- if (kind === "app") {
1206
- return "App";
1207
- }
1208
- return "";
1008
+ if (kind === "page") return "Page";
1009
+ if (kind === "component") return "Component";
1010
+ if (kind === "app") return "App";
1011
+ return "";
1209
1012
  }
1210
1013
  function getRegisterName(kind) {
1211
- if (kind === "page") {
1212
- return "registerPage";
1213
- }
1214
- if (kind === "component") {
1215
- return "registerComponent";
1216
- }
1217
- if (kind === "app") {
1218
- return "registerApp";
1219
- }
1220
- return void 0;
1014
+ if (kind === "page") return "registerPage";
1015
+ if (kind === "component") return "registerComponent";
1016
+ if (kind === "app") return "registerApp";
1221
1017
  }
1222
1018
  function overwriteCall(path, meta, registerName, templateIdent, styleIdent, s) {
1223
- const node = path.node;
1224
- const callee = node.callee;
1225
- if (!t.isIdentifier(callee)) {
1226
- return;
1227
- }
1228
- const end = node.end;
1229
- const insertPosition = end - 1;
1230
- const metaParts = [`id: ${JSON.stringify(meta.id)}`];
1231
- if (templateIdent) {
1232
- metaParts.push(`template: ${templateIdent}`);
1233
- }
1234
- if (styleIdent) {
1235
- metaParts.push(`style: ${styleIdent}`);
1236
- }
1237
- const metaCode = `{ ${metaParts.join(", ")} }`;
1238
- s.overwrite(callee.start, callee.end, registerName);
1239
- s.appendLeft(insertPosition, `, ${metaCode}`);
1240
- }
1241
- function transformScriptModule({
1242
- code,
1243
- cleanId,
1244
- meta,
1245
- enableHmr
1246
- }) {
1247
- const registerName = getRegisterName(meta.kind);
1248
- if (!registerName) {
1249
- return null;
1250
- }
1251
- let ast;
1252
- try {
1253
- ast = parse(code, {
1254
- sourceType: "module",
1255
- plugins: ["typescript", "jsx"],
1256
- errorRecovery: true,
1257
- ranges: true
1258
- });
1259
- } catch {
1260
- return null;
1261
- }
1262
- const s = new MagicString(code);
1263
- let transformed = false;
1264
- const imports = [];
1265
- const templateIdent = meta.templatePath ? "__weapp_template__" : void 0;
1266
- const styleIdent = meta.stylePath ? "__weapp_style__" : void 0;
1267
- if (meta.templatePath && templateIdent) {
1268
- imports.push(`import ${templateIdent} from '${toRelativeImport2(cleanId, meta.templatePath)}'`);
1269
- }
1270
- if (meta.stylePath && styleIdent) {
1271
- imports.push(`import ${styleIdent} from '${appendInlineQuery(toRelativeImport2(cleanId, meta.stylePath))}'`);
1272
- }
1273
- const registerImports = /* @__PURE__ */ new Set();
1274
- traverse(ast, {
1275
- CallExpression(path) {
1276
- if (!t.isIdentifier(path.node.callee)) {
1277
- return;
1278
- }
1279
- const name = path.node.callee.name;
1280
- if (name === mapRegisterIdentifier(meta.kind)) {
1281
- registerImports.add(registerName);
1282
- overwriteCall(path, meta, registerName, templateIdent, styleIdent, s);
1283
- transformed = true;
1284
- }
1285
- }
1286
- });
1287
- if (!transformed) {
1288
- return null;
1289
- }
1290
- if (registerImports.size > 0) {
1291
- imports.unshift(`import { ${Array.from(registerImports).join(", ")} } from '@weapp-vite/web/runtime/polyfill'`);
1292
- }
1293
- const prefix = `${imports.join("\n")}
1294
- `;
1295
- s.prepend(prefix);
1296
- if (enableHmr) {
1297
- s.append(`
1298
- if (import.meta.hot) { import.meta.hot.accept() }
1299
- `);
1300
- }
1301
- return {
1302
- code: s.toString(),
1303
- map: s.generateMap({
1304
- hires: true
1305
- })
1306
- };
1307
- }
1308
-
1309
- // src/plugin/scan.ts
1310
- import process from "process";
1311
- import { dirname as dirname3, extname as extname3, join, posix as posix2, relative as relative3, resolve as resolve2 } from "pathe";
1312
-
1313
- // src/shared/slugify.ts
1019
+ const node = path.node;
1020
+ const callee = node.callee;
1021
+ if (!t.isIdentifier(callee)) return;
1022
+ const insertPosition = node.end - 1;
1023
+ const metaParts = [`id: ${JSON.stringify(meta.id)}`];
1024
+ if (templateIdent) metaParts.push(`template: ${templateIdent}`);
1025
+ if (styleIdent) metaParts.push(`style: ${styleIdent}`);
1026
+ const metaCode = `{ ${metaParts.join(", ")} }`;
1027
+ s.overwrite(callee.start, callee.end, registerName);
1028
+ s.appendLeft(insertPosition, `, ${metaCode}`);
1029
+ }
1030
+ function transformScriptModule({ code, cleanId, meta, enableHmr }) {
1031
+ const registerName = getRegisterName(meta.kind);
1032
+ if (!registerName) return null;
1033
+ let ast;
1034
+ try {
1035
+ ast = parse(code, {
1036
+ sourceType: "module",
1037
+ plugins: ["typescript", "jsx"],
1038
+ errorRecovery: true,
1039
+ ranges: true
1040
+ });
1041
+ } catch {
1042
+ return null;
1043
+ }
1044
+ const s = new MagicString(code);
1045
+ let transformed = false;
1046
+ const imports = [];
1047
+ const templateIdent = meta.templatePath ? "__weapp_template__" : void 0;
1048
+ const styleIdent = meta.stylePath ? "__weapp_style__" : void 0;
1049
+ if (meta.templatePath && templateIdent) imports.push(`import ${templateIdent} from '${toRelativeImport(cleanId, meta.templatePath)}'`);
1050
+ if (meta.stylePath && styleIdent) imports.push(`import ${styleIdent} from '${appendInlineQuery(toRelativeImport(cleanId, meta.stylePath))}'`);
1051
+ const registerImports = /* @__PURE__ */ new Set();
1052
+ traverse(ast, { CallExpression(path) {
1053
+ if (!t.isIdentifier(path.node.callee)) return;
1054
+ if (path.node.callee.name === mapRegisterIdentifier(meta.kind)) {
1055
+ registerImports.add(registerName);
1056
+ overwriteCall(path, meta, registerName, templateIdent, styleIdent, s);
1057
+ transformed = true;
1058
+ }
1059
+ } });
1060
+ if (!transformed) return null;
1061
+ if (registerImports.size > 0) imports.unshift(`import { ${Array.from(registerImports).join(", ")} } from '@weapp-vite/web/runtime/polyfill'`);
1062
+ const prefix = `${imports.join("\n")}\n`;
1063
+ s.prepend(prefix);
1064
+ if (enableHmr) s.append(`\nif (import.meta.hot) { import.meta.hot.accept() }\n`);
1065
+ return {
1066
+ code: s.toString(),
1067
+ map: s.generateMap({ hires: true })
1068
+ };
1069
+ }
1070
+ //#endregion
1071
+ //#region src/shared/slugify.ts
1314
1072
  function slugify(id, prefix) {
1315
- const normalized = id.replace(/[^a-z0-9]+/gi, "-").replace(/^-+|-+$/g, "").toLowerCase();
1316
- return `${prefix}-${normalized || "index"}`;
1073
+ return `${prefix}-${id.replace(/[^a-z0-9]+/gi, "-").replace(/^-+|-+$/g, "").toLowerCase() || "index"}`;
1317
1074
  }
1318
-
1319
- // src/plugin/files.ts
1320
- import fs2 from "fs-extra";
1321
- import { extname as extname2 } from "pathe";
1322
- import { bundleRequire } from "rolldown-require";
1075
+ //#endregion
1076
+ //#region src/plugin/files.ts
1323
1077
  function isRecord(value) {
1324
- return typeof value === "object" && value !== null && !Array.isArray(value);
1078
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1325
1079
  }
1326
1080
  async function readJsonFile(pathname) {
1327
- const candidates = [pathname];
1328
- if (pathname.endsWith(".json")) {
1329
- candidates.push(`${pathname}.ts`, `${pathname}.js`);
1330
- }
1331
- for (const candidate of candidates) {
1332
- if (!await fs2.pathExists(candidate)) {
1333
- continue;
1334
- }
1335
- if (candidate.endsWith(".json")) {
1336
- const json = await fs2.readJson(candidate).catch(() => void 0);
1337
- if (!isRecord(json)) {
1338
- return void 0;
1339
- }
1340
- return json;
1341
- }
1342
- const { mod } = await bundleRequire({
1343
- filepath: candidate,
1344
- preserveTemporaryFile: true
1345
- });
1346
- const resolved = typeof mod.default === "function" ? await mod.default() : mod.default;
1347
- if (!isRecord(resolved)) {
1348
- return void 0;
1349
- }
1350
- return resolved;
1351
- }
1352
- return void 0;
1081
+ const candidates = [pathname];
1082
+ if (pathname.endsWith(".json")) candidates.push(`${pathname}.ts`, `${pathname}.js`);
1083
+ for (const candidate of candidates) {
1084
+ if (!await fs.pathExists(candidate)) continue;
1085
+ if (candidate.endsWith(".json")) {
1086
+ const json = await fs.readJson(candidate).catch(() => void 0);
1087
+ if (!isRecord(json)) return;
1088
+ return json;
1089
+ }
1090
+ const { mod } = await bundleRequire({
1091
+ filepath: candidate,
1092
+ preserveTemporaryFile: true
1093
+ });
1094
+ const resolved = typeof mod.default === "function" ? await mod.default() : mod.default;
1095
+ if (!isRecord(resolved)) return;
1096
+ return resolved;
1097
+ }
1353
1098
  }
1354
1099
  async function resolveJsonPath(basePath) {
1355
- const candidates = [basePath];
1356
- if (basePath.endsWith(".json")) {
1357
- candidates.push(`${basePath}.ts`, `${basePath}.js`);
1358
- }
1359
- for (const candidate of candidates) {
1360
- if (await fs2.pathExists(candidate)) {
1361
- return candidate;
1362
- }
1363
- }
1364
- return void 0;
1100
+ const candidates = [basePath];
1101
+ if (basePath.endsWith(".json")) candidates.push(`${basePath}.ts`, `${basePath}.js`);
1102
+ for (const candidate of candidates) if (await fs.pathExists(candidate)) return candidate;
1365
1103
  }
1366
1104
  async function resolveScriptFile(basePath) {
1367
- const ext = extname2(basePath);
1368
- if (ext && await fs2.pathExists(basePath)) {
1369
- return basePath;
1370
- }
1371
- for (const candidateExt of SCRIPT_EXTS) {
1372
- const candidate = `${basePath}${candidateExt}`;
1373
- if (await fs2.pathExists(candidate)) {
1374
- return candidate;
1375
- }
1376
- }
1377
- return void 0;
1105
+ if (extname(basePath) && await fs.pathExists(basePath)) return basePath;
1106
+ for (const candidateExt of SCRIPT_EXTS) {
1107
+ const candidate = `${basePath}${candidateExt}`;
1108
+ if (await fs.pathExists(candidate)) return candidate;
1109
+ }
1378
1110
  }
1379
1111
  async function resolveStyleFile(scriptPath) {
1380
- const base = scriptPath.replace(new RegExp(`${extname2(scriptPath)}$`), "");
1381
- for (const ext of STYLE_EXTS) {
1382
- const candidate = `${base}${ext}`;
1383
- if (await fs2.pathExists(candidate)) {
1384
- return candidate;
1385
- }
1386
- }
1387
- return void 0;
1112
+ const base = scriptPath.replace(new RegExp(`${extname(scriptPath)}$`), "");
1113
+ for (const ext of STYLE_EXTS) {
1114
+ const candidate = `${base}${ext}`;
1115
+ if (await fs.pathExists(candidate)) return candidate;
1116
+ }
1388
1117
  }
1389
1118
  async function resolveTemplateFile(scriptPath) {
1390
- const base = scriptPath.replace(new RegExp(`${extname2(scriptPath)}$`), "");
1391
- for (const ext of TEMPLATE_EXTS) {
1392
- const candidate = `${base}${ext}`;
1393
- if (await fs2.pathExists(candidate)) {
1394
- return candidate;
1395
- }
1396
- }
1397
- return void 0;
1398
- }
1399
-
1400
- // src/plugin/navigation.ts
1119
+ const base = scriptPath.replace(new RegExp(`${extname(scriptPath)}$`), "");
1120
+ for (const ext of TEMPLATE_EXTS) {
1121
+ const candidate = `${base}${ext}`;
1122
+ if (await fs.pathExists(candidate)) return candidate;
1123
+ }
1124
+ }
1125
+ //#endregion
1126
+ //#region src/plugin/navigation.ts
1401
1127
  function pickNavigationConfig(source) {
1402
- const config = {};
1403
- if (!source) {
1404
- return config;
1405
- }
1406
- if (typeof source.navigationBarTitleText === "string") {
1407
- config.title = source.navigationBarTitleText;
1408
- }
1409
- if (typeof source.navigationBarBackgroundColor === "string") {
1410
- config.backgroundColor = source.navigationBarBackgroundColor;
1411
- }
1412
- if (typeof source.navigationBarTextStyle === "string") {
1413
- config.textStyle = source.navigationBarTextStyle;
1414
- }
1415
- if (typeof source.navigationStyle === "string") {
1416
- config.navigationStyle = source.navigationStyle;
1417
- }
1418
- return config;
1128
+ const config = {};
1129
+ if (!source) return config;
1130
+ if (typeof source.navigationBarTitleText === "string") config.title = source.navigationBarTitleText;
1131
+ if (typeof source.navigationBarBackgroundColor === "string") config.backgroundColor = source.navigationBarBackgroundColor;
1132
+ if (typeof source.navigationBarTextStyle === "string") config.textStyle = source.navigationBarTextStyle;
1133
+ if (typeof source.navigationStyle === "string") config.navigationStyle = source.navigationStyle;
1134
+ return config;
1419
1135
  }
1420
1136
  function mergeNavigationConfig(base, overrides) {
1421
- return {
1422
- ...base,
1423
- ...overrides
1424
- };
1425
- }
1426
-
1427
- // src/plugin/scanConfig.ts
1428
- async function collectComponentTagsFromConfig({
1429
- json,
1430
- importerDir,
1431
- jsonPath,
1432
- warn,
1433
- resolveComponentScript,
1434
- getComponentTag,
1435
- collectComponent,
1436
- onResolved
1437
- }) {
1438
- const usingComponents = json.usingComponents;
1439
- if (!usingComponents || typeof usingComponents !== "object") {
1440
- return {};
1441
- }
1442
- const tags = {};
1443
- const resolved = [];
1444
- for (const [rawKey, rawValue] of Object.entries(usingComponents)) {
1445
- if (typeof rawValue !== "string") {
1446
- continue;
1447
- }
1448
- const key = normalizeComponentKey(rawKey);
1449
- if (!key) {
1450
- continue;
1451
- }
1452
- const script = await resolveComponentScript(rawValue, importerDir);
1453
- if (!script) {
1454
- warn(`[@weapp-vite/web] usingComponents entry "${rawKey}" not found: ${rawValue} (${jsonPath})`);
1455
- continue;
1456
- }
1457
- const tag = getComponentTag(script);
1458
- tags[key] = tag;
1459
- resolved.push({ rawValue });
1460
- }
1461
- onResolved?.(tags);
1462
- for (const entry of resolved) {
1463
- await collectComponent(entry.rawValue, importerDir);
1464
- }
1465
- return tags;
1466
- }
1467
- async function collectComponentTagsFromJson({
1468
- jsonBasePath,
1469
- importerDir,
1470
- warn,
1471
- collectFromConfig
1472
- }) {
1473
- const resolvedPath = await resolveJsonPath(jsonBasePath);
1474
- if (!resolvedPath) {
1475
- return {};
1476
- }
1477
- const json = await readJsonFile(resolvedPath);
1478
- if (!json) {
1479
- return {};
1480
- }
1481
- return collectFromConfig(json, importerDir, resolvedPath, warn);
1137
+ return {
1138
+ ...base,
1139
+ ...overrides
1140
+ };
1141
+ }
1142
+ //#endregion
1143
+ //#region src/plugin/scanConfig.ts
1144
+ async function collectComponentTagsFromConfig({ json, importerDir, jsonPath, warn, resolveComponentScript, getComponentTag, collectComponent, onResolved }) {
1145
+ const usingComponents = json.usingComponents;
1146
+ if (!usingComponents || typeof usingComponents !== "object") return {};
1147
+ const tags = {};
1148
+ const resolved = [];
1149
+ for (const [rawKey, rawValue] of Object.entries(usingComponents)) {
1150
+ if (typeof rawValue !== "string") continue;
1151
+ const key = normalizeComponentKey(rawKey);
1152
+ if (!key) continue;
1153
+ const script = await resolveComponentScript(rawValue, importerDir);
1154
+ if (!script) {
1155
+ warn(`[@weapp-vite/web] usingComponents entry "${rawKey}" not found: ${rawValue} (${jsonPath})`);
1156
+ continue;
1157
+ }
1158
+ tags[key] = getComponentTag(script);
1159
+ resolved.push({ rawValue });
1160
+ }
1161
+ onResolved?.(tags);
1162
+ for (const entry of resolved) await collectComponent(entry.rawValue, importerDir);
1163
+ return tags;
1164
+ }
1165
+ async function collectComponentTagsFromJson({ jsonBasePath, importerDir, warn, collectFromConfig }) {
1166
+ const resolvedPath = await resolveJsonPath(jsonBasePath);
1167
+ if (!resolvedPath) return {};
1168
+ const json = await readJsonFile(resolvedPath);
1169
+ if (!json) return {};
1170
+ return collectFromConfig(json, importerDir, resolvedPath, warn);
1482
1171
  }
1483
1172
  function mergeComponentTags(base, overrides) {
1484
- if (!Object.keys(base).length && !Object.keys(overrides).length) {
1485
- return {};
1486
- }
1487
- return {
1488
- ...base,
1489
- ...overrides
1490
- };
1173
+ if (!Object.keys(base).length && !Object.keys(overrides).length) return {};
1174
+ return {
1175
+ ...base,
1176
+ ...overrides
1177
+ };
1491
1178
  }
1492
1179
  function normalizeComponentKey(raw) {
1493
- return raw.trim().toLowerCase();
1180
+ return raw.trim().toLowerCase();
1494
1181
  }
1495
-
1496
- // src/plugin/scan.ts
1182
+ //#endregion
1183
+ //#region src/plugin/scan.ts
1497
1184
  async function scanProject({ srcRoot, warn, state }) {
1498
- state.moduleMeta.clear();
1499
- state.pageNavigationMap.clear();
1500
- state.templateComponentMap.clear();
1501
- state.templatePathSet.clear();
1502
- state.componentTagMap.clear();
1503
- state.componentIdMap.clear();
1504
- let appNavigationDefaults = {};
1505
- let appComponentTags = {};
1506
- const pages = /* @__PURE__ */ new Map();
1507
- const components = /* @__PURE__ */ new Map();
1508
- const reportWarning = (message) => {
1509
- if (warn) {
1510
- warn(message);
1511
- return;
1512
- }
1513
- if (typeof process !== "undefined" && typeof process.emitWarning === "function") {
1514
- process.emitWarning(message);
1515
- }
1516
- };
1517
- const appScript = await resolveScriptFile(join(srcRoot, "app"));
1518
- if (appScript) {
1519
- state.moduleMeta.set(normalizePath2(appScript), {
1520
- kind: "app",
1521
- id: "app",
1522
- scriptPath: appScript,
1523
- stylePath: await resolveStyleFile(appScript)
1524
- });
1525
- }
1526
- const resolveComponentScript = async (raw, importerDir) => {
1527
- const base = resolveComponentBase(raw, importerDir, srcRoot);
1528
- if (!base) {
1529
- return void 0;
1530
- }
1531
- return resolveScriptFile(base);
1532
- };
1533
- const getComponentId = (script) => {
1534
- const cached = state.componentIdMap.get(script);
1535
- if (cached) {
1536
- return cached;
1537
- }
1538
- const idRelative = relative3(srcRoot, script).replace(new RegExp(`${extname3(script)}$`), "");
1539
- const componentIdPosix = toPosixId(idRelative);
1540
- state.componentIdMap.set(script, componentIdPosix);
1541
- return componentIdPosix;
1542
- };
1543
- const getComponentTag = (script) => {
1544
- const cached = state.componentTagMap.get(script);
1545
- if (cached) {
1546
- return cached;
1547
- }
1548
- const id = getComponentId(script);
1549
- const tag = slugify(id, "wv-component");
1550
- state.componentTagMap.set(script, tag);
1551
- return tag;
1552
- };
1553
- const collectComponent = async (componentId, importerDir) => {
1554
- const base = resolveComponentBase(componentId, importerDir, srcRoot);
1555
- const script = base ? await resolveScriptFile(base) : void 0;
1556
- if (!script || components.has(script)) {
1557
- return;
1558
- }
1559
- const idRelative = relative3(srcRoot, script).replace(new RegExp(`${extname3(script)}$`), "");
1560
- const componentIdPosix = toPosixId(idRelative);
1561
- const template = await resolveTemplateFile(script);
1562
- const style = await resolveStyleFile(script);
1563
- if (template) {
1564
- state.templatePathSet.add(normalizePath2(template));
1565
- }
1566
- state.moduleMeta.set(normalizePath2(script), {
1567
- kind: "component",
1568
- id: componentIdPosix,
1569
- scriptPath: script,
1570
- templatePath: template,
1571
- stylePath: style
1572
- });
1573
- components.set(script, { script, id: componentIdPosix });
1574
- const componentJsonBasePath = `${script.replace(new RegExp(`${extname3(script)}$`), "")}.json`;
1575
- const componentTags = await collectComponentTagsFromJson({
1576
- jsonBasePath: componentJsonBasePath,
1577
- importerDir: dirname3(script),
1578
- warn: reportWarning,
1579
- collectFromConfig: (json, nextImporterDir, jsonPath, nextWarn) => collectComponentTagsFromConfig({
1580
- json,
1581
- importerDir: nextImporterDir,
1582
- jsonPath,
1583
- warn: nextWarn,
1584
- resolveComponentScript,
1585
- getComponentTag,
1586
- collectComponent
1587
- })
1588
- });
1589
- if (!template) {
1590
- return;
1591
- }
1592
- const mergedTags = mergeComponentTags(appComponentTags, componentTags);
1593
- if (Object.keys(mergedTags).length > 0) {
1594
- state.templateComponentMap.set(normalizePath2(template), mergedTags);
1595
- return;
1596
- }
1597
- state.templateComponentMap.delete(normalizePath2(template));
1598
- };
1599
- const appJsonBasePath = join(srcRoot, "app.json");
1600
- const appJsonPath = await resolveJsonPath(appJsonBasePath);
1601
- if (appJsonPath) {
1602
- const appJson = await readJsonFile(appJsonPath);
1603
- if (appJson) {
1604
- appComponentTags = await collectComponentTagsFromConfig({
1605
- json: appJson,
1606
- importerDir: srcRoot,
1607
- jsonPath: appJsonPath,
1608
- warn: reportWarning,
1609
- resolveComponentScript,
1610
- getComponentTag,
1611
- collectComponent,
1612
- onResolved: (tags) => {
1613
- appComponentTags = tags;
1614
- }
1615
- });
1616
- }
1617
- if (appJson?.pages && Array.isArray(appJson.pages)) {
1618
- for (const page of appJson.pages) {
1619
- if (typeof page === "string") {
1620
- await collectPage(page);
1621
- }
1622
- }
1623
- }
1624
- if (appJson?.subPackages && Array.isArray(appJson.subPackages)) {
1625
- for (const pkg of appJson.subPackages) {
1626
- if (!pkg || typeof pkg !== "object" || !Array.isArray(pkg.pages)) {
1627
- continue;
1628
- }
1629
- const root = typeof pkg.root === "string" ? pkg.root : "";
1630
- for (const page of pkg.pages) {
1631
- if (typeof page !== "string") {
1632
- continue;
1633
- }
1634
- await collectPage(posix2.join(root, page));
1635
- }
1636
- }
1637
- }
1638
- const windowConfig = isRecord(appJson?.window) ? appJson.window : void 0;
1639
- appNavigationDefaults = pickNavigationConfig(windowConfig);
1640
- }
1641
- state.appNavigationDefaults = appNavigationDefaults;
1642
- state.appComponentTags = appComponentTags;
1643
- state.scanResult = {
1644
- app: appScript,
1645
- pages: Array.from(pages.values()),
1646
- components: Array.from(components.values())
1647
- };
1648
- async function collectPage(pageId) {
1649
- const base = join(srcRoot, pageId);
1650
- const script = await resolveScriptFile(base);
1651
- if (!script) {
1652
- return;
1653
- }
1654
- const template = await resolveTemplateFile(base);
1655
- if (template) {
1656
- state.templatePathSet.add(normalizePath2(template));
1657
- }
1658
- const style = await resolveStyleFile(base);
1659
- const pageJsonBasePath = join(srcRoot, `${pageId}.json`);
1660
- const pageJsonPath = await resolveJsonPath(pageJsonBasePath);
1661
- const pageJson = pageJsonPath ? await readJsonFile(pageJsonPath) : void 0;
1662
- state.moduleMeta.set(normalizePath2(script), {
1663
- kind: "page",
1664
- id: toPosixId(pageId),
1665
- scriptPath: script,
1666
- templatePath: template,
1667
- stylePath: style
1668
- });
1669
- pages.set(script, {
1670
- script,
1671
- id: toPosixId(pageId)
1672
- });
1673
- const pageComponentTags = pageJson && pageJsonPath ? await collectComponentTagsFromConfig({
1674
- json: pageJson,
1675
- importerDir: dirname3(script),
1676
- jsonPath: pageJsonPath,
1677
- warn: reportWarning,
1678
- resolveComponentScript,
1679
- getComponentTag,
1680
- collectComponent
1681
- }) : await collectComponentTagsFromJson({
1682
- jsonBasePath: pageJsonBasePath,
1683
- importerDir: dirname3(script),
1684
- warn: reportWarning,
1685
- collectFromConfig: (json, importerDir, jsonPath, nextWarn) => collectComponentTagsFromConfig({
1686
- json,
1687
- importerDir,
1688
- jsonPath,
1689
- warn: nextWarn,
1690
- resolveComponentScript,
1691
- getComponentTag,
1692
- collectComponent
1693
- })
1694
- });
1695
- if (template) {
1696
- const mergedTags = mergeComponentTags(appComponentTags, pageComponentTags);
1697
- if (Object.keys(mergedTags).length > 0) {
1698
- state.templateComponentMap.set(normalizePath2(template), mergedTags);
1699
- } else {
1700
- state.templateComponentMap.delete(normalizePath2(template));
1701
- }
1702
- }
1703
- if (!template) {
1704
- return;
1705
- }
1706
- if (pageJson) {
1707
- state.pageNavigationMap.set(
1708
- normalizePath2(template),
1709
- mergeNavigationConfig(appNavigationDefaults, pickNavigationConfig(pageJson))
1710
- );
1711
- return;
1712
- }
1713
- state.pageNavigationMap.set(normalizePath2(template), { ...appNavigationDefaults });
1714
- }
1185
+ state.moduleMeta.clear();
1186
+ state.pageNavigationMap.clear();
1187
+ state.templateComponentMap.clear();
1188
+ state.templatePathSet.clear();
1189
+ state.componentTagMap.clear();
1190
+ state.componentIdMap.clear();
1191
+ let appNavigationDefaults = {};
1192
+ let appComponentTags = {};
1193
+ const pages = /* @__PURE__ */ new Map();
1194
+ const components = /* @__PURE__ */ new Map();
1195
+ const reportWarning = (message) => {
1196
+ if (warn) {
1197
+ warn(message);
1198
+ return;
1199
+ }
1200
+ if (typeof process !== "undefined" && typeof process.emitWarning === "function") process.emitWarning(message);
1201
+ };
1202
+ const appScript = await resolveScriptFile(join(srcRoot, "app"));
1203
+ if (appScript) state.moduleMeta.set(normalizePath(appScript), {
1204
+ kind: "app",
1205
+ id: "app",
1206
+ scriptPath: appScript,
1207
+ stylePath: await resolveStyleFile(appScript)
1208
+ });
1209
+ const resolveComponentScript = async (raw, importerDir) => {
1210
+ const base = resolveComponentBase(raw, importerDir, srcRoot);
1211
+ if (!base) return;
1212
+ return resolveScriptFile(base);
1213
+ };
1214
+ const getComponentId = (script) => {
1215
+ const cached = state.componentIdMap.get(script);
1216
+ if (cached) return cached;
1217
+ const componentIdPosix = toPosixId(relative(srcRoot, script).replace(new RegExp(`${extname(script)}$`), ""));
1218
+ state.componentIdMap.set(script, componentIdPosix);
1219
+ return componentIdPosix;
1220
+ };
1221
+ const getComponentTag = (script) => {
1222
+ const cached = state.componentTagMap.get(script);
1223
+ if (cached) return cached;
1224
+ const tag = slugify(getComponentId(script), "wv-component");
1225
+ state.componentTagMap.set(script, tag);
1226
+ return tag;
1227
+ };
1228
+ const collectComponent = async (componentId, importerDir) => {
1229
+ const base = resolveComponentBase(componentId, importerDir, srcRoot);
1230
+ const script = base ? await resolveScriptFile(base) : void 0;
1231
+ if (!script || components.has(script)) return;
1232
+ const componentIdPosix = toPosixId(relative(srcRoot, script).replace(new RegExp(`${extname(script)}$`), ""));
1233
+ const template = await resolveTemplateFile(script);
1234
+ const style = await resolveStyleFile(script);
1235
+ if (template) state.templatePathSet.add(normalizePath(template));
1236
+ state.moduleMeta.set(normalizePath(script), {
1237
+ kind: "component",
1238
+ id: componentIdPosix,
1239
+ scriptPath: script,
1240
+ templatePath: template,
1241
+ stylePath: style
1242
+ });
1243
+ components.set(script, {
1244
+ script,
1245
+ id: componentIdPosix
1246
+ });
1247
+ const componentTags = await collectComponentTagsFromJson({
1248
+ jsonBasePath: `${script.replace(new RegExp(`${extname(script)}$`), "")}.json`,
1249
+ importerDir: dirname(script),
1250
+ warn: reportWarning,
1251
+ collectFromConfig: (json, nextImporterDir, jsonPath, nextWarn) => collectComponentTagsFromConfig({
1252
+ json,
1253
+ importerDir: nextImporterDir,
1254
+ jsonPath,
1255
+ warn: nextWarn,
1256
+ resolveComponentScript,
1257
+ getComponentTag,
1258
+ collectComponent
1259
+ })
1260
+ });
1261
+ if (!template) return;
1262
+ const mergedTags = mergeComponentTags(appComponentTags, componentTags);
1263
+ if (Object.keys(mergedTags).length > 0) {
1264
+ state.templateComponentMap.set(normalizePath(template), mergedTags);
1265
+ return;
1266
+ }
1267
+ state.templateComponentMap.delete(normalizePath(template));
1268
+ };
1269
+ const appJsonPath = await resolveJsonPath(join(srcRoot, "app.json"));
1270
+ if (appJsonPath) {
1271
+ const appJson = await readJsonFile(appJsonPath);
1272
+ if (appJson) appComponentTags = await collectComponentTagsFromConfig({
1273
+ json: appJson,
1274
+ importerDir: srcRoot,
1275
+ jsonPath: appJsonPath,
1276
+ warn: reportWarning,
1277
+ resolveComponentScript,
1278
+ getComponentTag,
1279
+ collectComponent,
1280
+ onResolved: (tags) => {
1281
+ appComponentTags = tags;
1282
+ }
1283
+ });
1284
+ if (appJson?.pages && Array.isArray(appJson.pages)) {
1285
+ for (const page of appJson.pages) if (typeof page === "string") await collectPage(page);
1286
+ }
1287
+ if (appJson?.subPackages && Array.isArray(appJson.subPackages)) for (const pkg of appJson.subPackages) {
1288
+ if (!pkg || typeof pkg !== "object" || !Array.isArray(pkg.pages)) continue;
1289
+ const root = typeof pkg.root === "string" ? pkg.root : "";
1290
+ for (const page of pkg.pages) {
1291
+ if (typeof page !== "string") continue;
1292
+ await collectPage(posix.join(root, page));
1293
+ }
1294
+ }
1295
+ appNavigationDefaults = pickNavigationConfig(isRecord(appJson?.window) ? appJson.window : void 0);
1296
+ }
1297
+ state.appNavigationDefaults = appNavigationDefaults;
1298
+ state.appComponentTags = appComponentTags;
1299
+ state.scanResult = {
1300
+ app: appScript,
1301
+ pages: Array.from(pages.values()),
1302
+ components: Array.from(components.values())
1303
+ };
1304
+ async function collectPage(pageId) {
1305
+ const base = join(srcRoot, pageId);
1306
+ const script = await resolveScriptFile(base);
1307
+ if (!script) return;
1308
+ const template = await resolveTemplateFile(base);
1309
+ if (template) state.templatePathSet.add(normalizePath(template));
1310
+ const style = await resolveStyleFile(base);
1311
+ const pageJsonBasePath = join(srcRoot, `${pageId}.json`);
1312
+ const pageJsonPath = await resolveJsonPath(pageJsonBasePath);
1313
+ const pageJson = pageJsonPath ? await readJsonFile(pageJsonPath) : void 0;
1314
+ state.moduleMeta.set(normalizePath(script), {
1315
+ kind: "page",
1316
+ id: toPosixId(pageId),
1317
+ scriptPath: script,
1318
+ templatePath: template,
1319
+ stylePath: style
1320
+ });
1321
+ pages.set(script, {
1322
+ script,
1323
+ id: toPosixId(pageId)
1324
+ });
1325
+ const pageComponentTags = pageJson && pageJsonPath ? await collectComponentTagsFromConfig({
1326
+ json: pageJson,
1327
+ importerDir: dirname(script),
1328
+ jsonPath: pageJsonPath,
1329
+ warn: reportWarning,
1330
+ resolveComponentScript,
1331
+ getComponentTag,
1332
+ collectComponent
1333
+ }) : await collectComponentTagsFromJson({
1334
+ jsonBasePath: pageJsonBasePath,
1335
+ importerDir: dirname(script),
1336
+ warn: reportWarning,
1337
+ collectFromConfig: (json, importerDir, jsonPath, nextWarn) => collectComponentTagsFromConfig({
1338
+ json,
1339
+ importerDir,
1340
+ jsonPath,
1341
+ warn: nextWarn,
1342
+ resolveComponentScript,
1343
+ getComponentTag,
1344
+ collectComponent
1345
+ })
1346
+ });
1347
+ if (template) {
1348
+ const mergedTags = mergeComponentTags(appComponentTags, pageComponentTags);
1349
+ if (Object.keys(mergedTags).length > 0) state.templateComponentMap.set(normalizePath(template), mergedTags);
1350
+ else state.templateComponentMap.delete(normalizePath(template));
1351
+ }
1352
+ if (!template) return;
1353
+ if (pageJson) {
1354
+ state.pageNavigationMap.set(normalizePath(template), mergeNavigationConfig(appNavigationDefaults, pickNavigationConfig(pageJson)));
1355
+ return;
1356
+ }
1357
+ state.pageNavigationMap.set(normalizePath(template), { ...appNavigationDefaults });
1358
+ }
1715
1359
  }
1716
1360
  function resolveComponentBase(raw, importerDir, srcRoot) {
1717
- if (!raw) {
1718
- return void 0;
1719
- }
1720
- if (raw.startsWith(".")) {
1721
- return resolve2(importerDir, raw);
1722
- }
1723
- if (raw.startsWith("/")) {
1724
- return resolve2(srcRoot, raw.slice(1));
1725
- }
1726
- return resolve2(srcRoot, raw);
1727
- }
1728
-
1729
- // src/plugin/state.ts
1361
+ if (!raw) return;
1362
+ if (raw.startsWith(".")) return resolve(importerDir, raw);
1363
+ if (raw.startsWith("/")) return resolve(srcRoot, raw.slice(1));
1364
+ return resolve(srcRoot, raw);
1365
+ }
1366
+ //#endregion
1367
+ //#region src/plugin/state.ts
1730
1368
  function createEmptyScanState() {
1731
- return {
1732
- moduleMeta: /* @__PURE__ */ new Map(),
1733
- pageNavigationMap: /* @__PURE__ */ new Map(),
1734
- templateComponentMap: /* @__PURE__ */ new Map(),
1735
- templatePathSet: /* @__PURE__ */ new Set(),
1736
- componentTagMap: /* @__PURE__ */ new Map(),
1737
- componentIdMap: /* @__PURE__ */ new Map(),
1738
- appNavigationDefaults: {},
1739
- appComponentTags: {},
1740
- scanResult: {
1741
- app: void 0,
1742
- pages: [],
1743
- components: []
1744
- }
1745
- };
1746
- }
1747
-
1748
- // src/plugin/index.ts
1369
+ return {
1370
+ moduleMeta: /* @__PURE__ */ new Map(),
1371
+ pageNavigationMap: /* @__PURE__ */ new Map(),
1372
+ templateComponentMap: /* @__PURE__ */ new Map(),
1373
+ templatePathSet: /* @__PURE__ */ new Set(),
1374
+ componentTagMap: /* @__PURE__ */ new Map(),
1375
+ componentIdMap: /* @__PURE__ */ new Map(),
1376
+ appNavigationDefaults: {},
1377
+ appComponentTags: {},
1378
+ scanResult: {
1379
+ app: void 0,
1380
+ pages: [],
1381
+ components: []
1382
+ }
1383
+ };
1384
+ }
1385
+ //#endregion
1386
+ //#region src/plugin/index.ts
1749
1387
  function isTemplateFile(id) {
1750
- const lower = id.toLowerCase();
1751
- return TEMPLATE_EXTS.some((ext) => lower.endsWith(ext));
1388
+ const lower = id.toLowerCase();
1389
+ return TEMPLATE_EXTS.some((ext) => lower.endsWith(ext));
1752
1390
  }
1753
1391
  function isWxsFile(id) {
1754
- const lower = id.toLowerCase();
1755
- return WXS_EXTS.some((ext) => lower.endsWith(ext));
1392
+ const lower = id.toLowerCase();
1393
+ return WXS_EXTS.some((ext) => lower.endsWith(ext));
1756
1394
  }
1757
1395
  function hasWxsQuery(id) {
1758
- return id.includes("?wxs") || id.includes("&wxs");
1396
+ return id.includes("?wxs") || id.includes("&wxs");
1759
1397
  }
1760
1398
  function createInlineStyleModule(css) {
1761
- const serialized = JSON.stringify(css);
1762
- return [
1763
- `const __weapp_injected_styles__ = new Map()`,
1764
- `function __weapp_createStyleId__(css) {`,
1765
- ` let hash = 2166136261`,
1766
- ` for (let i = 0; i < css.length; i++) {`,
1767
- ` hash ^= css.charCodeAt(i)`,
1768
- ` hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24)`,
1769
- ` }`,
1770
- ` return 'weapp-web-style-' + (hash >>> 0).toString(36)`,
1771
- `}`,
1772
- `function __weapp_removeStyle__(id) {`,
1773
- ` if (typeof document === 'undefined') {`,
1774
- ` return`,
1775
- ` }`,
1776
- ` const style = __weapp_injected_styles__.get(id)`,
1777
- ` if (style) {`,
1778
- ` style.remove()`,
1779
- ` __weapp_injected_styles__.delete(id)`,
1780
- ` }`,
1781
- `}`,
1782
- `function injectStyle(css, id) {`,
1783
- ` if (typeof document === 'undefined') {`,
1784
- ` return () => {}`,
1785
- ` }`,
1786
- ` const styleId = id ?? __weapp_createStyleId__(css)`,
1787
- ` const existing = __weapp_injected_styles__.get(styleId)`,
1788
- ` if (existing) {`,
1789
- ` if (existing.textContent !== css) {`,
1790
- ` existing.textContent = css`,
1791
- ` }`,
1792
- ` return () => __weapp_removeStyle__(styleId)`,
1793
- ` }`,
1794
- ` const style = document.createElement('style')`,
1795
- ` style.id = styleId`,
1796
- ` style.textContent = css`,
1797
- ` document.head.append(style)`,
1798
- ` __weapp_injected_styles__.set(styleId, style)`,
1799
- ` return () => __weapp_removeStyle__(styleId)`,
1800
- `}`,
1801
- `const css = ${serialized}`,
1802
- `export default css`,
1803
- `export function useStyle(id) {`,
1804
- ` return injectStyle(css, id)`,
1805
- `}`
1806
- ].join("\n");
1399
+ return [
1400
+ `const __weapp_injected_styles__ = new Map()`,
1401
+ `function __weapp_createStyleId__(css) {`,
1402
+ ` let hash = 2166136261`,
1403
+ ` for (let i = 0; i < css.length; i++) {`,
1404
+ ` hash ^= css.charCodeAt(i)`,
1405
+ ` hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24)`,
1406
+ ` }`,
1407
+ ` return 'weapp-web-style-' + (hash >>> 0).toString(36)`,
1408
+ `}`,
1409
+ `function __weapp_removeStyle__(id) {`,
1410
+ ` if (typeof document === 'undefined') {`,
1411
+ ` return`,
1412
+ ` }`,
1413
+ ` const style = __weapp_injected_styles__.get(id)`,
1414
+ ` if (style) {`,
1415
+ ` style.remove()`,
1416
+ ` __weapp_injected_styles__.delete(id)`,
1417
+ ` }`,
1418
+ `}`,
1419
+ `function injectStyle(css, id) {`,
1420
+ ` if (typeof document === 'undefined') {`,
1421
+ ` return () => {}`,
1422
+ ` }`,
1423
+ ` const styleId = id ?? __weapp_createStyleId__(css)`,
1424
+ ` const existing = __weapp_injected_styles__.get(styleId)`,
1425
+ ` if (existing) {`,
1426
+ ` if (existing.textContent !== css) {`,
1427
+ ` existing.textContent = css`,
1428
+ ` }`,
1429
+ ` return () => __weapp_removeStyle__(styleId)`,
1430
+ ` }`,
1431
+ ` const style = document.createElement('style')`,
1432
+ ` style.id = styleId`,
1433
+ ` style.textContent = css`,
1434
+ ` document.head.append(style)`,
1435
+ ` __weapp_injected_styles__.set(styleId, style)`,
1436
+ ` return () => __weapp_removeStyle__(styleId)`,
1437
+ `}`,
1438
+ `const css = ${JSON.stringify(css)}`,
1439
+ `export default css`,
1440
+ `export function useStyle(id) {`,
1441
+ ` return injectStyle(css, id)`,
1442
+ `}`
1443
+ ].join("\n");
1807
1444
  }
1808
1445
  function weappWebPlugin(options = {}) {
1809
- let root = process2.cwd();
1810
- let srcRoot = resolve3(root, options.srcDir ?? "src");
1811
- let enableHmr = false;
1812
- const state = createEmptyScanState();
1813
- const wxssOptions = options.wxss;
1814
- const resolveTemplatePath = (raw, importer) => resolveTemplatePathSync(raw, importer, srcRoot);
1815
- const resolveWxsPath = (raw, importer) => resolveWxsPathSync(raw, importer, srcRoot);
1816
- return {
1817
- name: "@weapp-vite/web",
1818
- enforce: "pre",
1819
- async configResolved(config) {
1820
- root = config.root;
1821
- srcRoot = resolve3(root, options.srcDir ?? "src");
1822
- enableHmr = config.command === "serve";
1823
- await scanProject({ srcRoot, warn: this.warn?.bind(this), state });
1824
- },
1825
- async buildStart() {
1826
- await scanProject({ srcRoot, warn: this.warn?.bind(this), state });
1827
- },
1828
- resolveId(id) {
1829
- if (id === "/@weapp-vite/web/entry" || id === "@weapp-vite/web/entry") {
1830
- return ENTRY_ID;
1831
- }
1832
- return null;
1833
- },
1834
- load(id) {
1835
- if (id === ENTRY_ID) {
1836
- return generateEntryModule(state.scanResult, root, wxssOptions, options);
1837
- }
1838
- return null;
1839
- },
1840
- async handleHotUpdate(ctx) {
1841
- const clean = cleanUrl(ctx.file);
1842
- if (clean.endsWith(".json") || isTemplateFile(clean) || isWxsFile(clean) || clean.endsWith(".wxss") || SCRIPT_EXTS.includes(extname4(clean))) {
1843
- await scanProject({ srcRoot, warn: this.warn?.bind(this), state });
1844
- }
1845
- },
1846
- transform(code, id) {
1847
- const clean = cleanUrl(id);
1848
- if (isTemplateFile(clean)) {
1849
- if (isHtmlEntry(clean, root)) {
1850
- return null;
1851
- }
1852
- const normalizedId = normalizePath2(clean);
1853
- if (state.templatePathSet.size > 0) {
1854
- if (!isInsideDir(clean, srcRoot)) {
1855
- return null;
1856
- }
1857
- if (!state.templatePathSet.has(normalizedId)) {
1858
- return null;
1859
- }
1860
- }
1861
- const navigationConfig = state.pageNavigationMap.get(normalizedId);
1862
- const componentTags = state.templateComponentMap.get(normalizedId);
1863
- const { code: compiled, dependencies, warnings } = compileWxml({
1864
- id: clean,
1865
- source: code,
1866
- resolveTemplatePath,
1867
- resolveWxsPath,
1868
- navigationBar: navigationConfig ? { config: navigationConfig } : void 0,
1869
- componentTags
1870
- });
1871
- if (dependencies.length > 0 && "addWatchFile" in this) {
1872
- for (const dep of dependencies) {
1873
- this.addWatchFile(dep);
1874
- }
1875
- }
1876
- if (warnings?.length && "warn" in this) {
1877
- for (const warning of warnings) {
1878
- this.warn(warning);
1879
- }
1880
- }
1881
- return { code: compiled, map: null };
1882
- }
1883
- if (isWxsFile(clean) || hasWxsQuery(id)) {
1884
- const { code: compiled, dependencies, warnings } = transformWxsToEsm(code, clean, {
1885
- resolvePath: resolveWxsPath,
1886
- toImportPath: (resolved, importer) => normalizePath2(toRelativeImport2(importer, resolved))
1887
- });
1888
- if (dependencies.length > 0 && "addWatchFile" in this) {
1889
- for (const dep of dependencies) {
1890
- this.addWatchFile(dep);
1891
- }
1892
- }
1893
- if (warnings?.length && "warn" in this) {
1894
- for (const warning of warnings) {
1895
- this.warn(warning);
1896
- }
1897
- }
1898
- return { code: compiled, map: null };
1899
- }
1900
- if (TRANSFORM_STYLE_EXTS.some((ext) => clean.endsWith(ext))) {
1901
- const { css } = transformWxssToCss(code, wxssOptions);
1902
- return {
1903
- code: createInlineStyleModule(css),
1904
- map: null
1905
- };
1906
- }
1907
- if (STYLE_EXTS.some((ext) => clean.endsWith(ext)) && !clean.endsWith(".wxss")) {
1908
- const { css } = transformWxssToCss(code, wxssOptions);
1909
- return { code: css, map: null };
1910
- }
1911
- if (!SCRIPT_EXTS.some((ext) => clean.endsWith(ext))) {
1912
- return null;
1913
- }
1914
- if (clean.includes("node_modules")) {
1915
- return null;
1916
- }
1917
- const meta = state.moduleMeta.get(normalizePath2(clean));
1918
- if (!meta) {
1919
- return null;
1920
- }
1921
- return transformScriptModule({
1922
- code,
1923
- cleanId: clean,
1924
- meta,
1925
- enableHmr
1926
- });
1927
- }
1928
- };
1929
- }
1930
- export {
1931
- weappWebPlugin
1932
- };
1446
+ let root = process.cwd();
1447
+ let srcRoot = resolve(root, options.srcDir ?? "src");
1448
+ let enableHmr = false;
1449
+ const state = createEmptyScanState();
1450
+ const wxssOptions = options.wxss;
1451
+ const resolveTemplatePath = (raw, importer) => resolveTemplatePathSync(raw, importer, srcRoot);
1452
+ const resolveWxsPath = (raw, importer) => resolveWxsPathSync(raw, importer, srcRoot);
1453
+ return {
1454
+ name: "@weapp-vite/web",
1455
+ enforce: "pre",
1456
+ async configResolved(config) {
1457
+ root = config.root;
1458
+ srcRoot = resolve(root, options.srcDir ?? "src");
1459
+ enableHmr = config.command === "serve";
1460
+ await scanProject({
1461
+ srcRoot,
1462
+ warn: this.warn?.bind(this),
1463
+ state
1464
+ });
1465
+ },
1466
+ async buildStart() {
1467
+ await scanProject({
1468
+ srcRoot,
1469
+ warn: this.warn?.bind(this),
1470
+ state
1471
+ });
1472
+ },
1473
+ resolveId(id) {
1474
+ if (id === "/@weapp-vite/web/entry" || id === "@weapp-vite/web/entry") return ENTRY_ID;
1475
+ return null;
1476
+ },
1477
+ load(id) {
1478
+ if (id === "\0@weapp-vite/web/entry") return generateEntryModule(state.scanResult, root, wxssOptions, options);
1479
+ return null;
1480
+ },
1481
+ async handleHotUpdate(ctx) {
1482
+ const clean = cleanUrl(ctx.file);
1483
+ if (clean.endsWith(".json") || isTemplateFile(clean) || isWxsFile(clean) || clean.endsWith(".wxss") || SCRIPT_EXTS.includes(extname(clean))) await scanProject({
1484
+ srcRoot,
1485
+ warn: this.warn?.bind(this),
1486
+ state
1487
+ });
1488
+ },
1489
+ transform(code, id) {
1490
+ const clean = cleanUrl(id);
1491
+ if (isTemplateFile(clean)) {
1492
+ if (isHtmlEntry(clean, root)) return null;
1493
+ const normalizedId = normalizePath(clean);
1494
+ if (state.templatePathSet.size > 0) {
1495
+ if (!isInsideDir(clean, srcRoot)) return null;
1496
+ if (!state.templatePathSet.has(normalizedId)) return null;
1497
+ }
1498
+ const navigationConfig = state.pageNavigationMap.get(normalizedId);
1499
+ const componentTags = state.templateComponentMap.get(normalizedId);
1500
+ const { code: compiled, dependencies, warnings } = compileWxml({
1501
+ id: clean,
1502
+ source: code,
1503
+ resolveTemplatePath,
1504
+ resolveWxsPath,
1505
+ navigationBar: navigationConfig ? { config: navigationConfig } : void 0,
1506
+ componentTags
1507
+ });
1508
+ if (dependencies.length > 0 && "addWatchFile" in this) for (const dep of dependencies) this.addWatchFile(dep);
1509
+ if (warnings?.length && "warn" in this) for (const warning of warnings) this.warn(warning);
1510
+ return {
1511
+ code: compiled,
1512
+ map: null
1513
+ };
1514
+ }
1515
+ if (isWxsFile(clean) || hasWxsQuery(id)) {
1516
+ const { code: compiled, dependencies, warnings } = transformWxsToEsm(code, clean, {
1517
+ resolvePath: resolveWxsPath,
1518
+ toImportPath: (resolved, importer) => normalizePath(toRelativeImport(importer, resolved))
1519
+ });
1520
+ if (dependencies.length > 0 && "addWatchFile" in this) for (const dep of dependencies) this.addWatchFile(dep);
1521
+ if (warnings?.length && "warn" in this) for (const warning of warnings) this.warn(warning);
1522
+ return {
1523
+ code: compiled,
1524
+ map: null
1525
+ };
1526
+ }
1527
+ if (TRANSFORM_STYLE_EXTS.some((ext) => clean.endsWith(ext))) {
1528
+ const { css } = transformWxssToCss(code, wxssOptions);
1529
+ return {
1530
+ code: createInlineStyleModule(css),
1531
+ map: null
1532
+ };
1533
+ }
1534
+ if (STYLE_EXTS.some((ext) => clean.endsWith(ext)) && !clean.endsWith(".wxss")) {
1535
+ const { css } = transformWxssToCss(code, wxssOptions);
1536
+ return {
1537
+ code: css,
1538
+ map: null
1539
+ };
1540
+ }
1541
+ if (!SCRIPT_EXTS.some((ext) => clean.endsWith(ext))) return null;
1542
+ if (clean.includes("node_modules")) return null;
1543
+ const meta = state.moduleMeta.get(normalizePath(clean));
1544
+ if (!meta) return null;
1545
+ return transformScriptModule({
1546
+ code,
1547
+ cleanId: clean,
1548
+ meta,
1549
+ enableHmr
1550
+ });
1551
+ }
1552
+ };
1553
+ }
1554
+ //#endregion
1555
+ export { weappWebPlugin };