@weapp-vite/web 1.2.4 → 1.3.1

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,150 +1,41 @@
1
- // src/plugin.ts
2
- import process from "process";
3
- import { parse } from "@babel/parser";
4
- import _babelTraverse from "@babel/traverse";
5
- import * as t from "@babel/types";
6
- import fs from "fs-extra";
7
- import MagicString from "magic-string";
8
- import { dirname as dirname2, extname, join, normalize, posix, relative as relative2, resolve } from "pathe";
9
- import { bundleRequire } from "rolldown-require";
1
+ // src/plugin/index.ts
2
+ import process2 from "process";
3
+ import { extname as extname4, resolve as resolve3 } from "pathe";
10
4
 
11
- // src/compiler/wxml.ts
5
+ // src/compiler/wxml/compile.ts
12
6
  import { readFileSync } from "fs";
13
- import { parseDocument } from "htmlparser2";
14
- import { dirname, relative } from "pathe";
15
-
16
- // src/shared/wxml.ts
17
- var CONTROL_ATTRS = /* @__PURE__ */ new Set([
18
- "wx:if",
19
- "wx:elif",
20
- "wx:else",
21
- "wx:for",
22
- "wx:for-item",
23
- "wx:for-index",
24
- "wx:key"
25
- ]);
26
- var EVENT_PREFIX_RE = /^(?:bind|catch|mut-bind|capture-bind|capture-catch)([\w-]+)$/;
27
- var EVENT_KIND_ALIAS = {
28
- tap: "click"
29
- };
30
- var SELF_CLOSING_TAGS = /* @__PURE__ */ new Set([
31
- "area",
32
- "base",
33
- "br",
34
- "col",
35
- "embed",
36
- "hr",
37
- "img",
38
- "image",
39
- "input",
40
- "link",
41
- "meta",
42
- "param",
43
- "source",
44
- "track",
45
- "wbr"
46
- ]);
47
- function normalizeTagName(name) {
48
- switch (name) {
49
- case "view":
50
- case "cover-view":
51
- case "navigator":
52
- case "scroll-view":
53
- case "swiper":
54
- case "swiper-item":
55
- case "movable-area":
56
- case "movable-view":
57
- case "cover-image":
58
- return "div";
59
- case "text":
60
- case "icon":
61
- return "span";
62
- case "image":
63
- return "img";
64
- case "button":
65
- return "weapp-button";
66
- case "input":
67
- return "input";
68
- case "textarea":
69
- return "textarea";
70
- case "form":
71
- return "form";
72
- case "label":
73
- return "label";
74
- case "picker":
75
- case "picker-view":
76
- return "select";
77
- case "block":
78
- return "#fragment";
79
- case "slot":
80
- return "slot";
81
- default:
82
- return name || "div";
83
- }
84
- }
85
- function normalizeAttributeName(name) {
86
- if (name === "class" || name === "style" || name.startsWith("data-")) {
87
- return name;
88
- }
89
- if (name === "hover-class") {
90
- return "data-hover-class";
91
- }
92
- return name.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
93
- }
94
7
 
95
- // src/compiler/wxml.ts
96
- function shouldMarkWxsImport(pathname) {
97
- const lower = pathname.toLowerCase();
98
- if (lower.endsWith(".wxs") || lower.endsWith(".wxs.ts") || lower.endsWith(".wxs.js")) {
99
- return false;
100
- }
101
- return lower.endsWith(".ts") || lower.endsWith(".js");
8
+ // src/compiler/wxml/dependency.ts
9
+ 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
+ };
102
18
  }
103
- function isRenderableNode(node) {
104
- if (node.type === "directive" || node.type === "comment") {
105
- return false;
106
- }
107
- if (node.type === "text") {
108
- const data = node.data ?? "";
109
- return data.trim().length > 0;
19
+ 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);
110
24
  }
111
- return true;
112
25
  }
113
- function hasChildren(node) {
114
- return Array.isArray(node.children);
115
- }
116
- function toRenderNode(node, children) {
117
- if (node.type === "text") {
118
- const data = node.data ?? "";
119
- return { type: "text", data };
120
- }
121
- if (node.type === "tag" || node.type === "script" || node.type === "style") {
122
- const element = node;
123
- return {
124
- type: "element",
125
- name: element.name,
126
- attribs: element.attribs ?? {},
127
- children
128
- };
129
- }
130
- return void 0;
26
+ function warnReadTemplate(context, target) {
27
+ context.warnings.push(`[web] \u65E0\u6CD5\u8BFB\u53D6\u6A21\u677F\u4F9D\u8D56: ${target}`);
131
28
  }
132
- function convertNode(node) {
133
- if (!isRenderableNode(node)) {
134
- return void 0;
29
+ function warnCircularTemplate(context, from, target) {
30
+ const key = `${from}=>${target}`;
31
+ if (context.circularWarnings.has(key)) {
32
+ return;
135
33
  }
136
- const children = hasChildren(node) && node.children.length > 0 ? node.children.map((child) => convertNode(child)).filter((child) => Boolean(child)) : void 0;
137
- return toRenderNode(node, children);
138
- }
139
- function parseWxml(source) {
140
- const document = parseDocument(source, {
141
- xmlMode: true,
142
- decodeEntities: true,
143
- recognizeSelfClosing: true
144
- });
145
- const nodes = (document.children ?? []).filter(isRenderableNode);
146
- return nodes.map((node) => convertNode(node)).filter((node) => Boolean(node));
34
+ context.circularWarnings.add(key);
35
+ context.warnings.push(`[web] WXML \u5FAA\u73AF\u5F15\u7528: ${from} -> ${target}`);
147
36
  }
37
+
38
+ // src/compiler/wxml/navigation.ts
148
39
  var NAVIGATION_BAR_ATTRS = /* @__PURE__ */ new Set([
149
40
  "title",
150
41
  "background-color",
@@ -260,74 +151,203 @@ function buildNavigationBarAttrs(config, overrides) {
260
151
  }
261
152
  return attrs;
262
153
  }
263
- function parseInterpolations(value) {
264
- const parts = [];
265
- if (!value.includes("{{")) {
266
- return [{ type: "text", value }];
154
+
155
+ // src/compiler/wxml/parser.ts
156
+ import { parseDocument } from "htmlparser2";
157
+ function isRenderableNode(node) {
158
+ if (node.type === "directive" || node.type === "comment") {
159
+ return false;
267
160
  }
268
- let cursor = 0;
269
- while (cursor < value.length) {
270
- const start = value.indexOf("{{", cursor);
271
- if (start === -1) {
272
- parts.push({ type: "text", value: value.slice(cursor) });
273
- break;
274
- }
275
- if (start > cursor) {
276
- parts.push({ type: "text", value: value.slice(cursor, start) });
277
- }
278
- const end = value.indexOf("}}", start + 2);
279
- if (end === -1) {
280
- parts.push({ type: "text", value: value.slice(start) });
281
- break;
282
- }
283
- const expr = value.slice(start + 2, end).trim();
284
- if (expr) {
285
- parts.push({ type: "expr", value: expr });
286
- }
287
- cursor = end + 2;
161
+ if (node.type === "text") {
162
+ const data = node.data ?? "";
163
+ return data.trim().length > 0;
288
164
  }
289
- return parts;
165
+ return true;
290
166
  }
291
- function buildExpression(parts, scopeVar, wxsVar) {
292
- if (parts.length === 0) {
293
- return '""';
167
+ function hasChildren(node) {
168
+ return Array.isArray(node.children);
169
+ }
170
+ function toRenderNode(node, children) {
171
+ if (node.type === "text") {
172
+ const data = node.data ?? "";
173
+ return { type: "text", data };
294
174
  }
295
- if (parts.length === 1 && parts[0]?.type === "text") {
296
- return JSON.stringify(parts[0].value);
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
+ };
297
183
  }
298
- if (parts.length === 1 && parts[0]?.type === "expr") {
299
- return `ctx.eval(${JSON.stringify(parts[0].value)}, ${scopeVar}, ${wxsVar})`;
184
+ return void 0;
185
+ }
186
+ function convertNode(node) {
187
+ if (!isRenderableNode(node)) {
188
+ return void 0;
300
189
  }
301
- const segments = parts.map((part) => {
302
- if (part.type === "text") {
303
- return JSON.stringify(part.value);
304
- }
305
- return `ctx.eval(${JSON.stringify(part.value)}, ${scopeVar}, ${wxsVar})`;
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);
192
+ }
193
+ function parseWxml(source) {
194
+ const document = parseDocument(source, {
195
+ xmlMode: true,
196
+ decodeEntities: true,
197
+ recognizeSelfClosing: true
306
198
  });
307
- return `(${segments.join(" + ")})`;
199
+ const nodes = (document.children ?? []).filter(isRenderableNode);
200
+ return nodes.map((node) => convertNode(node)).filter((node) => Boolean(node));
308
201
  }
309
- function hasTopLevelColon(expression) {
310
- let depth = 0;
311
- let inSingleQuote = false;
312
- let inDoubleQuote = false;
313
- let inTemplate = false;
314
- let escaped = false;
315
- let sawTopLevelQuestion = false;
316
- for (let index = 0; index < expression.length; index += 1) {
317
- const char = expression[index];
318
- if (inSingleQuote) {
319
- if (escaped) {
320
- escaped = false;
321
- continue;
322
- }
323
- if (char === "\\") {
324
- escaped = true;
325
- continue;
326
- }
327
- if (char === "'") {
328
- inSingleQuote = false;
329
- }
330
- continue;
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"
212
+ ]);
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"
233
+ ]);
234
+ 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
+ }
271
+ }
272
+ 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
283
+ 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;
310
+ }
311
+ 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(" + ")})`;
328
+ }
329
+ 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;
331
351
  }
332
352
  if (inDoubleQuote) {
333
353
  if (escaped) {
@@ -412,34 +432,8 @@ function buildTemplateDataExpression(raw, scopeVar, wxsVar) {
412
432
  }
413
433
  return buildExpression(parseInterpolations(raw), scopeVar, wxsVar);
414
434
  }
415
- function createDependencyContext() {
416
- return {
417
- warnings: [],
418
- dependencies: [],
419
- dependencySet: /* @__PURE__ */ new Set(),
420
- visited: /* @__PURE__ */ new Set(),
421
- active: /* @__PURE__ */ new Set(),
422
- circularWarnings: /* @__PURE__ */ new Set()
423
- };
424
- }
425
- function addDependency(value, context, direct) {
426
- if (!context.dependencySet.has(value)) {
427
- context.dependencySet.add(value);
428
- context.dependencies.push(value);
429
- direct?.push(value);
430
- }
431
- }
432
- function warnReadTemplate(context, target) {
433
- context.warnings.push(`[web] \u65E0\u6CD5\u8BFB\u53D6\u6A21\u677F\u4F9D\u8D56: ${target}`);
434
- }
435
- function warnCircularTemplate(context, from, target) {
436
- const key = `${from}=>${target}`;
437
- if (context.circularWarnings.has(key)) {
438
- return;
439
- }
440
- context.circularWarnings.add(key);
441
- context.warnings.push(`[web] WXML \u5FAA\u73AF\u5F15\u7528: ${from} -> ${target}`);
442
- }
435
+
436
+ // src/compiler/wxml/attributes.ts
443
437
  function extractFor(attribs) {
444
438
  const expr = attribs["wx:for"];
445
439
  const itemName = attribs["wx:for-item"]?.trim() || "item";
@@ -528,6 +522,8 @@ function renderAttributes(attribs, scopeVar, wxsVar, options) {
528
522
  }
529
523
  return buffer;
530
524
  }
525
+
526
+ // src/compiler/wxml/renderer.ts
531
527
  var Renderer = class {
532
528
  renderNodes(nodes, scopeVar, wxsVar, componentTags) {
533
529
  const parts = [];
@@ -605,13 +601,13 @@ var Renderer = class {
605
601
  }
606
602
  if (node.type === "element") {
607
603
  if (node.name === "template" && node.attribs?.is) {
608
- return this.renderTemplateInvoke(node, scopeVar, wxsVar, componentTags);
604
+ return this.renderTemplateInvoke(node, scopeVar, wxsVar);
609
605
  }
610
606
  return this.renderElement(node, scopeVar, wxsVar, componentTags);
611
607
  }
612
608
  return '""';
613
609
  }
614
- renderTemplateInvoke(node, scopeVar, wxsVar, _componentTags) {
610
+ renderTemplateInvoke(node, scopeVar, wxsVar) {
615
611
  const attribs = node.attribs ?? {};
616
612
  const isExpr = buildExpression(parseInterpolations(attribs.is ?? ""), scopeVar, wxsVar);
617
613
  const dataExpr = attribs.data ? buildTemplateDataExpression(attribs.data, scopeVar, wxsVar) : void 0;
@@ -657,6 +653,16 @@ var Renderer = class {
657
653
  }
658
654
  };
659
655
  var renderer = new Renderer();
656
+
657
+ // src/compiler/wxml/specialNodes.ts
658
+ import { dirname, relative } from "pathe";
659
+ 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");
665
+ }
660
666
  function collectSpecialNodes(nodes, context) {
661
667
  const renderable = [];
662
668
  for (const node of nodes) {
@@ -743,6 +749,8 @@ function toRelativeImport(from, target) {
743
749
  function normalizeTemplatePath(pathname) {
744
750
  return pathname.split("\\").join("/");
745
751
  }
752
+
753
+ // src/compiler/wxml/compile.ts
746
754
  function compileWxml(options) {
747
755
  const dependencyContext = options.dependencyContext ?? createDependencyContext();
748
756
  const expandDependencies = options.expandDependencies ?? !options.dependencyContext;
@@ -1026,30 +1034,7 @@ function transformWxssToCss(source, options) {
1026
1034
  };
1027
1035
  }
1028
1036
 
1029
- // src/shared/slugify.ts
1030
- function slugify(id, prefix) {
1031
- const normalized = id.replace(/[^a-z0-9]+/gi, "-").replace(/^-+|-+$/g, "").toLowerCase();
1032
- return `${prefix}-${normalized || "index"}`;
1033
- }
1034
-
1035
- // src/plugin.ts
1036
- var traverseCandidate = (() => {
1037
- const mod = _babelTraverse;
1038
- if (typeof mod === "function") {
1039
- return mod;
1040
- }
1041
- if (mod?.default && typeof mod.default === "function") {
1042
- return mod.default;
1043
- }
1044
- if (mod?.traverse && typeof mod.traverse === "function") {
1045
- return mod.traverse;
1046
- }
1047
- return void 0;
1048
- })();
1049
- if (typeof traverseCandidate !== "function") {
1050
- throw new TypeError("[@weapp-vite/web] Failed to resolve @babel/traverse export.");
1051
- }
1052
- var traverse = traverseCandidate;
1037
+ // src/plugin/constants.ts
1053
1038
  var SCRIPT_EXTS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
1054
1039
  var STYLE_EXTS = [".wxss", ".scss", ".less", ".css"];
1055
1040
  var TRANSFORM_STYLE_EXTS = [".wxss"];
@@ -1057,593 +1042,53 @@ var TEMPLATE_EXTS = [".wxml", ".axml", ".swan", ".ttml", ".qml", ".ksml", ".xhsm
1057
1042
  var WXS_EXTS = [".wxs", ".wxs.ts", ".wxs.js"];
1058
1043
  var WXS_RESOLVE_EXTS = [".wxs", ".wxs.ts", ".wxs.js", ".ts", ".js"];
1059
1044
  var ENTRY_ID = "\0@weapp-vite/web/entry";
1060
- function isTemplateFile(id) {
1061
- const lower = id.toLowerCase();
1062
- return TEMPLATE_EXTS.some((ext) => lower.endsWith(ext));
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";
1049
+ function cleanUrl(url) {
1050
+ const queryIndex = url.indexOf("?");
1051
+ if (queryIndex >= 0) {
1052
+ return url.slice(0, queryIndex);
1053
+ }
1054
+ return url;
1063
1055
  }
1064
- function isWxsFile(id) {
1065
- const lower = id.toLowerCase();
1066
- return WXS_EXTS.some((ext) => lower.endsWith(ext));
1056
+ function normalizePath2(p) {
1057
+ return posix.normalize(p.split("\\").join("/"));
1067
1058
  }
1068
- function hasWxsQuery(id) {
1069
- return id.includes("?wxs") || id.includes("&wxs");
1059
+ function isInsideDir(filePath, dir) {
1060
+ const rel = relative2(dir, filePath);
1061
+ return rel === "" || !rel.startsWith("..") && !posix.isAbsolute(rel);
1070
1062
  }
1071
- function weappWebPlugin(options = {}) {
1072
- let root = process.cwd();
1073
- let srcRoot = resolve(root, options.srcDir ?? "src");
1074
- let enableHmr = false;
1075
- const moduleMeta = /* @__PURE__ */ new Map();
1076
- const pageNavigationMap = /* @__PURE__ */ new Map();
1077
- const templateComponentMap = /* @__PURE__ */ new Map();
1078
- const templatePathSet = /* @__PURE__ */ new Set();
1079
- const componentTagMap = /* @__PURE__ */ new Map();
1080
- const componentIdMap = /* @__PURE__ */ new Map();
1081
- let appNavigationDefaults = {};
1082
- let appComponentTags = {};
1083
- let scanResult = {
1084
- app: void 0,
1085
- pages: [],
1086
- components: []
1087
- };
1088
- const wxssOptions = options.wxss;
1089
- const resolveTemplatePath = (raw, importer) => resolveTemplatePathSync(raw, importer, srcRoot);
1090
- const resolveWxsPath = (raw, importer) => resolveWxsPathSync(raw, importer, srcRoot);
1091
- return {
1092
- name: "@weapp-vite/web",
1093
- enforce: "pre",
1094
- async configResolved(config) {
1095
- root = config.root;
1096
- srcRoot = resolve(root, options.srcDir ?? "src");
1097
- enableHmr = config.command === "serve";
1098
- await scanProject(this.warn?.bind(this));
1099
- },
1100
- async buildStart() {
1101
- await scanProject(this.warn?.bind(this));
1102
- },
1103
- resolveId(id) {
1104
- if (id === "/@weapp-vite/web/entry" || id === "@weapp-vite/web/entry") {
1105
- return ENTRY_ID;
1106
- }
1107
- return null;
1108
- },
1109
- load(id) {
1110
- if (id === ENTRY_ID) {
1111
- return generateEntryModule(scanResult, root, wxssOptions, options);
1112
- }
1113
- return null;
1114
- },
1115
- async handleHotUpdate(ctx) {
1116
- const clean = cleanUrl(ctx.file);
1117
- if (clean.endsWith(".json") || isTemplateFile(clean) || isWxsFile(clean) || clean.endsWith(".wxss") || SCRIPT_EXTS.includes(extname(clean))) {
1118
- await scanProject(this.warn?.bind(this));
1119
- }
1120
- },
1121
- transform(code, id) {
1122
- const clean = cleanUrl(id);
1123
- if (isTemplateFile(clean)) {
1124
- if (isHtmlEntry(clean, root)) {
1125
- return null;
1126
- }
1127
- const normalizedId = normalizePath2(clean);
1128
- if (templatePathSet.size > 0) {
1129
- if (!isInsideDir(clean, srcRoot)) {
1130
- return null;
1131
- }
1132
- if (!templatePathSet.has(normalizedId)) {
1133
- return null;
1134
- }
1135
- }
1136
- const navigationConfig = pageNavigationMap.get(normalizedId);
1137
- const componentTags = templateComponentMap.get(normalizedId);
1138
- const { code: compiled, dependencies, warnings } = compileWxml({
1139
- id: clean,
1140
- source: code,
1141
- resolveTemplatePath,
1142
- resolveWxsPath,
1143
- navigationBar: navigationConfig ? { config: navigationConfig } : void 0,
1144
- componentTags
1145
- });
1146
- if (dependencies.length > 0 && "addWatchFile" in this) {
1147
- for (const dep of dependencies) {
1148
- this.addWatchFile(dep);
1149
- }
1150
- }
1151
- if (warnings?.length && "warn" in this) {
1152
- for (const warning of warnings) {
1153
- this.warn(warning);
1154
- }
1155
- }
1156
- return { code: compiled, map: null };
1157
- }
1158
- if (isWxsFile(clean) || hasWxsQuery(id)) {
1159
- const { code: compiled, dependencies, warnings } = transformWxsToEsm(code, clean, {
1160
- resolvePath: resolveWxsPath,
1161
- toImportPath: (resolved, importer) => normalizePath2(toRelativeImport2(importer, resolved))
1162
- });
1163
- if (dependencies.length > 0 && "addWatchFile" in this) {
1164
- for (const dep of dependencies) {
1165
- this.addWatchFile(dep);
1166
- }
1167
- }
1168
- if (warnings?.length && "warn" in this) {
1169
- for (const warning of warnings) {
1170
- this.warn(warning);
1171
- }
1172
- }
1173
- return { code: compiled, map: null };
1174
- }
1175
- if (TRANSFORM_STYLE_EXTS.some((ext) => clean.endsWith(ext))) {
1176
- const { css } = transformWxssToCss(code, wxssOptions);
1177
- const serialized = JSON.stringify(css);
1178
- return {
1179
- code: [
1180
- `const __weapp_injected_styles__ = new Map()`,
1181
- `function __weapp_createStyleId__(css) {`,
1182
- ` let hash = 2166136261`,
1183
- ` for (let i = 0; i < css.length; i++) {`,
1184
- ` hash ^= css.charCodeAt(i)`,
1185
- ` hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24)`,
1186
- ` }`,
1187
- ` return 'weapp-web-style-' + (hash >>> 0).toString(36)`,
1188
- `}`,
1189
- `function __weapp_removeStyle__(id) {`,
1190
- ` if (typeof document === 'undefined') {`,
1191
- ` return`,
1192
- ` }`,
1193
- ` const style = __weapp_injected_styles__.get(id)`,
1194
- ` if (style) {`,
1195
- ` style.remove()`,
1196
- ` __weapp_injected_styles__.delete(id)`,
1197
- ` }`,
1198
- `}`,
1199
- `function injectStyle(css, id) {`,
1200
- ` if (typeof document === 'undefined') {`,
1201
- ` return () => {}`,
1202
- ` }`,
1203
- ` const styleId = id ?? __weapp_createStyleId__(css)`,
1204
- ` const existing = __weapp_injected_styles__.get(styleId)`,
1205
- ` if (existing) {`,
1206
- ` if (existing.textContent !== css) {`,
1207
- ` existing.textContent = css`,
1208
- ` }`,
1209
- ` return () => __weapp_removeStyle__(styleId)`,
1210
- ` }`,
1211
- ` const style = document.createElement('style')`,
1212
- ` style.id = styleId`,
1213
- ` style.textContent = css`,
1214
- ` document.head.append(style)`,
1215
- ` __weapp_injected_styles__.set(styleId, style)`,
1216
- ` return () => __weapp_removeStyle__(styleId)`,
1217
- `}`,
1218
- `const css = ${serialized}`,
1219
- `export default css`,
1220
- `export function useStyle(id) {`,
1221
- ` return injectStyle(css, id)`,
1222
- `}`
1223
- ].join("\n"),
1224
- map: null
1225
- };
1226
- }
1227
- if (STYLE_EXTS.some((ext) => clean.endsWith(ext)) && !clean.endsWith(".wxss")) {
1228
- const { css } = transformWxssToCss(code, wxssOptions);
1229
- return { code: css, map: null };
1230
- }
1231
- if (!SCRIPT_EXTS.some((ext) => clean.endsWith(ext))) {
1232
- return null;
1233
- }
1234
- if (clean.includes("node_modules")) {
1235
- return null;
1236
- }
1237
- const meta = moduleMeta.get(normalizePath2(clean));
1238
- if (!meta) {
1239
- return null;
1240
- }
1241
- const registerName = getRegisterName(meta.kind);
1242
- if (!registerName) {
1243
- return null;
1244
- }
1245
- let ast;
1246
- try {
1247
- ast = parse(code, {
1248
- sourceType: "module",
1249
- plugins: ["typescript", "jsx"],
1250
- errorRecovery: true,
1251
- ranges: true
1252
- });
1253
- } catch {
1254
- return null;
1255
- }
1256
- const s = new MagicString(code);
1257
- let transformed = false;
1258
- const imports = [];
1259
- const templateIdent = meta.templatePath ? `__weapp_template__` : void 0;
1260
- const styleIdent = meta.stylePath ? `__weapp_style__` : void 0;
1261
- if (meta.templatePath && templateIdent) {
1262
- imports.push(`import ${templateIdent} from '${toRelativeImport2(clean, meta.templatePath)}'`);
1263
- }
1264
- if (meta.stylePath && styleIdent) {
1265
- imports.push(`import ${styleIdent} from '${appendInlineQuery(toRelativeImport2(clean, meta.stylePath))}'`);
1266
- }
1267
- const registerImports = /* @__PURE__ */ new Set();
1268
- traverse(ast, {
1269
- CallExpression(path) {
1270
- if (!t.isIdentifier(path.node.callee)) {
1271
- return;
1272
- }
1273
- const name = path.node.callee.name;
1274
- if (name === mapRegisterIdentifier(meta.kind)) {
1275
- registerImports.add(registerName);
1276
- overwriteCall(path, meta, registerName, templateIdent, styleIdent, s);
1277
- transformed = true;
1278
- }
1279
- }
1280
- });
1281
- if (!transformed) {
1282
- return null;
1283
- }
1284
- if (registerImports.size > 0) {
1285
- imports.unshift(`import { ${Array.from(registerImports).join(", ")} } from '@weapp-vite/web/runtime/polyfill'`);
1286
- }
1287
- const prefix = `${imports.join("\n")}
1288
- `;
1289
- s.prepend(prefix);
1290
- if (enableHmr) {
1291
- s.append(`
1292
- if (import.meta.hot) { import.meta.hot.accept() }
1293
- `);
1294
- }
1295
- return {
1296
- code: s.toString(),
1297
- map: s.generateMap({
1298
- hires: true
1299
- })
1300
- };
1301
- }
1302
- };
1303
- async function scanProject(warn) {
1304
- moduleMeta.clear();
1305
- pageNavigationMap.clear();
1306
- templateComponentMap.clear();
1307
- templatePathSet.clear();
1308
- componentTagMap.clear();
1309
- componentIdMap.clear();
1310
- appNavigationDefaults = {};
1311
- appComponentTags = {};
1312
- const pages = /* @__PURE__ */ new Map();
1313
- const components = /* @__PURE__ */ new Map();
1314
- const reportWarning = (message) => {
1315
- if (warn) {
1316
- warn(message);
1317
- return;
1318
- }
1319
- if (typeof process !== "undefined" && typeof process.emitWarning === "function") {
1320
- process.emitWarning(message);
1321
- }
1322
- };
1323
- const appScript = await resolveScriptFile(join(srcRoot, "app"));
1324
- if (appScript) {
1325
- moduleMeta.set(
1326
- normalizePath2(appScript),
1327
- {
1328
- kind: "app",
1329
- id: "app",
1330
- scriptPath: appScript,
1331
- stylePath: await resolveStyleFile(appScript)
1332
- }
1333
- );
1334
- }
1335
- const appJsonBasePath = join(srcRoot, "app.json");
1336
- const appJsonPath = await resolveJsonPath(appJsonBasePath);
1337
- if (appJsonPath) {
1338
- const appJson = await readJsonFile(appJsonPath);
1339
- if (appJson) {
1340
- appComponentTags = await collectComponentTagsFromConfig(appJson, srcRoot, appJsonPath, reportWarning, (tags) => {
1341
- appComponentTags = tags;
1342
- });
1343
- }
1344
- if (appJson?.pages && Array.isArray(appJson.pages)) {
1345
- for (const page of appJson.pages) {
1346
- if (typeof page === "string") {
1347
- await collectPage(page);
1348
- }
1349
- }
1350
- }
1351
- if (appJson?.subPackages && Array.isArray(appJson.subPackages)) {
1352
- for (const pkg of appJson.subPackages) {
1353
- if (!pkg || typeof pkg !== "object") {
1354
- continue;
1355
- }
1356
- const root2 = typeof pkg.root === "string" ? pkg.root : "";
1357
- if (!Array.isArray(pkg.pages)) {
1358
- continue;
1359
- }
1360
- for (const page of pkg.pages) {
1361
- if (typeof page !== "string") {
1362
- continue;
1363
- }
1364
- const full = posix.join(root2, page);
1365
- await collectPage(full);
1366
- }
1367
- }
1368
- }
1369
- const windowConfig = isRecord(appJson?.window) ? appJson.window : void 0;
1370
- appNavigationDefaults = pickNavigationConfig(windowConfig);
1371
- }
1372
- scanResult = {
1373
- app: appScript,
1374
- pages: Array.from(pages.values()),
1375
- components: Array.from(components.values())
1376
- };
1377
- async function collectPage(pageId) {
1378
- const base = join(srcRoot, pageId);
1379
- const script = await resolveScriptFile(base);
1380
- if (!script) {
1381
- return;
1382
- }
1383
- const template = await resolveTemplateFile(base);
1384
- if (template) {
1385
- templatePathSet.add(normalizePath2(template));
1386
- }
1387
- const style = await resolveStyleFile(base);
1388
- const pageJsonBasePath = join(srcRoot, `${pageId}.json`);
1389
- const pageJsonPath = await resolveJsonPath(pageJsonBasePath);
1390
- const pageJson = pageJsonPath ? await readJsonFile(pageJsonPath) : void 0;
1391
- moduleMeta.set(
1392
- normalizePath2(script),
1393
- {
1394
- kind: "page",
1395
- id: toPosixId(pageId),
1396
- scriptPath: script,
1397
- templatePath: template,
1398
- stylePath: style
1399
- }
1400
- );
1401
- pages.set(script, {
1402
- script,
1403
- id: toPosixId(pageId)
1404
- });
1405
- const pageComponentTags = pageJson && pageJsonPath ? await collectComponentTagsFromConfig(pageJson, dirname2(script), pageJsonPath, reportWarning) : await collectComponentTagsFromJson(pageJsonBasePath, dirname2(script), reportWarning);
1406
- if (template) {
1407
- const mergedTags = mergeComponentTags(appComponentTags, pageComponentTags);
1408
- if (Object.keys(mergedTags).length > 0) {
1409
- templateComponentMap.set(normalizePath2(template), mergedTags);
1410
- } else {
1411
- templateComponentMap.delete(normalizePath2(template));
1412
- }
1413
- }
1414
- if (pageJson) {
1415
- if (template) {
1416
- const config = mergeNavigationConfig(appNavigationDefaults, pickNavigationConfig(pageJson));
1417
- pageNavigationMap.set(normalizePath2(template), config);
1418
- }
1419
- } else if (template) {
1420
- pageNavigationMap.set(normalizePath2(template), { ...appNavigationDefaults });
1421
- }
1422
- }
1423
- async function collectComponent(componentId, importerDir) {
1424
- const base = resolveComponentBase(componentId, importerDir);
1425
- const script = base ? await resolveScriptFile(base) : void 0;
1426
- if (!script) {
1427
- return;
1428
- }
1429
- if (components.has(script)) {
1430
- return;
1431
- }
1432
- const idRelative = relative2(srcRoot, script).replace(new RegExp(`${extname(script)}$`), "");
1433
- const componentIdPosix = toPosixId(idRelative);
1434
- const template = await resolveTemplateFile(script);
1435
- if (template) {
1436
- templatePathSet.add(normalizePath2(template));
1437
- }
1438
- const style = await resolveStyleFile(script);
1439
- moduleMeta.set(
1440
- normalizePath2(script),
1441
- {
1442
- kind: "component",
1443
- id: componentIdPosix,
1444
- scriptPath: script,
1445
- templatePath: template,
1446
- stylePath: style
1447
- }
1448
- );
1449
- components.set(script, {
1450
- script,
1451
- id: componentIdPosix
1452
- });
1453
- const componentJsonBasePath = `${script.replace(new RegExp(`${extname(script)}$`), "")}.json`;
1454
- const componentTags = await collectComponentTagsFromJson(componentJsonBasePath, dirname2(script), reportWarning);
1455
- if (template) {
1456
- const mergedTags = mergeComponentTags(appComponentTags, componentTags);
1457
- if (Object.keys(mergedTags).length > 0) {
1458
- templateComponentMap.set(normalizePath2(template), mergedTags);
1459
- } else {
1460
- templateComponentMap.delete(normalizePath2(template));
1461
- }
1462
- }
1463
- }
1464
- async function collectComponentTagsFromConfig(json, importerDir, jsonPath, warn2, onResolved) {
1465
- const usingComponents = json.usingComponents;
1466
- if (!usingComponents || typeof usingComponents !== "object") {
1467
- return {};
1468
- }
1469
- const tags = {};
1470
- const resolved = [];
1471
- for (const [rawKey, rawValue] of Object.entries(usingComponents)) {
1472
- if (typeof rawValue !== "string") {
1473
- continue;
1474
- }
1475
- const key = normalizeComponentKey(rawKey);
1476
- if (!key) {
1477
- continue;
1478
- }
1479
- const script = await resolveComponentScript(rawValue, importerDir);
1480
- if (!script) {
1481
- warn2(`[@weapp-vite/web] usingComponents entry "${rawKey}" not found: ${rawValue} (${jsonPath})`);
1482
- continue;
1483
- }
1484
- const tag = getComponentTag(script);
1485
- if (tag) {
1486
- tags[key] = tag;
1487
- resolved.push({ rawValue });
1488
- }
1489
- }
1490
- onResolved?.(tags);
1491
- for (const entry of resolved) {
1492
- await collectComponent(entry.rawValue, importerDir);
1493
- }
1494
- return tags;
1495
- }
1496
- async function collectComponentTagsFromJson(jsonBasePath, importerDir, warn2) {
1497
- const resolvedPath = await resolveJsonPath(jsonBasePath);
1498
- if (!resolvedPath) {
1499
- return {};
1500
- }
1501
- const json = await readJsonFile(resolvedPath);
1502
- if (!json) {
1503
- return {};
1504
- }
1505
- return collectComponentTagsFromConfig(json, importerDir, resolvedPath, warn2);
1506
- }
1507
- function mergeComponentTags(base, overrides) {
1508
- if (!Object.keys(base).length && !Object.keys(overrides).length) {
1509
- return {};
1510
- }
1511
- return {
1512
- ...base,
1513
- ...overrides
1514
- };
1515
- }
1516
- function normalizeComponentKey(raw) {
1517
- return raw.trim().toLowerCase();
1518
- }
1519
- function getComponentId(script) {
1520
- const cached = componentIdMap.get(script);
1521
- if (cached) {
1522
- return cached;
1523
- }
1524
- const idRelative = relative2(srcRoot, script).replace(new RegExp(`${extname(script)}$`), "");
1525
- const componentIdPosix = toPosixId(idRelative);
1526
- componentIdMap.set(script, componentIdPosix);
1527
- return componentIdPosix;
1528
- }
1529
- function getComponentTag(script) {
1530
- const cached = componentTagMap.get(script);
1531
- if (cached) {
1532
- return cached;
1533
- }
1534
- const id = getComponentId(script);
1535
- const tag = slugify(id, "wv-component");
1536
- componentTagMap.set(script, tag);
1537
- return tag;
1538
- }
1539
- async function resolveComponentScript(raw, importerDir) {
1540
- const base = resolveComponentBase(raw, importerDir);
1541
- if (!base) {
1542
- return void 0;
1543
- }
1544
- return resolveScriptFile(base);
1545
- }
1546
- function resolveComponentBase(raw, importerDir) {
1547
- if (!raw) {
1548
- return void 0;
1549
- }
1550
- if (raw.startsWith(".")) {
1551
- return resolve(importerDir, raw);
1552
- }
1553
- if (raw.startsWith("/")) {
1554
- return resolve(srcRoot, raw.slice(1));
1555
- }
1556
- return resolve(srcRoot, raw);
1557
- }
1558
- }
1559
- }
1560
- function cleanUrl(url) {
1561
- const queryIndex = url.indexOf("?");
1562
- if (queryIndex >= 0) {
1563
- return url.slice(0, queryIndex);
1063
+ function isHtmlEntry(filePath, root) {
1064
+ if (!filePath.toLowerCase().endsWith(".html")) {
1065
+ return false;
1564
1066
  }
1565
- return url;
1067
+ return normalizePath2(filePath) === normalizePath2(resolve(root, "index.html"));
1566
1068
  }
1567
- function isRecord(value) {
1568
- return typeof value === "object" && value !== null && !Array.isArray(value);
1069
+ function toPosixId(id) {
1070
+ return normalize(id).split("\\").join("/");
1569
1071
  }
1570
- async function readJsonFile(pathname) {
1571
- const candidates = [pathname];
1572
- if (pathname.endsWith(".json")) {
1573
- candidates.push(`${pathname}.ts`, `${pathname}.js`);
1574
- }
1575
- for (const candidate of candidates) {
1576
- if (!await fs.pathExists(candidate)) {
1577
- continue;
1578
- }
1579
- if (candidate.endsWith(".json")) {
1580
- const json = await fs.readJson(candidate).catch(() => void 0);
1581
- if (!isRecord(json)) {
1582
- return void 0;
1583
- }
1584
- return json;
1585
- }
1586
- const { mod } = await bundleRequire({
1587
- filepath: candidate,
1588
- preserveTemporaryFile: true
1589
- });
1590
- const resolved = typeof mod.default === "function" ? await mod.default() : mod.default;
1591
- if (!isRecord(resolved)) {
1592
- return void 0;
1593
- }
1594
- return resolved;
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)}`);
1595
1077
  }
1596
- return void 0;
1078
+ return `./${normalizePath2(rel)}`;
1597
1079
  }
1598
- async function resolveJsonPath(basePath) {
1599
- const candidates = [basePath];
1600
- if (basePath.endsWith(".json")) {
1601
- candidates.push(`${basePath}.ts`, `${basePath}.js`);
1602
- }
1603
- for (const candidate of candidates) {
1604
- if (await fs.pathExists(candidate)) {
1605
- return candidate;
1080
+ function appendInlineQuery(id) {
1081
+ if (id.includes("?")) {
1082
+ if (id.includes("?inline") || id.includes("&inline")) {
1083
+ return id;
1606
1084
  }
1085
+ return `${id}&inline`;
1607
1086
  }
1608
- return void 0;
1609
- }
1610
- function pickNavigationConfig(source) {
1611
- const config = {};
1612
- if (!source) {
1613
- return config;
1614
- }
1615
- if (typeof source.navigationBarTitleText === "string") {
1616
- config.title = source.navigationBarTitleText;
1617
- }
1618
- if (typeof source.navigationBarBackgroundColor === "string") {
1619
- config.backgroundColor = source.navigationBarBackgroundColor;
1620
- }
1621
- if (typeof source.navigationBarTextStyle === "string") {
1622
- config.textStyle = source.navigationBarTextStyle;
1623
- }
1624
- if (typeof source.navigationStyle === "string") {
1625
- config.navigationStyle = source.navigationStyle;
1626
- }
1627
- return config;
1628
- }
1629
- function mergeNavigationConfig(base, overrides) {
1630
- return {
1631
- ...base,
1632
- ...overrides
1633
- };
1634
- }
1635
- function normalizePath2(p) {
1636
- return posix.normalize(p.split("\\").join("/"));
1637
- }
1638
- function isInsideDir(filePath, dir) {
1639
- const rel = relative2(dir, filePath);
1640
- return rel === "" || !rel.startsWith("..") && !posix.isAbsolute(rel);
1087
+ return `${id}?inline`;
1641
1088
  }
1642
- function isHtmlEntry(filePath, root) {
1643
- if (!filePath.toLowerCase().endsWith(".html")) {
1644
- return false;
1645
- }
1646
- return normalizePath2(filePath) === normalizePath2(resolve(root, "index.html"));
1089
+ function relativeModuleId(root, absPath) {
1090
+ const rel = relative2(root, absPath);
1091
+ return `/${normalizePath2(rel)}`;
1647
1092
  }
1648
1093
  function resolveImportBase(raw, importer, srcRoot) {
1649
1094
  if (!raw) {
@@ -1690,130 +1135,797 @@ function resolveWxsPathSync(raw, importer, srcRoot) {
1690
1135
  }
1691
1136
  return resolveFileWithExtensionsSync(base, WXS_RESOLVE_EXTS);
1692
1137
  }
1138
+
1139
+ // src/plugin/entry.ts
1140
+ 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;
1193
+ })();
1194
+ if (typeof traverseCandidate !== "function") {
1195
+ throw new TypeError("[@weapp-vite/web] Failed to resolve @babel/traverse export.");
1196
+ }
1197
+ var traverse = traverseCandidate;
1198
+ 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 "";
1209
+ }
1210
+ 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;
1221
+ }
1222
+ 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
1314
+ function slugify(id, prefix) {
1315
+ const normalized = id.replace(/[^a-z0-9]+/gi, "-").replace(/^-+|-+$/g, "").toLowerCase();
1316
+ return `${prefix}-${normalized || "index"}`;
1317
+ }
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";
1323
+ function isRecord(value) {
1324
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1325
+ }
1326
+ 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;
1353
+ }
1354
+ 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;
1365
+ }
1693
1366
  async function resolveScriptFile(basePath) {
1694
- const ext = extname(basePath);
1695
- if (ext && await fs.pathExists(basePath)) {
1367
+ const ext = extname2(basePath);
1368
+ if (ext && await fs2.pathExists(basePath)) {
1696
1369
  return basePath;
1697
1370
  }
1698
1371
  for (const candidateExt of SCRIPT_EXTS) {
1699
1372
  const candidate = `${basePath}${candidateExt}`;
1700
- if (await fs.pathExists(candidate)) {
1373
+ if (await fs2.pathExists(candidate)) {
1701
1374
  return candidate;
1702
1375
  }
1703
1376
  }
1704
1377
  return void 0;
1705
1378
  }
1706
1379
  async function resolveStyleFile(scriptPath) {
1707
- const base = scriptPath.replace(new RegExp(`${extname(scriptPath)}$`), "");
1380
+ const base = scriptPath.replace(new RegExp(`${extname2(scriptPath)}$`), "");
1708
1381
  for (const ext of STYLE_EXTS) {
1709
1382
  const candidate = `${base}${ext}`;
1710
- if (await fs.pathExists(candidate)) {
1383
+ if (await fs2.pathExists(candidate)) {
1711
1384
  return candidate;
1712
1385
  }
1713
1386
  }
1714
1387
  return void 0;
1715
1388
  }
1716
1389
  async function resolveTemplateFile(scriptPath) {
1717
- const base = scriptPath.replace(new RegExp(`${extname(scriptPath)}$`), "");
1390
+ const base = scriptPath.replace(new RegExp(`${extname2(scriptPath)}$`), "");
1718
1391
  for (const ext of TEMPLATE_EXTS) {
1719
1392
  const candidate = `${base}${ext}`;
1720
- if (await fs.pathExists(candidate)) {
1393
+ if (await fs2.pathExists(candidate)) {
1721
1394
  return candidate;
1722
1395
  }
1723
1396
  }
1724
1397
  return void 0;
1725
1398
  }
1726
- function toPosixId(id) {
1727
- return normalize(id).split("\\").join("/");
1728
- }
1729
- function toRelativeImport2(from, target) {
1730
- const fromDir = dirname2(from);
1731
- const rel = relative2(fromDir, target);
1732
- if (!rel || rel.startsWith(".")) {
1733
- return normalizePath2(rel || `./${posix.basename(target)}`);
1399
+
1400
+ // src/plugin/navigation.ts
1401
+ function pickNavigationConfig(source) {
1402
+ const config = {};
1403
+ if (!source) {
1404
+ return config;
1734
1405
  }
1735
- return `./${normalizePath2(rel)}`;
1736
- }
1737
- function appendInlineQuery(id) {
1738
- if (id.includes("?")) {
1739
- if (id.includes("?inline") || id.includes("&inline")) {
1740
- return id;
1741
- }
1742
- return `${id}&inline`;
1406
+ if (typeof source.navigationBarTitleText === "string") {
1407
+ config.title = source.navigationBarTitleText;
1743
1408
  }
1744
- return `${id}?inline`;
1745
- }
1746
- function mapRegisterIdentifier(kind) {
1747
- if (kind === "page") {
1748
- return "Page";
1409
+ if (typeof source.navigationBarBackgroundColor === "string") {
1410
+ config.backgroundColor = source.navigationBarBackgroundColor;
1749
1411
  }
1750
- if (kind === "component") {
1751
- return "Component";
1412
+ if (typeof source.navigationBarTextStyle === "string") {
1413
+ config.textStyle = source.navigationBarTextStyle;
1752
1414
  }
1753
- if (kind === "app") {
1754
- return "App";
1415
+ if (typeof source.navigationStyle === "string") {
1416
+ config.navigationStyle = source.navigationStyle;
1755
1417
  }
1756
- return "";
1418
+ return config;
1757
1419
  }
1758
- function getRegisterName(kind) {
1759
- if (kind === "page") {
1760
- return "registerPage";
1761
- }
1762
- if (kind === "component") {
1763
- return "registerComponent";
1420
+ 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 });
1764
1460
  }
1765
- if (kind === "app") {
1766
- return "registerApp";
1461
+ onResolved?.(tags);
1462
+ for (const entry of resolved) {
1463
+ await collectComponent(entry.rawValue, importerDir);
1767
1464
  }
1768
- return void 0;
1465
+ return tags;
1769
1466
  }
1770
- function overwriteCall(path, meta, registerName, templateIdent, styleIdent, s) {
1771
- const node = path.node;
1772
- const callee = node.callee;
1773
- if (!t.isIdentifier(callee)) {
1774
- return;
1467
+ async function collectComponentTagsFromJson({
1468
+ jsonBasePath,
1469
+ importerDir,
1470
+ warn,
1471
+ collectFromConfig
1472
+ }) {
1473
+ const resolvedPath = await resolveJsonPath(jsonBasePath);
1474
+ if (!resolvedPath) {
1475
+ return {};
1775
1476
  }
1776
- const end = node.end;
1777
- const insertPosition = end - 1;
1778
- const metaParts = [`id: ${JSON.stringify(meta.id)}`];
1779
- if (templateIdent) {
1780
- metaParts.push(`template: ${templateIdent}`);
1477
+ const json = await readJsonFile(resolvedPath);
1478
+ if (!json) {
1479
+ return {};
1781
1480
  }
1782
- if (styleIdent) {
1783
- metaParts.push(`style: ${styleIdent}`);
1481
+ return collectFromConfig(json, importerDir, resolvedPath, warn);
1482
+ }
1483
+ function mergeComponentTags(base, overrides) {
1484
+ if (!Object.keys(base).length && !Object.keys(overrides).length) {
1485
+ return {};
1784
1486
  }
1785
- const metaCode = `{ ${metaParts.join(", ")} }`;
1786
- s.overwrite(callee.start, callee.end, registerName);
1787
- s.appendLeft(insertPosition, `, ${metaCode}`);
1487
+ return {
1488
+ ...base,
1489
+ ...overrides
1490
+ };
1788
1491
  }
1789
- function generateEntryModule(result, root, wxssOptions, pluginOptions) {
1790
- const importLines = [`import { initializePageRoutes } from '@weapp-vite/web/runtime/polyfill'`];
1791
- const bodyLines = [];
1792
- for (const page of result.pages) {
1793
- importLines.push(`import '${relativeModuleId(root, page.script)}'`);
1492
+ function normalizeComponentKey(raw) {
1493
+ return raw.trim().toLowerCase();
1494
+ }
1495
+
1496
+ // src/plugin/scan.ts
1497
+ 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
+ });
1794
1525
  }
1795
- for (const component of result.components) {
1796
- importLines.push(`import '${relativeModuleId(root, component.script)}'`);
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);
1797
1640
  }
1798
- if (result.app) {
1799
- importLines.push(`import '${relativeModuleId(root, result.app)}'`);
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 });
1800
1714
  }
1801
- const pageOrder = result.pages.map((page) => page.id);
1802
- const rpxConfig = wxssOptions?.designWidth ? { designWidth: wxssOptions.designWidth, varName: wxssOptions.rpxVar } : void 0;
1803
- const initOptions = {};
1804
- if (rpxConfig) {
1805
- initOptions.rpx = rpxConfig;
1715
+ }
1716
+ function resolveComponentBase(raw, importerDir, srcRoot) {
1717
+ if (!raw) {
1718
+ return void 0;
1806
1719
  }
1807
- if (pluginOptions?.form?.preventDefault !== void 0) {
1808
- initOptions.form = { preventDefault: pluginOptions.form.preventDefault };
1720
+ if (raw.startsWith(".")) {
1721
+ return resolve2(importerDir, raw);
1809
1722
  }
1810
- const initOptionsCode = Object.keys(initOptions).length > 0 ? `, ${JSON.stringify(initOptions)}` : "";
1811
- bodyLines.push(`initializePageRoutes(${JSON.stringify(pageOrder)}${initOptionsCode})`);
1812
- return [...importLines, ...bodyLines].join("\n");
1723
+ if (raw.startsWith("/")) {
1724
+ return resolve2(srcRoot, raw.slice(1));
1725
+ }
1726
+ return resolve2(srcRoot, raw);
1813
1727
  }
1814
- function relativeModuleId(root, absPath) {
1815
- const rel = relative2(root, absPath);
1816
- return `/${normalizePath2(rel)}`;
1728
+
1729
+ // src/plugin/state.ts
1730
+ 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
1749
+ function isTemplateFile(id) {
1750
+ const lower = id.toLowerCase();
1751
+ return TEMPLATE_EXTS.some((ext) => lower.endsWith(ext));
1752
+ }
1753
+ function isWxsFile(id) {
1754
+ const lower = id.toLowerCase();
1755
+ return WXS_EXTS.some((ext) => lower.endsWith(ext));
1756
+ }
1757
+ function hasWxsQuery(id) {
1758
+ return id.includes("?wxs") || id.includes("&wxs");
1759
+ }
1760
+ 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");
1807
+ }
1808
+ 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
+ };
1817
1929
  }
1818
1930
  export {
1819
1931
  weappWebPlugin