@dimina/compiler 1.0.6 → 1.0.8

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,17 +1,21 @@
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
- import types from "@babel/types";
5
5
  import _traverse from "@babel/traverse";
6
+ import types from "@babel/types";
6
7
  import { compileTemplate } from "@vue/compiler-sfc";
7
8
  import * as cheerio from "cheerio";
8
- import * as htmlparser2 from "htmlparser2";
9
9
  import { transform } from "esbuild";
10
- import { r as resetStoreInfo, g as getTargetPath, a as getComponent, b as getContentByPath, c as getAbsolutePath, d as collectAssets, e as getAppId, f as getWorkPath, t as transformRpx, h as tagWhiteList } from "../env-CezfCSQz.js";
10
+ import * as htmlparser2 from "htmlparser2";
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();
14
- const processedModules = /* @__PURE__ */ new Set();
15
+ const wxsModuleRegistry = /* @__PURE__ */ new Set();
16
+ const wxsFilePathMap = /* @__PURE__ */ new Map();
17
+ const moduleCompileStatus = /* @__PURE__ */ new Map();
18
+ const moduleCompileResults = /* @__PURE__ */ new Map();
15
19
  if (!isMainThread) {
16
20
  parentPort.on("message", async ({ pages, storeInfo }) => {
17
21
  try {
@@ -36,7 +40,17 @@ if (!isMainThread) {
36
40
  }
37
41
  });
38
42
  }
43
+ function clearCompileState() {
44
+ moduleCompileStatus.clear();
45
+ moduleCompileResults.clear();
46
+ compileResCache.clear();
47
+ wxsModuleRegistry.clear();
48
+ wxsFilePathMap.clear();
49
+ }
39
50
  async function compileML(pages, root, progress) {
51
+ const workPath = getWorkPath();
52
+ clearCompileState();
53
+ initWxsFilePathMap(workPath);
40
54
  for (const page of pages) {
41
55
  const scriptRes = /* @__PURE__ */ new Map();
42
56
  buildCompileView(page, false, scriptRes, []);
@@ -56,54 +70,156 @@ async function compileML(pages, root, progress) {
56
70
  if (root) {
57
71
  const subDir = `${getTargetPath()}/${root}`;
58
72
  if (!fs.existsSync(subDir)) {
59
- fs.mkdirSync(subDir);
73
+ fs.mkdirSync(subDir, { recursive: true });
60
74
  }
61
75
  fs.writeFileSync(`${subDir}/${filename}.js`, mergeRender);
62
76
  } else {
63
77
  const mainDir = `${getTargetPath()}/main`;
64
78
  if (!fs.existsSync(mainDir)) {
65
- fs.mkdirSync(mainDir);
79
+ fs.mkdirSync(mainDir, { recursive: true });
66
80
  }
67
81
  fs.writeFileSync(`${mainDir}/${filename}.js`, mergeRender);
68
82
  }
69
83
  progress.completedTasks++;
70
84
  }
71
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
+ }
72
116
  function buildCompileView(module, isComponent = false, scriptRes, depthChain = []) {
73
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
+ }
74
130
  if (depthChain.includes(currentPath)) {
75
- console.warn(`检测到循环依赖: ${[...depthChain, currentPath].join(" -> ")}`);
131
+ console.warn("[view]", `检测到循环依赖: ${[...depthChain, currentPath].join(" -> ")}`);
132
+ return { scriptModule: [] };
76
133
  }
77
- if (depthChain.length > 100) {
78
- console.warn(`检测到深度依赖: ${[...depthChain, currentPath].join(" -> ")}`);
134
+ if (depthChain.length > 5) {
135
+ console.warn("[view]", `检测到深度依赖,中断编译: ${[...depthChain, currentPath].join(" -> ")}`);
136
+ return { scriptModule: [] };
79
137
  }
138
+ moduleCompileStatus.set(currentPath, "pending");
80
139
  depthChain = [...depthChain, currentPath];
81
- compileModule(module, isComponent, scriptRes);
82
- if (module.usingComponents) {
83
- for (const componentInfo of Object.values(module.usingComponents)) {
84
- const componentModule = getComponent(componentInfo);
85
- if (!componentModule) {
86
- 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
+ }
164
+ }
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
+ }
87
171
  }
88
- buildCompileView(componentModule, true, scriptRes, depthChain);
172
+ compileModuleWithAllWxs(module, scriptRes, allScriptModules);
89
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: [] };
90
182
  }
91
- processedModules.add(currentPath);
92
183
  }
93
184
  function compileModule(module, isComponent, scriptRes) {
94
185
  const { tpl, instruction } = toCompileTemplate(isComponent, module.path, module.usingComponents, module.componentPlaceholder);
95
186
  if (!tpl) {
96
- return;
187
+ return null;
97
188
  }
189
+ let useCache = false;
190
+ let cachedCode = null;
98
191
  if (!scriptRes.has(module.path) && compileResCache.has(module.path)) {
99
- const res = compileResCache.get(module.path);
100
- scriptRes.set(module.path, res);
101
- for (const sm of instruction.scriptModule) {
102
- if (!scriptRes.has(sm.path)) {
103
- 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
+ }
104
200
  }
201
+ } else if (typeof cacheData2 === "string") {
202
+ cachedCode = cacheData2;
203
+ useCache = true;
105
204
  }
106
- 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
+ };
107
223
  }
108
224
  const processedTpl = tpl.replace(/\bthis\./g, "_ctx.");
109
225
  const tplCode = compileTemplate({
@@ -124,7 +240,7 @@ function compileModule(module, isComponent, scriptRes) {
124
240
  });
125
241
  let tplComponents = "{";
126
242
  for (const tm of instruction.templateModule) {
127
- tplComponents += `'${tm.path}':${compileTemplate({
243
+ let { code: code2 } = compileTemplate({
128
244
  source: tm.tpl,
129
245
  filename: tm.path,
130
246
  id: `data-v-${module.id}`,
@@ -137,36 +253,231 @@ function compileModule(module, isComponent, scriptRes) {
137
253
  mode: "function",
138
254
  inline: true
139
255
  }
140
- }).code},`;
256
+ });
257
+ const ast = babel.parseSync(code2);
258
+ insertWxsToRenderAst(ast, instruction.scriptModule, scriptRes);
259
+ code2 = babel.transformFromAstSync(ast, "", {
260
+ comments: false
261
+ }).code;
262
+ tplComponents += `'${tm.path}':${code2.replace(/;$/, "").replace(/^"use strict";\s*/, "")},`;
141
263
  }
142
264
  tplComponents += "}";
143
265
  const tplAst = babel.parseSync(tplCode.code);
144
- for (const sm of instruction.scriptModule) {
145
- if (!scriptRes.has(sm.path)) {
146
- scriptRes.set(sm.path, sm.code);
266
+ insertWxsToRenderAst(tplAst, instruction.scriptModule, scriptRes);
267
+ const { code: transCode } = babel.transformFromAstSync(tplAst, "", {
268
+ comments: false
269
+ });
270
+ const code = `Module({
271
+ path: '${module.path}',
272
+ id: '${module.id}',
273
+ render: ${transCode.replace(/;$/, "").replace(/^"use strict";\s*/, "")},
274
+ usingComponents: ${JSON.stringify(module.usingComponents)},
275
+ tplComponents: ${tplComponents},
276
+ });`;
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
+ }
147
285
  }
148
- const assignmentExpression = types.assignmentExpression(
149
- "=",
150
- // 创建赋值表达式
151
- types.memberExpression(
152
- types.identifier("_ctx"),
153
- // 对象标识符
154
- types.identifier(sm.path),
155
- // 属性标识符
156
- false
157
- // 是否是计算属性
158
- ),
159
- // 创建require调用表达式
160
- types.callExpression(
161
- types.identifier("require"),
162
- // 函数标识符
163
- [types.stringLiteral(sm.path)]
164
- // 参数列表,这里传入字符串字面量'foo'
165
- )
166
- );
167
- const expressionStatement = types.expressionStatement(assignmentExpression);
168
- tplAst.program.body[0].expression.body.body.splice(0, 0, expressionStatement);
286
+ instruction.scriptModule = mergedModules;
287
+ }
288
+ const cacheData = {
289
+ code,
290
+ instruction
291
+ };
292
+ compileResCache.set(module.path, cacheData);
293
+ scriptRes.set(module.path, code);
294
+ return instruction;
295
+ }
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;
169
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);
170
481
  const { code: transCode } = babel.transformFromAstSync(tplAst, "", {
171
482
  comments: false
172
483
  });
@@ -177,12 +488,19 @@ function compileModule(module, isComponent, scriptRes) {
177
488
  usingComponents: ${JSON.stringify(module.usingComponents)},
178
489
  tplComponents: ${tplComponents},
179
490
  });`;
180
- compileResCache.set(module.path, code);
491
+ const cacheData = {
492
+ code,
493
+ instruction: mergedInstruction
494
+ };
495
+ compileResCache.set(module.path, cacheData);
181
496
  scriptRes.set(module.path, code);
182
497
  }
183
- function toCompileTemplate(isComponent, path, components, componentPlaceholder) {
498
+ function processIncludedFileWxsDependencies(content, includePath, scriptModule, components) {
499
+ console.warn("[view]", `跳过被引入文件的组件 wxs 依赖处理: ${includePath}`);
500
+ }
501
+ function toCompileTemplate(isComponent, path2, components, componentPlaceholder) {
184
502
  const workPath = getWorkPath();
185
- const fullPath = getViewPath(workPath, path);
503
+ const fullPath = getViewPath(workPath, path2);
186
504
  if (!fullPath) {
187
505
  return { tpl: void 0 };
188
506
  }
@@ -191,10 +509,20 @@ function toCompileTemplate(isComponent, path, components, componentPlaceholder)
191
509
  content = "<block></block>";
192
510
  } else {
193
511
  if (isComponent) {
194
- content = `<wrapper>${content}</wrapper>`;
512
+ content = `<wrapper name="${path2}">${content}</wrapper>`;
513
+ } else {
514
+ const tempRoot = cheerio.load(content, {
515
+ xmlMode: true,
516
+ decodeEntities: false
517
+ });
518
+ const rootNodes = tempRoot.root().children().toArray().filter((node) => node.type !== "comment");
519
+ if (rootNodes.length > 1) {
520
+ content = `<view>${content}</view>`;
521
+ }
195
522
  }
196
523
  }
197
524
  const templateModule = [];
525
+ const scriptModule = [];
198
526
  const $ = cheerio.load(content, {
199
527
  xmlMode: true,
200
528
  decodeEntities: false
@@ -203,85 +531,74 @@ function toCompileTemplate(isComponent, path, components, componentPlaceholder)
203
531
  includeNodes.each((_, elem) => {
204
532
  const src = $(elem).attr("src");
205
533
  if (src) {
206
- 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();
207
540
  if (includeContent) {
208
541
  const $includeContent = cheerio.load(includeContent, {
209
542
  xmlMode: true,
210
543
  decodeEntities: false
211
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);
212
557
  $includeContent("template").remove();
213
558
  $includeContent("wxs").remove();
214
559
  $includeContent("dds").remove();
215
- $(elem).html($includeContent.html());
560
+ $(elem).replaceWith($includeContent.html());
561
+ } else {
562
+ $(elem).remove();
216
563
  }
564
+ } else {
565
+ $(elem).remove();
217
566
  }
218
567
  });
219
- transTagTemplate($, templateModule, path, components);
568
+ transTagTemplate($, templateModule, path2, components);
569
+ transTagWxs($, scriptModule, path2);
220
570
  const importNodes = $("import");
221
571
  importNodes.each((_, elem) => {
222
572
  const src = $(elem).attr("src");
223
573
  if (src) {
224
- const importContent = getContentByPath(getAbsolutePath(workPath, path, src)).trim();
574
+ const importFullPath = getAbsolutePath(workPath, path2, src);
575
+ let importPath = importFullPath.replace(workPath, "").replace(/\.(wxml|ddml)$/, "");
576
+ if (!importPath.startsWith("/")) {
577
+ importPath = "/" + importPath;
578
+ }
579
+ const importContent = getContentByPath(importFullPath).trim();
225
580
  if (importContent) {
581
+ const $$ = cheerio.load(importContent, {
582
+ xmlMode: true,
583
+ decodeEntities: false
584
+ });
226
585
  transTagTemplate(
227
- cheerio.load(importContent, {
228
- xmlMode: true,
229
- decodeEntities: false
230
- }),
586
+ $$,
231
587
  templateModule,
232
- path,
588
+ path2,
233
589
  components
234
590
  );
591
+ transTagWxs(
592
+ $$,
593
+ scriptModule,
594
+ importPath
595
+ );
596
+ processIncludedFileWxsDependencies(importContent, importPath);
235
597
  }
236
598
  }
237
599
  });
238
600
  importNodes.remove();
239
- const scriptModule = [];
240
- let wxsNodes = $("wxs");
241
- if (wxsNodes.length === 0) {
242
- wxsNodes = $("dds");
243
- }
244
- wxsNodes.each((_, elem) => {
245
- const smName = $(elem).attr("module");
246
- if (smName) {
247
- let wxsContent;
248
- if (compileResCache.has(smName)) {
249
- wxsContent = compileResCache.get(smName);
250
- } else {
251
- const src = $(elem).attr("src");
252
- if (src) {
253
- wxsContent = getContentByPath(getAbsolutePath(workPath, path, src)).trim();
254
- } else {
255
- wxsContent = $(elem).html();
256
- }
257
- const wxsAst = babel.parseSync(wxsContent);
258
- traverse(wxsAst, {
259
- CallExpression(path2) {
260
- if (path2.node.callee.name === "getRegExp" || path2.node.callee.name === "getDate") {
261
- const args = [];
262
- for (let i = 0; i < path2.node.arguments.length; i++) {
263
- args.push(path2.node.arguments[i]);
264
- }
265
- const newExpr = types.newExpression(types.identifier(path2.node.callee.name.substring(3)), args);
266
- path2.replaceWith(newExpr);
267
- }
268
- }
269
- });
270
- wxsContent = babel.transformFromAstSync(wxsAst, "", {
271
- comments: false
272
- }).code;
273
- compileResCache.set(smName, wxsContent);
274
- }
275
- if (wxsContent) {
276
- scriptModule.push({
277
- path: smName,
278
- code: wxsContent
279
- });
280
- }
281
- }
282
- });
283
- wxsNodes.remove();
284
- transAsses($, $("image"), path);
601
+ transAsses($, $("image"), path2);
285
602
  const res = [];
286
603
  transHtmlTag($.html(), res, components);
287
604
  return {
@@ -292,17 +609,16 @@ function toCompileTemplate(isComponent, path, components, componentPlaceholder)
292
609
  }
293
610
  };
294
611
  }
295
- function transTagTemplate($, templateModule, path, components, componentPlaceholder) {
612
+ function transTagTemplate($, templateModule, path2, components, componentPlaceholder) {
296
613
  const templateNodes = $("template[name]");
297
614
  templateNodes.each((_, elem) => {
298
615
  const name = $(elem).attr("name");
299
616
  const templateContent = $(elem);
300
- templateContent.find("template").remove();
301
617
  templateContent.find("import").remove();
302
618
  templateContent.find("include").remove();
303
619
  templateContent.find("wxs").remove();
304
620
  templateContent.find("dds").remove();
305
- transAsses($, templateContent.find("image"), path);
621
+ transAsses($, templateContent.find("image"), path2);
306
622
  const res = [];
307
623
  transHtmlTag(templateContent.html(), res, components);
308
624
  templateModule.push({
@@ -312,11 +628,11 @@ function transTagTemplate($, templateModule, path, components, componentPlacehol
312
628
  });
313
629
  templateNodes.remove();
314
630
  }
315
- function transAsses($, imageNodes, path) {
631
+ function transAsses($, imageNodes, path2) {
316
632
  imageNodes.each((_, elem) => {
317
633
  const imgSrc = $(elem).attr("src").trim();
318
634
  if (!imgSrc.startsWith("{{")) {
319
- $(elem).attr("src", collectAssets(getWorkPath(), path, imgSrc, getTargetPath(), getAppId()));
635
+ $(elem).attr("src", collectAssets(getWorkPath(), path2, imgSrc, getTargetPath(), getAppId()));
320
636
  }
321
637
  });
322
638
  }
@@ -358,20 +674,20 @@ function transTag(opts) {
358
674
  res = `dd-${tag}`;
359
675
  }
360
676
  let tagRes;
361
- const propsAry = getProps(attrs, tag);
677
+ const propsAry = isStart ? getProps(attrs, tag) : [];
362
678
  const multipleSlots = attrs?.slot;
363
679
  if (attrs?.slot) {
364
- const withVIf = [];
365
- const withoutVIf = [];
366
- for (let i = 0; i < propsAry.length; i++) {
367
- const prop = propsAry[i];
368
- if (prop.includes("v-if") || prop.includes("v-else-if") || prop.includes("v-else")) {
369
- withVIf.push(prop);
370
- } else {
371
- withoutVIf.push(prop);
372
- }
373
- }
374
680
  if (isStart) {
681
+ const withVIf = [];
682
+ const withoutVIf = [];
683
+ for (let i = 0; i < propsAry.length; i++) {
684
+ const prop = propsAry[i];
685
+ if (prop.includes("v-if") || prop.includes("v-else-if") || prop.includes("v-else")) {
686
+ withVIf.push(prop);
687
+ } else {
688
+ withoutVIf.push(prop);
689
+ }
690
+ }
375
691
  tagRes = `<template ${`${withVIf.join(" ")}`} #${multipleSlots}><${res}${` ${withoutVIf.join(" ")}`}>`;
376
692
  } else {
377
693
  tagRes = `</${res}></template>`;
@@ -411,14 +727,7 @@ function getProps(attrs, tag) {
411
727
  });
412
728
  } else if (name.endsWith(":for-item") || name.endsWith(":for-index")) ;
413
729
  else if (name.endsWith(":key")) {
414
- let tranValue;
415
- if (/\*this/.test(value)) {
416
- tranValue = JSON.stringify("item");
417
- } else if (/item/.test(value)) {
418
- tranValue = getForItemName(attrs);
419
- } else {
420
- tranValue = parseKeyExpression(value, getForItemName(attrs));
421
- }
730
+ const tranValue = parseKeyExpression(value, getForItemName(attrs), getForIndexName(attrs));
422
731
  attrsList.push({
423
732
  name: ":key",
424
733
  value: tranValue
@@ -535,19 +844,37 @@ function generateVModelTemplate(expression) {
535
844
  }
536
845
  return updateExpression;
537
846
  }
538
- function parseKeyExpression(exp, itemName = "item") {
847
+ function parseKeyExpression(exp, itemName = "item", indexName = "index") {
539
848
  exp = exp.trim();
849
+ if (/\*this/.test(exp) || /\*item/.test(exp)) {
850
+ return `${itemName}.toString()`;
851
+ }
540
852
  if (!exp.includes("{{")) {
541
- return exp.startsWith(itemName) ? `'${exp}'` : `'${itemName}.${exp}'`;
853
+ if (/^-?\d+(\.\d+)?$/.test(exp)) {
854
+ return exp;
855
+ }
856
+ if (exp === indexName) {
857
+ return indexName;
858
+ }
859
+ return exp.startsWith(itemName) ? `${exp}` : `${itemName}.${exp}`;
542
860
  }
543
861
  if (exp.startsWith("{{") && exp.endsWith("}}")) {
544
862
  const content = exp.slice(2, -2).trim();
545
- return content.startsWith(itemName) ? `'${content}'` : `'${itemName}.${content}'`;
863
+ if (content === "this") {
864
+ return `${itemName}.toString()`;
865
+ } else if (content === indexName) {
866
+ return indexName;
867
+ } else {
868
+ return content.startsWith(itemName) ? `${content}` : `${itemName}.${content}`;
869
+ }
546
870
  }
547
871
  const parts = exp.split(/(\{\{.*?\}\})/);
548
872
  const result = parts.map((part) => {
549
873
  if (part.startsWith("{{") && part.endsWith("}}")) {
550
874
  const content = part.slice(2, -2).trim();
875
+ if (content === indexName) {
876
+ return indexName;
877
+ }
551
878
  return content.startsWith(itemName) ? content : `${itemName}.${content}`;
552
879
  }
553
880
  return `'${part}'`;
@@ -653,14 +980,188 @@ function parseBraceExp(exp) {
653
980
  }
654
981
  return group.join("").replace(/^\+|\+$/g, "");
655
982
  }
656
- const viewCompiler = {
657
- splitWithBraces,
658
- parseClassRules,
983
+ function transTagWxs($, scriptModule, filePath) {
984
+ let wxsNodes = $("wxs");
985
+ if (wxsNodes.length === 0) {
986
+ wxsNodes = $("dds");
987
+ }
988
+ wxsNodes.each((_, elem) => {
989
+ const smName = $(elem).attr("module");
990
+ if (smName) {
991
+ let wxsContent;
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);
1013
+ } else {
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
+ }
1021
+ } else {
1022
+ wxsContent = $(elem).html();
1023
+ }
1024
+ if (!wxsContent) {
1025
+ return;
1026
+ }
1027
+ wxsContent = processWxsContent(wxsContent, wxsFilePath, scriptModule, workPath, filePath);
1028
+ compileResCache.set(cacheKey, wxsContent);
1029
+ }
1030
+ if (wxsContent) {
1031
+ registerWxsModule(uniqueModuleName);
1032
+ scriptModule.push({
1033
+ path: uniqueModuleName,
1034
+ code: wxsContent,
1035
+ originalName: smName
1036
+ // 保存原始模块名用于模板中的引用
1037
+ });
1038
+ }
1039
+ }
1040
+ });
1041
+ wxsNodes.remove();
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
+ }
1129
+ function insertWxsToRenderAst(ast, scriptModule, scriptRes) {
1130
+ for (const sm of scriptModule) {
1131
+ if (!scriptRes.has(sm.path)) {
1132
+ scriptRes.set(sm.path, sm.code);
1133
+ }
1134
+ const templatePropertyName = sm.originalName || sm.path;
1135
+ const requireModuleName = sm.path;
1136
+ const assignmentExpression = types.assignmentExpression(
1137
+ "=",
1138
+ // 创建赋值表达式
1139
+ types.memberExpression(
1140
+ types.identifier("_ctx"),
1141
+ // 对象标识符
1142
+ types.identifier(templatePropertyName),
1143
+ // 使用原始模块名作为属性名
1144
+ false
1145
+ // 是否是计算属性
1146
+ ),
1147
+ // 创建require调用表达式
1148
+ types.callExpression(
1149
+ types.identifier("require"),
1150
+ // 函数标识符
1151
+ [types.stringLiteral(requireModuleName)]
1152
+ // 使用唯一模块名作为 require 参数
1153
+ )
1154
+ );
1155
+ const expressionStatement = types.expressionStatement(assignmentExpression);
1156
+ ast.program.body[0].expression.body.body.unshift(expressionStatement);
1157
+ }
1158
+ }
1159
+ export {
1160
+ compileML,
1161
+ generateVModelTemplate,
659
1162
  parseBraceExp,
1163
+ parseClassRules,
660
1164
  parseKeyExpression,
661
- compileML,
662
- generateVModelTemplate
663
- };
664
- export {
665
- viewCompiler as default
1165
+ processWxsContent,
1166
+ splitWithBraces
666
1167
  };