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