@dimina/compiler 1.0.17 → 1.1.0

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,5 +1,5 @@
1
- import { S as transformRpx, a as getContentByPath, d as getTemplateExts, f as getViewScriptExts, h as resetStoreInfo, i as getComponent, m as getWorkPath, n as getAppId, p as getViewScriptTags, u as getTargetPath, v as collectAssets, x as tagWhiteList, y as getAbsolutePath } from "../env-iShlMOS1.js";
2
- import { t as checkTemplateCompatibility } from "../compatibility-DbP7rQJN.js";
1
+ import { C as tagWhiteList, T as toMiniProgramModuleId, a as getComponent, b as getAbsolutePath, d as getTargetPath, f as getTemplateExts, g as resetStoreInfo, h as getWorkPath, m as getViewScriptTags, n as getAppId, o as getContentByPath, p as getViewScriptExts, w as transformRpx, y as collectAssets } from "../env-OH3--qg8.js";
2
+ import { r as takeCompatibilityWarnings, t as checkTemplateCompatibility } from "../compatibility-DdxfVhcK.js";
3
3
  import path from "node:path";
4
4
  import { isMainThread, parentPort } from "node:worker_threads";
5
5
  import fs from "node:fs";
@@ -253,7 +253,10 @@ if (!isMainThread) parentPort.on("message", async ({ pages, storeInfo }) => {
253
253
  compileResCache.clear();
254
254
  wxsModuleRegistry.clear();
255
255
  wxsFilePathMap.clear();
256
- parentPort.postMessage({ success: true });
256
+ parentPort.postMessage({
257
+ success: true,
258
+ compatibilityWarnings: takeCompatibilityWarnings()
259
+ });
257
260
  } catch (error) {
258
261
  compileResCache.clear();
259
262
  wxsModuleRegistry.clear();
@@ -275,17 +278,26 @@ async function compileML(pages, root, progress) {
275
278
  initWxsFilePathMap(getWorkPath());
276
279
  for (const page of pages) {
277
280
  const scriptRes = /* @__PURE__ */ new Map();
278
- buildCompileView(page, false, scriptRes, [], /* @__PURE__ */ new Set());
281
+ buildCompileView(page, false, scriptRes, /* @__PURE__ */ new Set(), /* @__PURE__ */ new Set());
279
282
  let mergeRender = "";
280
283
  for (const [key, value] of scriptRes.entries()) {
281
- const { code: minifiedCode } = await transform(`modDefine('${key}', function(require, module, exports) {
284
+ const amdFormat = `modDefine('${key}', function(require, module, exports) {
282
285
  ${value}
283
- });`, {
284
- minify: true,
285
- target: ["es2020"],
286
- platform: "browser"
287
- });
288
- mergeRender += minifiedCode;
286
+ });`;
287
+ try {
288
+ const { code: minifiedCode } = await transform(amdFormat, {
289
+ minify: true,
290
+ target: ["es2020"],
291
+ platform: "browser"
292
+ });
293
+ mergeRender += minifiedCode;
294
+ } catch (error) {
295
+ const location = error.errors?.[0]?.location;
296
+ const sourceLines = amdFormat.split("\n");
297
+ const sourceHint = location?.line ? sourceLines.slice(Math.max(0, location.line - 3), location.line + 2).map((line, index) => `${Math.max(1, location.line - 2) + index}: ${line.trim()}`).join("\n") : "";
298
+ error.message = `视图模块 ${key} 转换失败: ${error.message}${sourceHint ? `\n${sourceHint}` : ""}`;
299
+ throw error;
300
+ }
289
301
  }
290
302
  scriptRes.clear();
291
303
  const filename = `${page.path.replace(/\//g, "_")}`;
@@ -336,6 +348,17 @@ function scanWxsFiles(dir, workPath) {
336
348
  function registerWxsModule(modulePath) {
337
349
  wxsModuleRegistry.add(modulePath);
338
350
  }
351
+ function getTemplateCompilerOptions(scopeId) {
352
+ return {
353
+ prefixIdentifiers: true,
354
+ hoistStatic: false,
355
+ cacheHandlers: true,
356
+ scopeId,
357
+ mode: "function",
358
+ inline: true,
359
+ isCustomElement: (tag) => !tag.startsWith("dd-")
360
+ };
361
+ }
339
362
  /**
340
363
  * 检查是否为已注册的 wxs 模块
341
364
  * @param {string} modulePath - 模块路径
@@ -344,17 +367,10 @@ function registerWxsModule(modulePath) {
344
367
  function isRegisteredWxsModule(modulePath) {
345
368
  return wxsModuleRegistry.has(modulePath);
346
369
  }
347
- function buildCompileView(module, isComponent = false, scriptRes, depthChain = [], inheritedTemplatePaths = /* @__PURE__ */ new Set()) {
370
+ function buildCompileView(module, isComponent = false, scriptRes, activePaths = /* @__PURE__ */ new Set(), inheritedTemplatePaths = /* @__PURE__ */ new Set()) {
348
371
  const currentPath = module.path;
349
- if (depthChain.includes(currentPath)) {
350
- console.warn("[view]", `检测到循环依赖: ${[...depthChain, currentPath].join(" -> ")}`);
351
- return;
352
- }
353
- if (depthChain.length > 20) {
354
- console.warn("[view]", `检测到深度依赖: ${[...depthChain, currentPath].join(" -> ")}`);
355
- return;
356
- }
357
- depthChain = [...depthChain, currentPath];
372
+ if (activePaths.has(currentPath)) return;
373
+ activePaths.add(currentPath);
358
374
  const allScriptModules = [];
359
375
  const currentInstruction = compileModule(module, isComponent, scriptRes, { skipTemplatePaths: isComponent ? inheritedTemplatePaths : /* @__PURE__ */ new Set() });
360
376
  if (currentInstruction && currentInstruction.scriptModule) allScriptModules.push(...currentInstruction.scriptModule);
@@ -363,11 +379,8 @@ function buildCompileView(module, isComponent = false, scriptRes, depthChain = [
363
379
  if (module.usingComponents) for (const componentInfo of Object.values(module.usingComponents)) {
364
380
  const componentModule = getComponent(componentInfo);
365
381
  if (!componentModule) continue;
366
- if (componentModule.path === module.path) {
367
- console.warn("[view]", `检测到循环依赖,跳过处理: ${module.path}`);
368
- continue;
369
- }
370
- const componentInstruction = buildCompileView(componentModule, true, scriptRes, depthChain, childInheritedTemplatePaths);
382
+ if (componentModule.path === module.path) continue;
383
+ const componentInstruction = buildCompileView(componentModule, true, scriptRes, activePaths, childInheritedTemplatePaths);
371
384
  if (componentInstruction && componentInstruction.scriptModule) {
372
385
  for (const sm of componentInstruction.scriptModule) if (!allScriptModules.find((existing) => existing.path === sm.path)) allScriptModules.push(sm);
373
386
  }
@@ -376,6 +389,7 @@ function buildCompileView(module, isComponent = false, scriptRes, depthChain = [
376
389
  for (const sm of allScriptModules) if (!scriptRes.has(sm.path)) scriptRes.set(sm.path, sm.code);
377
390
  compileModuleWithAllWxs(module, scriptRes, allScriptModules);
378
391
  }
392
+ activePaths.delete(currentPath);
379
393
  return {
380
394
  scriptModule: allScriptModules,
381
395
  templateModule: currentInstruction?.templateModule || []
@@ -428,14 +442,7 @@ function compileModule(module, isComponent, scriptRes, options = {}) {
428
442
  filename: module.path,
429
443
  id: `data-v-${module.id}`,
430
444
  scoped: true,
431
- compilerOptions: {
432
- prefixIdentifiers: true,
433
- hoistStatic: false,
434
- cacheHandlers: true,
435
- scopeId: `data-v-${module.id}`,
436
- mode: "function",
437
- inline: true
438
- }
445
+ compilerOptions: getTemplateCompilerOptions(`data-v-${module.id}`)
439
446
  });
440
447
  let tplComponents = "{";
441
448
  for (const tm of compileInstruction.templateModule) {
@@ -444,14 +451,7 @@ function compileModule(module, isComponent, scriptRes, options = {}) {
444
451
  filename: tm.path,
445
452
  id: `data-v-${module.id}`,
446
453
  scoped: true,
447
- compilerOptions: {
448
- prefixIdentifiers: true,
449
- hoistStatic: false,
450
- cacheHandlers: true,
451
- scopeId: `data-v-${module.id}`,
452
- mode: "function",
453
- inline: true
454
- }
454
+ compilerOptions: getTemplateCompilerOptions(`data-v-${module.id}`)
455
455
  });
456
456
  code = insertWxsToRenderCode(code, compileInstruction.scriptModule, scriptRes, tm.path);
457
457
  tplComponents += `'${tm.path}':${code},`;
@@ -461,8 +461,12 @@ function compileModule(module, isComponent, scriptRes, options = {}) {
461
461
  const code = `Module({
462
462
  path: '${module.path}',
463
463
  id: '${module.id}',
464
+ appStyleScopeId: ${JSON.stringify(module.appStyleScopeId || null)},
465
+ sharedStyleScopeIds: ${JSON.stringify(module.sharedStyleScopeIds || [])},
466
+ styleIsolation: ${JSON.stringify(module.styleIsolation || "isolated")},
464
467
  render: ${transCode},
465
468
  usingComponents: ${JSON.stringify(module.usingComponents)},
469
+ customTabBar: ${JSON.stringify(module.customTabBar || null)},
466
470
  tplComponents: ${tplComponents},
467
471
  });`;
468
472
  const allWxsModules = collectAllWxsModules(scriptRes, /* @__PURE__ */ new Set(), compileInstruction.scriptModule || []);
@@ -613,14 +617,7 @@ function compileModuleWithAllWxs(module, scriptRes, allScriptModules) {
613
617
  filename: module.path,
614
618
  id: `data-v-${module.id}`,
615
619
  scoped: true,
616
- compilerOptions: {
617
- prefixIdentifiers: true,
618
- hoistStatic: false,
619
- cacheHandlers: true,
620
- scopeId: `data-v-${module.id}`,
621
- mode: "function",
622
- inline: true
623
- }
620
+ compilerOptions: getTemplateCompilerOptions(`data-v-${module.id}`)
624
621
  });
625
622
  let tplComponents = "{";
626
623
  for (const tm of mergedInstruction.templateModule) {
@@ -629,14 +626,7 @@ function compileModuleWithAllWxs(module, scriptRes, allScriptModules) {
629
626
  filename: tm.path,
630
627
  id: `data-v-${module.id}`,
631
628
  scoped: true,
632
- compilerOptions: {
633
- prefixIdentifiers: true,
634
- hoistStatic: false,
635
- cacheHandlers: true,
636
- scopeId: `data-v-${module.id}`,
637
- mode: "function",
638
- inline: true
639
- }
629
+ compilerOptions: getTemplateCompilerOptions(`data-v-${module.id}`)
640
630
  });
641
631
  code = insertWxsToRenderCode(code, allScriptModules, scriptRes, tm.path);
642
632
  tplComponents += `'${tm.path}':${code},`;
@@ -646,8 +636,12 @@ function compileModuleWithAllWxs(module, scriptRes, allScriptModules) {
646
636
  const code = `Module({
647
637
  path: '${module.path}',
648
638
  id: '${module.id}',
639
+ appStyleScopeId: ${JSON.stringify(module.appStyleScopeId || null)},
640
+ sharedStyleScopeIds: ${JSON.stringify(module.sharedStyleScopeIds || [])},
641
+ styleIsolation: ${JSON.stringify(module.styleIsolation || "isolated")},
649
642
  render: ${transCode},
650
643
  usingComponents: ${JSON.stringify(module.usingComponents)},
644
+ customTabBar: ${JSON.stringify(module.customTabBar || null)},
651
645
  tplComponents: ${tplComponents},
652
646
  });`;
653
647
  const cacheData = {
@@ -729,12 +723,13 @@ function toCompileTemplate(isComponent, path, components, componentPlaceholder,
729
723
  const workPath = getWorkPath();
730
724
  const fullPath = getViewPath(workPath, path);
731
725
  if (!fullPath) return { tpl: void 0 };
726
+ const sourcePath = toMiniProgramModuleId(fullPath, workPath).replace(buildExtStripRegex(getTemplateExts()), "");
732
727
  const diagnosticSource = fullPath.startsWith(workPath) ? fullPath.slice(workPath.length) : path;
733
728
  let content = getContentByPath(fullPath).trim();
734
729
  if (!content) content = "<block></block>";
735
730
  else {
736
731
  checkTemplateCompatibility(content, diagnosticSource, components);
737
- if (isComponent) content = `<wrapper name="${path}">${content}</wrapper>`;
732
+ if (isComponent) content = `<component-host name="${path}">${content}</component-host>`;
738
733
  else if (cheerio.load(content, {
739
734
  xmlMode: true,
740
735
  decodeEntities: false
@@ -752,7 +747,7 @@ function toCompileTemplate(isComponent, path, components, componentPlaceholder,
752
747
  $("include").each((_, elem) => {
753
748
  const src = $(elem).attr("src");
754
749
  if (src) {
755
- const includeFullPath = getAbsolutePath(workPath, path, src);
750
+ const includeFullPath = resolveTemplateDependencyPath(workPath, sourcePath, src);
756
751
  let includePath = includeFullPath.replace(workPath, "").replace(buildExtStripRegex(getTemplateExts()), "");
757
752
  const includeDiagnosticSource = includeFullPath.startsWith(workPath) ? includeFullPath.slice(workPath.length) : includePath;
758
753
  if (!includePath.startsWith("/")) includePath = "/" + includePath;
@@ -773,13 +768,13 @@ function toCompileTemplate(isComponent, path, components, componentPlaceholder,
773
768
  } else $(elem).remove();
774
769
  } else $(elem).remove();
775
770
  });
776
- transTagTemplate($, templateModule, path, components, componentPlaceholder);
777
- transTagWxs($, scriptModule, path);
771
+ transTagTemplate($, templateModule, sourcePath, components, componentPlaceholder);
772
+ transTagWxs($, scriptModule, sourcePath);
778
773
  const importNodes = $("import");
779
774
  importNodes.each((_, elem) => {
780
775
  const src = $(elem).attr("src");
781
776
  if (src) {
782
- const importFullPath = getAbsolutePath(workPath, path, src);
777
+ const importFullPath = resolveTemplateDependencyPath(workPath, sourcePath, src);
783
778
  let importPath = importFullPath.replace(workPath, "").replace(buildExtStripRegex(getTemplateExts()), "");
784
779
  const importDiagnosticSource = importFullPath.startsWith(workPath) ? importFullPath.slice(workPath.length) : importPath;
785
780
  if (!importPath.startsWith("/")) importPath = "/" + importPath;
@@ -790,14 +785,14 @@ function toCompileTemplate(isComponent, path, components, componentPlaceholder,
790
785
  xmlMode: true,
791
786
  decodeEntities: false
792
787
  });
793
- transTagTemplate($$, templateModule, path, components, componentPlaceholder);
788
+ transTagTemplate($$, templateModule, importPath, components, componentPlaceholder);
794
789
  transTagWxs($$, scriptModule, importPath);
795
790
  processIncludedFileWxsDependencies(importContent, importPath, scriptModule, components, processedPaths);
796
791
  }
797
792
  }
798
793
  });
799
794
  importNodes.remove();
800
- transAsses($, $("image"), path);
795
+ transAsses($, $("image"), sourcePath);
801
796
  const res = [];
802
797
  transHtmlTag($.html(), res, components, componentPlaceholder);
803
798
  return {
@@ -832,6 +827,72 @@ function transAsses($, imageNodes, path) {
832
827
  if (!imgSrc.startsWith("{{")) $(elem).attr("src", collectAssets(getWorkPath(), path, imgSrc, getTargetPath(), getAppId()));
833
828
  });
834
829
  }
830
+ var DIMINA_SLOT_GROUP_TAG = "dimina-slot-group";
831
+ var DIMINA_FOR_SCOPE_TAG = "dimina-for-scope";
832
+ function getDirectiveAttributeNames(attrs, suffixes) {
833
+ return Object.keys(attrs || {}).filter((name) => suffixes.some((suffix) => name.endsWith(suffix)));
834
+ }
835
+ function hasForAndIf(attrs) {
836
+ return getDirectiveAttributeNames(attrs, [":for", ":for-items"]).length > 0 && getDirectiveAttributeNames(attrs, [":if"]).length > 0;
837
+ }
838
+ function groupDuplicateNamedSlots($, components) {
839
+ const slotHosts = $("*").toArray().filter((element) => {
840
+ const tag = element.tagName;
841
+ return tag === "component" || Boolean(components?.[tag]);
842
+ });
843
+ for (const host of slotHosts) {
844
+ const groups = /* @__PURE__ */ new Map();
845
+ for (const child of $(host).children().toArray()) {
846
+ const slotName = child.attribs?.slot;
847
+ if (!slotName) continue;
848
+ const group = groups.get(slotName) || [];
849
+ group.push(child);
850
+ groups.set(slotName, group);
851
+ }
852
+ for (const [slotName, nodes] of groups) {
853
+ if (nodes.length === 1 && !hasForAndIf(nodes[0].attribs)) continue;
854
+ const wrapper = $(`<${DIMINA_SLOT_GROUP_TAG}></${DIMINA_SLOT_GROUP_TAG}>`);
855
+ wrapper.attr("name", slotName);
856
+ $(nodes[0]).before(wrapper);
857
+ for (const node of nodes) {
858
+ $(node).removeAttr("slot");
859
+ wrapper.append(node);
860
+ }
861
+ }
862
+ }
863
+ }
864
+ function wrapForIfScopes($) {
865
+ const nodes = $("*").toArray();
866
+ for (const node of nodes) {
867
+ if (node.tagName === DIMINA_FOR_SCOPE_TAG || !hasForAndIf(node.attribs)) continue;
868
+ const attrsToMove = getDirectiveAttributeNames(node.attribs, [
869
+ ":for",
870
+ ":for-items",
871
+ ":for-item",
872
+ ":for-index",
873
+ ":key"
874
+ ]);
875
+ const wrapper = $(`<${DIMINA_FOR_SCOPE_TAG}></${DIMINA_FOR_SCOPE_TAG}>`);
876
+ for (const name of attrsToMove) {
877
+ wrapper.attr(name, node.attribs[name]);
878
+ $(node).removeAttr(name);
879
+ }
880
+ $(node).before(wrapper);
881
+ wrapper.append(node);
882
+ }
883
+ }
884
+ function normalizeTemplateSyntax(html, components) {
885
+ const $ = cheerio.load(html, {
886
+ xmlMode: true,
887
+ decodeEntities: false,
888
+ _useHtmlParser2: true,
889
+ lowerCaseTags: false,
890
+ lowerCaseAttributeNames: false
891
+ });
892
+ groupDuplicateNamedSlots($, components);
893
+ wrapForIfScopes($);
894
+ return $.html();
895
+ }
835
896
  function transHtmlTag(html, res, components, componentPlaceholder) {
836
897
  const attrsList = [];
837
898
  const parser = new htmlparser2.Parser({
@@ -859,7 +920,7 @@ function transHtmlTag(html, res, components, componentPlaceholder) {
859
920
  console.error(error);
860
921
  }
861
922
  }, { xmlMode: true });
862
- parser.write(html);
923
+ parser.write(normalizeTemplateSyntax(html, components));
863
924
  parser.end();
864
925
  }
865
926
  /**
@@ -869,11 +930,15 @@ function transHtmlTag(html, res, components, componentPlaceholder) {
869
930
  function transTag(opts) {
870
931
  const { isStart, tag, attrs, components } = opts;
871
932
  let res;
872
- if (tag === "slot") res = tag;
933
+ if (tag === DIMINA_SLOT_GROUP_TAG) {
934
+ if (isStart) return `<template ${generateSlotDirective(attrs.name)}>`;
935
+ return "</template>";
936
+ } else if (tag === DIMINA_FOR_SCOPE_TAG) res = "template";
937
+ else if (tag === "slot") res = tag;
873
938
  else if (components && components[tag]) res = `dd-${tag}`;
874
939
  else if (tag === "component" || tag === "canvas") res = tag;
875
- else if (!tagWhiteList.includes(tag)) res = "dd-text";
876
- else res = `dd-${tag}`;
940
+ else if (tagWhiteList.includes(tag)) res = `dd-${tag}`;
941
+ else res = tag;
877
942
  let tagRes;
878
943
  const propsAry = isStart ? getProps(attrs, tag, components) : [];
879
944
  const multipleSlots = attrs?.slot;
@@ -918,7 +983,17 @@ function generateSlotDirective(slotValue) {
918
983
  */
919
984
  function getProps(attrs, tag, components) {
920
985
  const attrsList = [];
986
+ const isCustomComponent = Boolean(components && components[tag]);
921
987
  const propBindings = {};
988
+ const hasEventBindings = Object.keys(attrs).some((name) => /^(?:capture-)?(?:bind|catch)(?::)?.+/.test(name));
989
+ if (tag === "page-meta") attrsList.push({
990
+ name: "dimina-rpx-unit",
991
+ value: "vw"
992
+ });
993
+ if (hasEventBindings) attrsList.push({
994
+ name: "v-c-event-node",
995
+ value: components && components[tag] ? "'component'" : "'node'"
996
+ });
922
997
  Object.entries(attrs).forEach(([name, value]) => {
923
998
  if (name.endsWith(":if")) attrsList.push({
924
999
  name: "v-if",
@@ -942,11 +1017,20 @@ function getProps(attrs, tag, components) {
942
1017
  name: ":key",
943
1018
  value: tranValue
944
1019
  });
945
- } else if (name === "style") attrsList.push({
946
- name: "v-c-style",
947
- value: transformRpx(parseSafeBraceExp(value))
948
- });
949
- else if (name === "class") {
1020
+ } else if (name === "style") {
1021
+ const parsedStyle = parseSafeBraceExp(value);
1022
+ attrsList.push({
1023
+ name: "v-c-style",
1024
+ value: transformRpx(parsedStyle)
1025
+ });
1026
+ if (isCustomComponent) {
1027
+ attrsList.push({
1028
+ name: ":dimina-wxml-style",
1029
+ value: parsedStyle
1030
+ });
1031
+ if (isWrappedByBraces(value) && parsedStyle) propBindings.style = parsedStyle;
1032
+ }
1033
+ } else if (name === "class") {
950
1034
  if (isWrappedByBraces(value)) attrsList.push({
951
1035
  name: ":class",
952
1036
  value: parseClassRules(value)
@@ -998,7 +1082,7 @@ function getProps(attrs, tag, components) {
998
1082
  });
999
1083
  else if (isWrappedByBraces(value)) {
1000
1084
  const pVal = tag === "template" && name === "data" ? parseTemplateDataExp(value) : parseSafeBraceExp(value);
1001
- if (components && components[tag]) {
1085
+ if (isCustomComponent) {
1002
1086
  if (pVal && typeof pVal === "string") propBindings[name] = pVal;
1003
1087
  }
1004
1088
  attrsList.push({
@@ -1017,7 +1101,7 @@ function getProps(attrs, tag, components) {
1017
1101
  else if (/\$\{[^}]*\}/.test(value)) propsRes.push(`:${name}="\`${value}\`"`);
1018
1102
  else propsRes.push(`${name}="${escapeQuotes(value)}"`);
1019
1103
  });
1020
- if (components && components[tag] && Object.keys(propBindings).length > 0) try {
1104
+ if (isCustomComponent && Object.keys(propBindings).length > 0) try {
1021
1105
  const validBindings = {};
1022
1106
  for (const [key, value] of Object.entries(propBindings)) if (value !== void 0 && value !== null && typeof value === "string") validBindings[key] = value;
1023
1107
  if (Object.keys(validBindings).length > 0) {
@@ -1089,6 +1173,20 @@ function getViewPath(workPath, src) {
1089
1173
  }
1090
1174
  }
1091
1175
  /**
1176
+ * 解析 import/include 的模板文件路径。
1177
+ * 微信允许省略 .wxml;显式扩展名保持原样,无扩展名时按当前模板类型优先级补全。
1178
+ */
1179
+ function resolveTemplateDependencyPath(workPath, ownerPath, src) {
1180
+ const resolvedPath = getAbsolutePath(workPath, ownerPath, src);
1181
+ if (fs.existsSync(resolvedPath) && fs.statSync(resolvedPath).isFile()) return resolvedPath;
1182
+ if (path.extname(resolvedPath)) return resolvedPath;
1183
+ for (const ext of getTemplateExts()) {
1184
+ const candidate = `${resolvedPath}${ext}`;
1185
+ if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) return candidate;
1186
+ }
1187
+ return resolvedPath;
1188
+ }
1189
+ /**
1092
1190
  * 将字符串内部的双引号进行替换
1093
1191
  * @param {*} input
1094
1192
  */
@@ -1129,7 +1227,7 @@ function splitWithBraces(str) {
1129
1227
  function parseClassRules(cssRule) {
1130
1228
  let list = splitWithBraces(cssRule);
1131
1229
  list = list.map((item) => {
1132
- return parseBraceExp(item);
1230
+ return parseSafeBraceExp(item);
1133
1231
  });
1134
1232
  if (list.length === 1) return list.pop();
1135
1233
  return `[${list.join(",")}]`;
@@ -1157,11 +1255,16 @@ function getForIndexName(attrs) {
1157
1255
  * @param {*} attrs
1158
1256
  */
1159
1257
  function parseForExp(exp, attrs) {
1160
- return `(${getForItemName(attrs)}, ${getForIndexName(attrs)}) in ${parseBraceExp(exp)}`;
1258
+ return `(${getForItemName(attrs)}, ${getForIndexName(attrs)}) in ${parseSafeBraceExp(exp)}`;
1161
1259
  }
1162
1260
  var braceRegex = /(\{\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\}\})|([^{}]+)/g;
1163
1261
  var noBraceRegex = /\{\{((?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*)\}\}/;
1164
1262
  var ternaryRegex = /[^?]+\?.+:.+/;
1263
+ var RESERVED_TEMPLATE_CONTEXT_ALIASES = /* @__PURE__ */ new Map([["class", "__dimina_reserved_class"]]);
1264
+ var RESERVED_TEMPLATE_CONTEXT_NAMES = new Map([...RESERVED_TEMPLATE_CONTEXT_ALIASES].map(([name, alias]) => [alias, name]));
1265
+ function encodeReservedTemplateContextIdentifier(expression) {
1266
+ return RESERVED_TEMPLATE_CONTEXT_ALIASES.get(expression) || expression;
1267
+ }
1165
1268
  /**
1166
1269
  * 解析 {{}} 表达式的值
1167
1270
  * @param {*} exp
@@ -1173,7 +1276,7 @@ function parseBraceExp(exp) {
1173
1276
  if (result[1]) {
1174
1277
  const matchResult = result[1].match(noBraceRegex);
1175
1278
  if (matchResult) {
1176
- const statement = matchResult[1].trim();
1279
+ const statement = encodeReservedTemplateContextIdentifier(matchResult[1].trim());
1177
1280
  if (ternaryRegex.test(statement)) group.push(`(${statement})`);
1178
1281
  else group.push(statement);
1179
1282
  }
@@ -1189,8 +1292,8 @@ function parseBraceExp(exp) {
1189
1292
  */
1190
1293
  function parseTemplateDataExp(exp) {
1191
1294
  const matchResult = exp.trim().match(/^\{\{([\s\S]*)\}\}$/);
1192
- if (matchResult) return `{${matchResult[1].trim()}}`;
1193
- return `{${parseBraceExp(exp)}}`;
1295
+ if (matchResult) return addOptionalChaining(`{${matchResult[1].trim()}}`);
1296
+ return `{${parseSafeBraceExp(exp)}}`;
1194
1297
  }
1195
1298
  function transTagWxs($, scriptModule, filePath) {
1196
1299
  const wxsNodes = $(getViewScriptTags().join(","));
@@ -1330,8 +1433,7 @@ function insertWxsToRenderCode(code, scriptModule, scriptRes, filename = "render
1330
1433
  });
1331
1434
  declarations.push(`const ${localIdentifier} = require(${JSON.stringify(requireModuleName)});`);
1332
1435
  }
1333
- if (wxsBindings.length === 0) return getProgramCode(code, ast);
1334
- if (renderBody?.type === "BlockStatement") codeReplacements.push({
1436
+ if (wxsBindings.length > 0 && renderBody?.type === "BlockStatement") codeReplacements.push({
1335
1437
  type: "insert",
1336
1438
  start: renderBody.start + 1,
1337
1439
  end: renderBody.start + 1,
@@ -1339,6 +1441,15 @@ function insertWxsToRenderCode(code, scriptModule, scriptRes, filename = "render
1339
1441
  });
1340
1442
  walk(ast, { enter(node) {
1341
1443
  if (node.type === "MemberExpression" && node.object?.type === "Identifier" && node.object.name === "_ctx" && !node.computed && node.property?.type === "Identifier") {
1444
+ const reservedName = RESERVED_TEMPLATE_CONTEXT_NAMES.get(node.property.name);
1445
+ if (reservedName) {
1446
+ codeReplacements.push({
1447
+ start: node.property.start,
1448
+ end: node.property.end,
1449
+ value: reservedName
1450
+ });
1451
+ return;
1452
+ }
1342
1453
  const replacement = wxsBindings.find((item) => item.templatePropertyName === node.property.name);
1343
1454
  if (replacement) codeReplacements.push({
1344
1455
  start: node.start,
@@ -1347,8 +1458,9 @@ function insertWxsToRenderCode(code, scriptModule, scriptRes, filename = "render
1347
1458
  });
1348
1459
  }
1349
1460
  } });
1461
+ if (codeReplacements.length === 0) return getProgramCode(code, ast);
1350
1462
  const transformed = applyCodeReplacements(code, codeReplacements);
1351
1463
  return getProgramCode(transformed, parseJs(transformed, filename));
1352
1464
  }
1353
1465
  //#endregion
1354
- export { compileML, generateSlotDirective, generateVModelTemplate, initWxsFilePathMap, loadWxsModule, parseBraceExp, parseClassRules, parseKeyExpression, parseTemplateDataExp, processIncludeConditionalAttrs, processWxsContent, splitWithBraces };
1466
+ export { compileML, generateSlotDirective, generateVModelTemplate, initWxsFilePathMap, loadWxsModule, normalizeTemplateSyntax, parseBraceExp, parseClassRules, parseKeyExpression, parseTemplateDataExp, processIncludeConditionalAttrs, processWxsContent, splitWithBraces };