@dimina/compiler 1.0.7 → 1.0.9

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.
@@ -1,4 +1,5 @@
1
1
  import fs from "node:fs";
2
+ import path from "node:path";
2
3
  import { isMainThread, parentPort } from "node:worker_threads";
3
4
  import babel from "@babel/core";
4
5
  import _traverse from "@babel/traverse";
@@ -7,10 +8,14 @@ import { compileTemplate } from "@vue/compiler-sfc";
7
8
  import * as cheerio from "cheerio";
8
9
  import { transform } from "esbuild";
9
10
  import * as htmlparser2 from "htmlparser2";
10
- import { r as resetStoreInfo, g as getTargetPath, a as getComponent, b as getContentByPath, c as getAbsolutePath, d as getWorkPath, e as collectAssets, f as getAppId, t as transformRpx, h as tagWhiteList } from "../env-fkuCnng-.js";
11
+ import { r as resetStoreInfo, g as getTargetPath, a as getComponent, b as getContentByPath, c as getAbsolutePath, d as getWorkPath, e as collectAssets, f as getAppId, t as transformRpx, h as tagWhiteList } from "../env-Csj3AHY4.js";
11
12
  const traverse = _traverse.default ? _traverse.default : _traverse;
12
13
  const fileType = [".wxml", ".ddml"];
13
14
  const compileResCache = /* @__PURE__ */ new Map();
15
+ const wxsModuleRegistry = /* @__PURE__ */ new Set();
16
+ const wxsFilePathMap = /* @__PURE__ */ new Map();
17
+ const moduleCompileStatus = /* @__PURE__ */ new Map();
18
+ const moduleCompileResults = /* @__PURE__ */ new Map();
14
19
  if (!isMainThread) {
15
20
  parentPort.on("message", async ({ pages, storeInfo }) => {
16
21
  try {
@@ -35,7 +40,17 @@ if (!isMainThread) {
35
40
  }
36
41
  });
37
42
  }
43
+ function clearCompileState() {
44
+ moduleCompileStatus.clear();
45
+ moduleCompileResults.clear();
46
+ compileResCache.clear();
47
+ wxsModuleRegistry.clear();
48
+ wxsFilePathMap.clear();
49
+ }
38
50
  async function compileML(pages, root, progress) {
51
+ const workPath = getWorkPath();
52
+ clearCompileState();
53
+ initWxsFilePathMap(workPath);
39
54
  for (const page of pages) {
40
55
  const scriptRes = /* @__PURE__ */ new Map();
41
56
  buildCompileView(page, false, scriptRes, []);
@@ -68,46 +83,143 @@ async function compileML(pages, root, progress) {
68
83
  progress.completedTasks++;
69
84
  }
70
85
  }
86
+ function initWxsFilePathMap(workPath) {
87
+ wxsFilePathMap.clear();
88
+ const npmDir = path.join(workPath, "miniprogram_npm");
89
+ if (fs.existsSync(npmDir)) {
90
+ scanWxsFiles(npmDir, workPath);
91
+ }
92
+ }
93
+ function scanWxsFiles(dir, workPath) {
94
+ try {
95
+ const items = fs.readdirSync(dir);
96
+ for (const item of items) {
97
+ const fullPath = path.join(dir, item);
98
+ const stat = fs.statSync(fullPath);
99
+ if (stat.isDirectory()) {
100
+ scanWxsFiles(fullPath, workPath);
101
+ } else if (stat.isFile() && item.endsWith(".wxs")) {
102
+ const relativePath = fullPath.replace(workPath, "").replace(/\.wxs$/, "");
103
+ const moduleName = relativePath.replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
104
+ wxsFilePathMap.set(moduleName, fullPath);
105
+ }
106
+ }
107
+ } catch (error) {
108
+ }
109
+ }
110
+ function registerWxsModule(modulePath) {
111
+ wxsModuleRegistry.add(modulePath);
112
+ }
113
+ function isRegisteredWxsModule(modulePath) {
114
+ return wxsModuleRegistry.has(modulePath);
115
+ }
71
116
  function buildCompileView(module, isComponent = false, scriptRes, depthChain = []) {
72
117
  const currentPath = module.path;
118
+ if (moduleCompileStatus.has(currentPath)) {
119
+ const status = moduleCompileStatus.get(currentPath);
120
+ if (status === "pending") {
121
+ console.warn("[view]", `检测到循环依赖: ${[...depthChain, currentPath].join(" -> ")}`);
122
+ return { scriptModule: [] };
123
+ } else if (status === "completed") {
124
+ return moduleCompileResults.get(currentPath) || { scriptModule: [] };
125
+ } else if (status === "failed") {
126
+ console.warn("[view]", `模块编译失败,跳过: ${currentPath}`);
127
+ return { scriptModule: [] };
128
+ }
129
+ }
73
130
  if (depthChain.includes(currentPath)) {
74
131
  console.warn("[view]", `检测到循环依赖: ${[...depthChain, currentPath].join(" -> ")}`);
75
- return;
132
+ return { scriptModule: [] };
76
133
  }
77
- if (depthChain.length > 20) {
78
- console.warn("[view]", `检测到深度依赖: ${[...depthChain, currentPath].join(" -> ")}`);
79
- return;
134
+ if (depthChain.length > 5) {
135
+ console.warn("[view]", `检测到深度依赖,中断编译: ${[...depthChain, currentPath].join(" -> ")}`);
136
+ return { scriptModule: [] };
80
137
  }
138
+ moduleCompileStatus.set(currentPath, "pending");
81
139
  depthChain = [...depthChain, currentPath];
82
- compileModule(module, isComponent, scriptRes);
83
- if (module.usingComponents) {
84
- for (const componentInfo of Object.values(module.usingComponents)) {
85
- const componentModule = getComponent(componentInfo);
86
- if (!componentModule) {
87
- continue;
140
+ try {
141
+ const allScriptModules = [];
142
+ const currentInstruction = compileModule(module, isComponent, scriptRes);
143
+ if (currentInstruction && currentInstruction.scriptModule) {
144
+ allScriptModules.push(...currentInstruction.scriptModule);
145
+ }
146
+ if (module.usingComponents) {
147
+ for (const componentInfo of Object.values(module.usingComponents)) {
148
+ const componentModule = getComponent(componentInfo);
149
+ if (!componentModule) {
150
+ continue;
151
+ }
152
+ if (componentModule.path === module.path) {
153
+ console.warn("[view]", `检测到自依赖,跳过处理: ${module.path}`);
154
+ continue;
155
+ }
156
+ const componentInstruction = buildCompileView(componentModule, true, scriptRes, depthChain);
157
+ if (componentInstruction && componentInstruction.scriptModule) {
158
+ for (const sm of componentInstruction.scriptModule) {
159
+ if (!allScriptModules.find((existing) => existing.path === sm.path)) {
160
+ allScriptModules.push(sm);
161
+ }
162
+ }
163
+ }
88
164
  }
89
- if (componentModule.path === module.path) {
90
- console.warn("[view]", `检测到自依赖,跳过处理: ${module.path}`);
91
- continue;
165
+ }
166
+ if (!isComponent && allScriptModules.length > 0) {
167
+ for (const sm of allScriptModules) {
168
+ if (!scriptRes.has(sm.path)) {
169
+ scriptRes.set(sm.path, sm.code);
170
+ }
92
171
  }
93
- buildCompileView(componentModule, true, scriptRes, depthChain);
172
+ compileModuleWithAllWxs(module, scriptRes, allScriptModules);
94
173
  }
174
+ const result = { scriptModule: allScriptModules };
175
+ moduleCompileStatus.set(currentPath, "completed");
176
+ moduleCompileResults.set(currentPath, result);
177
+ return result;
178
+ } catch (error) {
179
+ moduleCompileStatus.set(currentPath, "failed");
180
+ console.error("[view]", `模块编译失败: ${currentPath}`, error.message);
181
+ return { scriptModule: [] };
95
182
  }
96
183
  }
97
184
  function compileModule(module, isComponent, scriptRes) {
98
185
  const { tpl, instruction } = toCompileTemplate(isComponent, module.path, module.usingComponents, module.componentPlaceholder);
99
186
  if (!tpl) {
100
- return;
187
+ return null;
101
188
  }
189
+ let useCache = false;
190
+ let cachedCode = null;
102
191
  if (!scriptRes.has(module.path) && compileResCache.has(module.path)) {
103
- const res = compileResCache.get(module.path);
104
- scriptRes.set(module.path, res);
105
- for (const sm of instruction.scriptModule) {
106
- if (!scriptRes.has(sm.path)) {
107
- scriptRes.set(sm.path, sm.code);
192
+ const cacheData2 = compileResCache.get(module.path);
193
+ if (cacheData2 && typeof cacheData2 === "object" && cacheData2.code && cacheData2.instruction) {
194
+ cachedCode = cacheData2.code;
195
+ useCache = true;
196
+ for (const sm of cacheData2.instruction.scriptModule) {
197
+ if (!scriptRes.has(sm.path)) {
198
+ scriptRes.set(sm.path, sm.code);
199
+ }
108
200
  }
201
+ } else if (typeof cacheData2 === "string") {
202
+ cachedCode = cacheData2;
203
+ useCache = true;
109
204
  }
110
- return;
205
+ }
206
+ if (useCache && cachedCode) {
207
+ scriptRes.set(module.path, cachedCode);
208
+ const allWxsModules2 = collectAllWxsModules(scriptRes, /* @__PURE__ */ new Set(), instruction.scriptModule || []);
209
+ if (allWxsModules2.length > 0) {
210
+ const existingModules = instruction.scriptModule || [];
211
+ const mergedModules = [...existingModules];
212
+ for (const wxsModule of allWxsModules2) {
213
+ if (!mergedModules.find((existing) => existing.path === wxsModule.path)) {
214
+ mergedModules.push(wxsModule);
215
+ }
216
+ }
217
+ instruction.scriptModule = mergedModules;
218
+ }
219
+ return {
220
+ ...instruction,
221
+ scriptModule: allWxsModules2
222
+ };
111
223
  }
112
224
  const processedTpl = tpl.replace(/\bthis\./g, "_ctx.");
113
225
  const tplCode = compileTemplate({
@@ -162,12 +274,233 @@ function compileModule(module, isComponent, scriptRes) {
162
274
  usingComponents: ${JSON.stringify(module.usingComponents)},
163
275
  tplComponents: ${tplComponents},
164
276
  });`;
165
- compileResCache.set(module.path, code);
277
+ const allWxsModules = collectAllWxsModules(scriptRes, /* @__PURE__ */ new Set(), instruction.scriptModule || []);
278
+ if (allWxsModules.length > 0) {
279
+ const existingModules = instruction.scriptModule || [];
280
+ const mergedModules = [...existingModules];
281
+ for (const wxsModule of allWxsModules) {
282
+ if (!mergedModules.find((existing) => existing.path === wxsModule.path)) {
283
+ mergedModules.push(wxsModule);
284
+ }
285
+ }
286
+ instruction.scriptModule = mergedModules;
287
+ }
288
+ const cacheData = {
289
+ code,
290
+ instruction
291
+ };
292
+ compileResCache.set(module.path, cacheData);
166
293
  scriptRes.set(module.path, code);
294
+ return instruction;
167
295
  }
168
- function toCompileTemplate(isComponent, path, components, componentPlaceholder) {
296
+ function processWxsContent(wxsContent, wxsFilePath, scriptModule, workPath, filePath) {
297
+ let wxsAst;
298
+ try {
299
+ wxsAst = babel.parseSync(wxsContent);
300
+ } catch (error) {
301
+ console.error(`[view] 解析 wxs 文件失败: ${wxsFilePath}`, error.message);
302
+ return wxsContent;
303
+ }
304
+ traverse(wxsAst, {
305
+ CallExpression(astPath) {
306
+ const calleeName = astPath.node.callee.name;
307
+ if (calleeName === "getRegExp") {
308
+ const args = astPath.node.arguments;
309
+ if (args.length > 0) {
310
+ if (args[0].type === "StringLiteral" && (!args[1] || args[1].type === "StringLiteral")) {
311
+ let pattern = "";
312
+ let flags = "";
313
+ const arg = args[0];
314
+ if (arg.extra && arg.extra.raw) {
315
+ pattern = arg.extra.raw.slice(1, -1);
316
+ } else if (arg.value !== void 0) {
317
+ pattern = arg.value;
318
+ } else {
319
+ pattern = "";
320
+ }
321
+ if (args.length > 1) {
322
+ const flagArg = args[1];
323
+ if (flagArg.extra && flagArg.extra.raw) {
324
+ flags = flagArg.extra.raw.slice(1, -1);
325
+ } else if (flagArg.value !== void 0) {
326
+ flags = flagArg.value;
327
+ } else {
328
+ flags = "";
329
+ }
330
+ }
331
+ const regexLiteral = types.regExpLiteral(pattern, flags);
332
+ astPath.replaceWith(regexLiteral);
333
+ } else {
334
+ const newRegExpArgs = [args[0]];
335
+ if (args.length > 1) {
336
+ newRegExpArgs.push(args[1]);
337
+ }
338
+ const newRegExpCall = types.newExpression(
339
+ types.identifier("RegExp"),
340
+ newRegExpArgs
341
+ );
342
+ astPath.replaceWith(newRegExpCall);
343
+ }
344
+ }
345
+ } else if (calleeName === "getDate") {
346
+ const args = [];
347
+ for (let i = 0; i < astPath.node.arguments.length; i++) {
348
+ args.push(astPath.node.arguments[i]);
349
+ }
350
+ const newExpr = types.newExpression(types.identifier("Date"), args);
351
+ astPath.replaceWith(newExpr);
352
+ } else if (calleeName === "require" && astPath.node.arguments.length > 0 && wxsFilePath) {
353
+ const requirePath = astPath.node.arguments[0].value;
354
+ if (requirePath && typeof requirePath === "string") {
355
+ let resolvedWxsPath;
356
+ if (filePath && filePath.includes("/miniprogram_npm/")) {
357
+ const currentWxsDir = path.dirname(wxsFilePath);
358
+ resolvedWxsPath = path.resolve(currentWxsDir, requirePath);
359
+ const relativePath = resolvedWxsPath.replace(workPath, "").replace(/\.wxs$/, "");
360
+ const moduleName = relativePath.replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
361
+ processWxsDependency(resolvedWxsPath, moduleName, scriptModule, workPath, filePath);
362
+ astPath.node.arguments[0] = types.stringLiteral(moduleName);
363
+ } else {
364
+ const currentWxsDir = path.dirname(wxsFilePath);
365
+ resolvedWxsPath = path.resolve(currentWxsDir, requirePath);
366
+ const relativePath = resolvedWxsPath.replace(workPath, "").replace(/\.wxs$/, "");
367
+ const depModuleName = relativePath.replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
368
+ processWxsDependency(resolvedWxsPath, depModuleName, scriptModule, workPath, filePath);
369
+ astPath.node.arguments[0] = types.stringLiteral(depModuleName);
370
+ }
371
+ }
372
+ }
373
+ },
374
+ MemberExpression(astPath) {
375
+ if (astPath.node.property.name === "constructor" && !astPath.node.computed) {
376
+ const getTypeString = types.callExpression(
377
+ types.memberExpression(
378
+ types.callExpression(
379
+ types.memberExpression(
380
+ types.memberExpression(
381
+ types.memberExpression(
382
+ types.identifier("Object"),
383
+ types.identifier("prototype")
384
+ ),
385
+ types.identifier("toString")
386
+ ),
387
+ types.identifier("call")
388
+ ),
389
+ [astPath.node.object]
390
+ ),
391
+ types.identifier("slice")
392
+ ),
393
+ [types.numericLiteral(8), types.numericLiteral(-1)]
394
+ );
395
+ astPath.replaceWith(getTypeString);
396
+ }
397
+ }
398
+ });
399
+ return babel.transformFromAstSync(wxsAst, "", {
400
+ comments: false
401
+ }).code;
402
+ }
403
+ function isWxsModuleByContent(moduleCode, modulePath = "") {
404
+ if (!moduleCode || typeof moduleCode !== "string") {
405
+ return false;
406
+ }
407
+ if (modulePath && isRegisteredWxsModule(modulePath)) {
408
+ return true;
409
+ }
410
+ return false;
411
+ }
412
+ function processWxsDependency(wxsFilePath, moduleName, scriptModule, workPath, filePath) {
413
+ if (!fs.existsSync(wxsFilePath)) {
414
+ console.warn(`[view] wxs 依赖文件不存在: ${wxsFilePath}`);
415
+ return;
416
+ }
417
+ if (scriptModule.find((sm) => sm.path === moduleName)) {
418
+ return;
419
+ }
420
+ const wxsContent = getContentByPath(wxsFilePath).trim();
421
+ if (!wxsContent) {
422
+ return;
423
+ }
424
+ const wxsCode = processWxsContent(wxsContent, wxsFilePath, scriptModule, workPath, filePath);
425
+ registerWxsModule(moduleName);
426
+ scriptModule.push({
427
+ path: moduleName,
428
+ code: wxsCode
429
+ });
430
+ }
431
+ function compileModuleWithAllWxs(module, scriptRes, allScriptModules) {
432
+ const { tpl, instruction } = toCompileTemplate(false, module.path, module.usingComponents, module.componentPlaceholder);
433
+ if (!tpl) {
434
+ return;
435
+ }
436
+ const mergedInstruction = {
437
+ ...instruction,
438
+ scriptModule: allScriptModules
439
+ };
440
+ const processedTpl = tpl.replace(/\bthis\./g, "_ctx.");
441
+ const tplCode = compileTemplate({
442
+ source: processedTpl,
443
+ filename: module.path,
444
+ id: `data-v-${module.id}`,
445
+ scoped: true,
446
+ compilerOptions: {
447
+ prefixIdentifiers: true,
448
+ hoistStatic: false,
449
+ cacheHandlers: true,
450
+ scopeId: `data-v-${module.id}`,
451
+ mode: "function",
452
+ inline: true
453
+ }
454
+ });
455
+ let tplComponents = "{";
456
+ for (const tm of mergedInstruction.templateModule) {
457
+ let { code: code2 } = compileTemplate({
458
+ source: tm.tpl,
459
+ filename: tm.path,
460
+ id: `data-v-${module.id}`,
461
+ scoped: true,
462
+ compilerOptions: {
463
+ prefixIdentifiers: true,
464
+ hoistStatic: false,
465
+ cacheHandlers: true,
466
+ scopeId: `data-v-${module.id}`,
467
+ mode: "function",
468
+ inline: true
469
+ }
470
+ });
471
+ const ast = babel.parseSync(code2);
472
+ insertWxsToRenderAst(ast, allScriptModules, scriptRes);
473
+ code2 = babel.transformFromAstSync(ast, "", {
474
+ comments: false
475
+ }).code;
476
+ tplComponents += `'${tm.path}':${code2.replace(/;$/, "").replace(/^"use strict";\s*/, "")},`;
477
+ }
478
+ tplComponents += "}";
479
+ const tplAst = babel.parseSync(tplCode.code);
480
+ insertWxsToRenderAst(tplAst, allScriptModules, scriptRes);
481
+ const { code: transCode } = babel.transformFromAstSync(tplAst, "", {
482
+ comments: false
483
+ });
484
+ const code = `Module({
485
+ path: '${module.path}',
486
+ id: '${module.id}',
487
+ render: ${transCode.replace(/;$/, "").replace(/^"use strict";\s*/, "")},
488
+ usingComponents: ${JSON.stringify(module.usingComponents)},
489
+ tplComponents: ${tplComponents},
490
+ });`;
491
+ const cacheData = {
492
+ code,
493
+ instruction: mergedInstruction
494
+ };
495
+ compileResCache.set(module.path, cacheData);
496
+ scriptRes.set(module.path, code);
497
+ }
498
+ function processIncludedFileWxsDependencies(content, includePath, scriptModule, components) {
499
+ console.warn("[view]", `跳过被引入文件的组件 wxs 依赖处理: ${includePath}`);
500
+ }
501
+ function toCompileTemplate(isComponent, path2, components, componentPlaceholder) {
169
502
  const workPath = getWorkPath();
170
- const fullPath = getViewPath(workPath, path);
503
+ const fullPath = getViewPath(workPath, path2);
171
504
  if (!fullPath) {
172
505
  return { tpl: void 0 };
173
506
  }
@@ -176,7 +509,7 @@ function toCompileTemplate(isComponent, path, components, componentPlaceholder)
176
509
  content = "<block></block>";
177
510
  } else {
178
511
  if (isComponent) {
179
- content = `<wrapper>${content}</wrapper>`;
512
+ content = `<wrapper name="${path2}">${content}</wrapper>`;
180
513
  } else {
181
514
  const tempRoot = cheerio.load(content, {
182
515
  xmlMode: true,
@@ -198,27 +531,51 @@ function toCompileTemplate(isComponent, path, components, componentPlaceholder)
198
531
  includeNodes.each((_, elem) => {
199
532
  const src = $(elem).attr("src");
200
533
  if (src) {
201
- const includeContent = getContentByPath(getAbsolutePath(workPath, path, src)).trim();
534
+ const includeFullPath = getAbsolutePath(workPath, path2, src);
535
+ let includePath = includeFullPath.replace(workPath, "").replace(/\.(wxml|ddml)$/, "");
536
+ if (!includePath.startsWith("/")) {
537
+ includePath = "/" + includePath;
538
+ }
539
+ const includeContent = getContentByPath(includeFullPath).trim();
202
540
  if (includeContent) {
203
541
  const $includeContent = cheerio.load(includeContent, {
204
542
  xmlMode: true,
205
543
  decodeEntities: false
206
544
  });
545
+ transTagTemplate(
546
+ $includeContent,
547
+ templateModule,
548
+ includePath,
549
+ components
550
+ );
551
+ transTagWxs(
552
+ $includeContent,
553
+ scriptModule,
554
+ includePath
555
+ );
556
+ processIncludedFileWxsDependencies(includeContent, includePath);
207
557
  $includeContent("template").remove();
208
558
  $includeContent("wxs").remove();
209
559
  $includeContent("dds").remove();
210
- $(elem).html($includeContent.html());
560
+ $(elem).replaceWith($includeContent.html());
561
+ } else {
562
+ $(elem).remove();
211
563
  }
564
+ } else {
565
+ $(elem).remove();
212
566
  }
213
567
  });
214
- transTagTemplate($, templateModule, path, components);
215
- transTagWxs($, scriptModule, path);
568
+ transTagTemplate($, templateModule, path2, components);
569
+ transTagWxs($, scriptModule, path2);
216
570
  const importNodes = $("import");
217
571
  importNodes.each((_, elem) => {
218
572
  const src = $(elem).attr("src");
219
573
  if (src) {
220
- const importFullPath = getAbsolutePath(workPath, path, src);
221
- const importPath = importFullPath.replace(workPath, "").split("/").slice(0, -1).join("/");
574
+ const importFullPath = getAbsolutePath(workPath, path2, src);
575
+ let importPath = importFullPath.replace(workPath, "").replace(/\.(wxml|ddml)$/, "");
576
+ if (!importPath.startsWith("/")) {
577
+ importPath = "/" + importPath;
578
+ }
222
579
  const importContent = getContentByPath(importFullPath).trim();
223
580
  if (importContent) {
224
581
  const $$ = cheerio.load(importContent, {
@@ -228,7 +585,7 @@ function toCompileTemplate(isComponent, path, components, componentPlaceholder)
228
585
  transTagTemplate(
229
586
  $$,
230
587
  templateModule,
231
- path,
588
+ path2,
232
589
  components
233
590
  );
234
591
  transTagWxs(
@@ -236,11 +593,12 @@ function toCompileTemplate(isComponent, path, components, componentPlaceholder)
236
593
  scriptModule,
237
594
  importPath
238
595
  );
596
+ processIncludedFileWxsDependencies(importContent, importPath);
239
597
  }
240
598
  }
241
599
  });
242
600
  importNodes.remove();
243
- transAsses($, $("image"), path);
601
+ transAsses($, $("image"), path2);
244
602
  const res = [];
245
603
  transHtmlTag($.html(), res, components);
246
604
  return {
@@ -251,7 +609,7 @@ function toCompileTemplate(isComponent, path, components, componentPlaceholder)
251
609
  }
252
610
  };
253
611
  }
254
- function transTagTemplate($, templateModule, path, components, componentPlaceholder) {
612
+ function transTagTemplate($, templateModule, path2, components, componentPlaceholder) {
255
613
  const templateNodes = $("template[name]");
256
614
  templateNodes.each((_, elem) => {
257
615
  const name = $(elem).attr("name");
@@ -260,7 +618,7 @@ function transTagTemplate($, templateModule, path, components, componentPlacehol
260
618
  templateContent.find("include").remove();
261
619
  templateContent.find("wxs").remove();
262
620
  templateContent.find("dds").remove();
263
- transAsses($, templateContent.find("image"), path);
621
+ transAsses($, templateContent.find("image"), path2);
264
622
  const res = [];
265
623
  transHtmlTag(templateContent.html(), res, components);
266
624
  templateModule.push({
@@ -270,11 +628,11 @@ function transTagTemplate($, templateModule, path, components, componentPlacehol
270
628
  });
271
629
  templateNodes.remove();
272
630
  }
273
- function transAsses($, imageNodes, path) {
631
+ function transAsses($, imageNodes, path2) {
274
632
  imageNodes.each((_, elem) => {
275
633
  const imgSrc = $(elem).attr("src").trim();
276
634
  if (!imgSrc.startsWith("{{")) {
277
- $(elem).attr("src", collectAssets(getWorkPath(), path, imgSrc, getTargetPath(), getAppId()));
635
+ $(elem).attr("src", collectAssets(getWorkPath(), path2, imgSrc, getTargetPath(), getAppId()));
278
636
  }
279
637
  });
280
638
  }
@@ -369,7 +727,7 @@ function getProps(attrs, tag) {
369
727
  });
370
728
  } else if (name.endsWith(":for-item") || name.endsWith(":for-index")) ;
371
729
  else if (name.endsWith(":key")) {
372
- const tranValue = parseKeyExpression(value, getForItemName(attrs));
730
+ const tranValue = parseKeyExpression(value, getForItemName(attrs), getForIndexName(attrs));
373
731
  attrsList.push({
374
732
  name: ":key",
375
733
  value: tranValue
@@ -486,7 +844,7 @@ function generateVModelTemplate(expression) {
486
844
  }
487
845
  return updateExpression;
488
846
  }
489
- function parseKeyExpression(exp, itemName = "item") {
847
+ function parseKeyExpression(exp, itemName = "item", indexName = "index") {
490
848
  exp = exp.trim();
491
849
  if (/\*this/.test(exp) || /\*item/.test(exp)) {
492
850
  return `${itemName}.toString()`;
@@ -495,12 +853,17 @@ function parseKeyExpression(exp, itemName = "item") {
495
853
  if (/^-?\d+(\.\d+)?$/.test(exp)) {
496
854
  return exp;
497
855
  }
856
+ if (exp === indexName) {
857
+ return indexName;
858
+ }
498
859
  return exp.startsWith(itemName) ? `${exp}` : `${itemName}.${exp}`;
499
860
  }
500
861
  if (exp.startsWith("{{") && exp.endsWith("}}")) {
501
862
  const content = exp.slice(2, -2).trim();
502
863
  if (content === "this") {
503
864
  return `${itemName}.toString()`;
865
+ } else if (content === indexName) {
866
+ return indexName;
504
867
  } else {
505
868
  return content.startsWith(itemName) ? `${content}` : `${itemName}.${content}`;
506
869
  }
@@ -509,6 +872,9 @@ function parseKeyExpression(exp, itemName = "item") {
509
872
  const result = parts.map((part) => {
510
873
  if (part.startsWith("{{") && part.endsWith("}}")) {
511
874
  const content = part.slice(2, -2).trim();
875
+ if (content === indexName) {
876
+ return indexName;
877
+ }
512
878
  return content.startsWith(itemName) ? content : `${itemName}.${content}`;
513
879
  }
514
880
  return `'${part}'`;
@@ -614,7 +980,7 @@ function parseBraceExp(exp) {
614
980
  }
615
981
  return group.join("").replace(/^\+|\+$/g, "");
616
982
  }
617
- function transTagWxs($, scriptModule, path) {
983
+ function transTagWxs($, scriptModule, filePath) {
618
984
  let wxsNodes = $("wxs");
619
985
  if (wxsNodes.length === 0) {
620
986
  wxsNodes = $("dds");
@@ -623,56 +989,158 @@ function transTagWxs($, scriptModule, path) {
623
989
  const smName = $(elem).attr("module");
624
990
  if (smName) {
625
991
  let wxsContent;
626
- if (compileResCache.has(smName)) {
627
- wxsContent = compileResCache.get(smName);
992
+ let uniqueModuleName = smName;
993
+ let cacheKey = smName;
994
+ const src = $(elem).attr("src");
995
+ let wxsFilePath = null;
996
+ const workPath = getWorkPath();
997
+ if (src) {
998
+ if (filePath.includes("/miniprogram_npm/")) {
999
+ const componentDir = filePath.split("/").slice(0, -1).join("/");
1000
+ const componentFullPath = workPath + componentDir;
1001
+ wxsFilePath = path.resolve(componentFullPath, src);
1002
+ } else {
1003
+ wxsFilePath = getAbsolutePath(workPath, filePath, src);
1004
+ }
1005
+ if (wxsFilePath) {
1006
+ const relativePath = wxsFilePath.replace(workPath, "").replace(/\.wxs$/, "");
1007
+ uniqueModuleName = relativePath.replace(/[\/\\@\-]/g, "_").replace(/^_/, "");
1008
+ cacheKey = wxsFilePath;
1009
+ }
1010
+ }
1011
+ if (compileResCache.has(cacheKey)) {
1012
+ wxsContent = compileResCache.get(cacheKey);
628
1013
  } else {
629
- const src = $(elem).attr("src");
630
- if (src) {
631
- wxsContent = getContentByPath(getAbsolutePath(getWorkPath(), path, src)).trim();
1014
+ if (src && wxsFilePath) {
1015
+ if (fs.existsSync(wxsFilePath)) {
1016
+ wxsContent = getContentByPath(wxsFilePath).trim();
1017
+ } else {
1018
+ console.warn(`[view] wxs 文件不存在: ${wxsFilePath}`);
1019
+ return;
1020
+ }
632
1021
  } else {
633
1022
  wxsContent = $(elem).html();
634
1023
  }
635
- const wxsAst = babel.parseSync(wxsContent);
636
- traverse(wxsAst, {
637
- CallExpression(path2) {
638
- if (path2.node.callee.name === "getRegExp" || path2.node.callee.name === "getDate") {
639
- const args = [];
640
- for (let i = 0; i < path2.node.arguments.length; i++) {
641
- args.push(path2.node.arguments[i]);
642
- }
643
- const newExpr = types.newExpression(types.identifier(path2.node.callee.name.substring(3)), args);
644
- path2.replaceWith(newExpr);
645
- }
646
- }
647
- });
648
- wxsContent = babel.transformFromAstSync(wxsAst, "", {
649
- comments: false
650
- }).code;
651
- compileResCache.set(smName, wxsContent);
1024
+ if (!wxsContent) {
1025
+ return;
1026
+ }
1027
+ wxsContent = processWxsContent(wxsContent, wxsFilePath, scriptModule, workPath, filePath);
1028
+ compileResCache.set(cacheKey, wxsContent);
652
1029
  }
653
1030
  if (wxsContent) {
1031
+ registerWxsModule(uniqueModuleName);
654
1032
  scriptModule.push({
655
- path: smName,
656
- code: wxsContent
1033
+ path: uniqueModuleName,
1034
+ code: wxsContent,
1035
+ originalName: smName
1036
+ // 保存原始模块名用于模板中的引用
657
1037
  });
658
1038
  }
659
1039
  }
660
1040
  });
661
1041
  wxsNodes.remove();
662
1042
  }
1043
+ function collectAllWxsModules(scriptRes, collectedPaths = /* @__PURE__ */ new Set(), scriptModule = [], maxDepth = 5) {
1044
+ if (maxDepth <= 0) {
1045
+ console.warn("[view]", "collectAllWxsModules 达到最大递归深度,停止处理");
1046
+ return [];
1047
+ }
1048
+ const allWxsModules = [];
1049
+ const workPath = getWorkPath();
1050
+ for (const [modulePath, moduleCode] of scriptRes.entries()) {
1051
+ if (collectedPaths.has(modulePath)) {
1052
+ continue;
1053
+ }
1054
+ if (isWxsModuleByContent(moduleCode, modulePath)) {
1055
+ collectedPaths.add(modulePath);
1056
+ allWxsModules.push({
1057
+ path: modulePath,
1058
+ code: moduleCode
1059
+ });
1060
+ const dependencies = extractWxsDependencies(moduleCode);
1061
+ for (const depPath of dependencies) {
1062
+ if (!collectedPaths.has(depPath)) {
1063
+ if (scriptRes.has(depPath)) {
1064
+ const depModules = collectAllWxsModules(
1065
+ /* @__PURE__ */ new Map([[depPath, scriptRes.get(depPath)]]),
1066
+ collectedPaths,
1067
+ scriptModule,
1068
+ maxDepth - 1
1069
+ );
1070
+ allWxsModules.push(...depModules);
1071
+ } else {
1072
+ const loaded = loadWxsModule(depPath, workPath, scriptModule);
1073
+ if (loaded) {
1074
+ scriptRes.set(depPath, loaded.code);
1075
+ allWxsModules.push(loaded);
1076
+ collectedPaths.add(depPath);
1077
+ const depModules = collectAllWxsModules(
1078
+ /* @__PURE__ */ new Map([[depPath, loaded.code]]),
1079
+ collectedPaths,
1080
+ scriptModule,
1081
+ maxDepth - 1
1082
+ );
1083
+ allWxsModules.push(...depModules);
1084
+ }
1085
+ }
1086
+ }
1087
+ }
1088
+ }
1089
+ }
1090
+ return allWxsModules;
1091
+ }
1092
+ function loadWxsModule(modulePath, workPath, scriptModule) {
1093
+ if (!modulePath.startsWith("miniprogram_npm__") || !modulePath.includes("_wxs_")) {
1094
+ return null;
1095
+ }
1096
+ const wxsFilePath = wxsFilePathMap.get(modulePath);
1097
+ if (!wxsFilePath) {
1098
+ console.warn(`[view] 无法找到 wxs 模块文件: ${modulePath}`);
1099
+ return null;
1100
+ }
1101
+ try {
1102
+ const wxsContent = getContentByPath(wxsFilePath).trim();
1103
+ if (!wxsContent) {
1104
+ return null;
1105
+ }
1106
+ const processedContent = processWxsContent(wxsContent, wxsFilePath, scriptModule, workPath, "");
1107
+ registerWxsModule(modulePath);
1108
+ return {
1109
+ path: modulePath,
1110
+ code: processedContent
1111
+ };
1112
+ } catch (error) {
1113
+ console.warn(`[view] 加载 wxs 模块失败: ${modulePath}`, error.message);
1114
+ return null;
1115
+ }
1116
+ }
1117
+ function extractWxsDependencies(moduleCode) {
1118
+ const dependencies = [];
1119
+ const requirePattern = /(?:require|_)\s*\(\s*["']([^"']+)["']\s*\)/g;
1120
+ let match;
1121
+ while ((match = requirePattern.exec(moduleCode)) !== null) {
1122
+ const depPath = match[1];
1123
+ if (depPath && !dependencies.includes(depPath)) {
1124
+ dependencies.push(depPath);
1125
+ }
1126
+ }
1127
+ return dependencies;
1128
+ }
663
1129
  function insertWxsToRenderAst(ast, scriptModule, scriptRes) {
664
1130
  for (const sm of scriptModule) {
665
1131
  if (!scriptRes.has(sm.path)) {
666
1132
  scriptRes.set(sm.path, sm.code);
667
1133
  }
1134
+ const templatePropertyName = sm.originalName || sm.path;
1135
+ const requireModuleName = sm.path;
668
1136
  const assignmentExpression = types.assignmentExpression(
669
1137
  "=",
670
1138
  // 创建赋值表达式
671
1139
  types.memberExpression(
672
1140
  types.identifier("_ctx"),
673
1141
  // 对象标识符
674
- types.identifier(sm.path),
675
- // 属性标识符
1142
+ types.identifier(templatePropertyName),
1143
+ // 使用原始模块名作为属性名
676
1144
  false
677
1145
  // 是否是计算属性
678
1146
  ),
@@ -680,8 +1148,8 @@ function insertWxsToRenderAst(ast, scriptModule, scriptRes) {
680
1148
  types.callExpression(
681
1149
  types.identifier("require"),
682
1150
  // 函数标识符
683
- [types.stringLiteral(sm.path)]
684
- // 参数列表,这里传入字符串字面量'foo'
1151
+ [types.stringLiteral(requireModuleName)]
1152
+ // 使用唯一模块名作为 require 参数
685
1153
  )
686
1154
  );
687
1155
  const expressionStatement = types.expressionStatement(assignmentExpression);
@@ -694,5 +1162,6 @@ export {
694
1162
  parseBraceExp,
695
1163
  parseClassRules,
696
1164
  parseKeyExpression,
1165
+ processWxsContent,
697
1166
  splitWithBraces
698
1167
  };