@wevu/compiler 0.1.1 → 6.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -169,10 +169,10 @@ declare function getSfcCheckMtime(config?: {
169
169
  */
170
170
  interface MiniProgramPlatform {
171
171
  name: string;
172
- wrapIf: (exp: string, content: string) => string;
173
- wrapElseIf: (exp: string, content: string) => string;
172
+ wrapIf: (exp: string, content: string, renderMustache: (exp: string) => string) => string;
173
+ wrapElseIf: (exp: string, content: string, renderMustache: (exp: string) => string) => string;
174
174
  wrapElse: (content: string) => string;
175
- forAttrs: (listExp: string, item?: string, index?: string) => string[];
175
+ forAttrs: (listExp: string, renderMustache: (exp: string) => string, item?: string, index?: string) => string[];
176
176
  keyThisValue: string;
177
177
  keyAttr: (value: string) => string;
178
178
  mapEventName: (eventName: string) => string;
@@ -233,6 +233,8 @@ interface TemplateCompileOptions {
233
233
  scopedSlotsRequireProps?: boolean;
234
234
  slotMultipleInstance?: boolean;
235
235
  classStyleRuntime?: ClassStyleRuntime | 'auto';
236
+ objectLiteralBindMode?: ObjectLiteralBindMode;
237
+ mustacheInterpolation?: MustacheInterpolationMode;
236
238
  wxsExtension?: string;
237
239
  classStyleWxsSrc?: string;
238
240
  }
@@ -244,12 +246,20 @@ type ScopedSlotsCompilerMode = 'auto' | 'augmented' | 'off';
244
246
  * class/style 运行时模式。
245
247
  */
246
248
  type ClassStyleRuntime = 'wxs' | 'js';
249
+ /**
250
+ * 对象字面量 v-bind 产物模式。
251
+ */
252
+ type ObjectLiteralBindMode = 'runtime' | 'inline';
253
+ /**
254
+ * Mustache 输出风格。
255
+ */
256
+ type MustacheInterpolationMode = 'compact' | 'spaced';
247
257
  /**
248
258
  * class/style 绑定信息。
249
259
  */
250
260
  interface ClassStyleBinding {
251
261
  name: string;
252
- type: 'class' | 'style';
262
+ type: 'class' | 'style' | 'bind';
253
263
  exp: string;
254
264
  expAst?: Expression;
255
265
  forStack: ForParseResult[];
package/dist/index.mjs CHANGED
@@ -415,11 +415,11 @@ function toAlipayDirectiveEvent(prefix, eventName) {
415
415
  */
416
416
  const alipayPlatform = {
417
417
  name: "alipay",
418
- wrapIf: (exp, content) => `<block a:if="{{${exp}}}">${content}</block>`,
419
- wrapElseIf: (exp, content) => `<block a:elif="{{${exp}}}">${content}</block>`,
418
+ wrapIf: (exp, content, renderMustache) => `<block a:if="${renderMustache(exp)}">${content}</block>`,
419
+ wrapElseIf: (exp, content, renderMustache) => `<block a:elif="${renderMustache(exp)}">${content}</block>`,
420
420
  wrapElse: (content) => `<block a:else>${content}</block>`,
421
- forAttrs: (listExp, item, index) => {
422
- const attrs = [`a:for="{{${listExp}}}"`];
421
+ forAttrs: (listExp, renderMustache, item, index) => {
422
+ const attrs = [`a:for="${renderMustache(listExp)}"`];
423
423
  if (item) attrs.push(`a:for-item="${item}"`);
424
424
  if (index) attrs.push(`a:for-index="${index}"`);
425
425
  return attrs;
@@ -474,11 +474,11 @@ function parseEventBinding$2(eventName) {
474
474
  */
475
475
  const swanPlatform = {
476
476
  name: "swan",
477
- wrapIf: (exp, content) => `<block s-if="{{${exp}}}">${content}</block>`,
478
- wrapElseIf: (exp, content) => `<block s-elif="{{${exp}}}">${content}</block>`,
477
+ wrapIf: (exp, content, renderMustache) => `<block s-if="${renderMustache(exp)}">${content}</block>`,
478
+ wrapElseIf: (exp, content, renderMustache) => `<block s-elif="${renderMustache(exp)}">${content}</block>`,
479
479
  wrapElse: (content) => `<block s-else>${content}</block>`,
480
- forAttrs: (listExp, item, index) => {
481
- const attrs = [`s-for="{{${listExp}}}"`];
480
+ forAttrs: (listExp, renderMustache, item, index) => {
481
+ const attrs = [`s-for="${renderMustache(listExp)}"`];
482
482
  if (item) attrs.push(`s-for-item="${item}"`);
483
483
  if (index) attrs.push(`s-for-index="${index}"`);
484
484
  return attrs;
@@ -538,11 +538,11 @@ function parseEventBinding$1(eventName) {
538
538
  */
539
539
  const ttPlatform = {
540
540
  name: "tt",
541
- wrapIf: (exp, content) => `<block tt:if="{{${exp}}}">${content}</block>`,
542
- wrapElseIf: (exp, content) => `<block tt:elif="{{${exp}}}">${content}</block>`,
541
+ wrapIf: (exp, content, renderMustache) => `<block tt:if="${renderMustache(exp)}">${content}</block>`,
542
+ wrapElseIf: (exp, content, renderMustache) => `<block tt:elif="${renderMustache(exp)}">${content}</block>`,
543
543
  wrapElse: (content) => `<block tt:else>${content}</block>`,
544
- forAttrs: (listExp, item, index) => {
545
- const attrs = [`tt:for="{{${listExp}}}"`];
544
+ forAttrs: (listExp, renderMustache, item, index) => {
545
+ const attrs = [`tt:for="${renderMustache(listExp)}"`];
546
546
  if (item) attrs.push(`tt:for-item="${item}"`);
547
547
  if (index) attrs.push(`tt:for-index="${index}"`);
548
548
  return attrs;
@@ -602,11 +602,11 @@ function parseEventBinding(eventName) {
602
602
  */
603
603
  const wechatPlatform = {
604
604
  name: "wechat",
605
- wrapIf: (exp, content) => `<block wx:if="{{${exp}}}">${content}</block>`,
606
- wrapElseIf: (exp, content) => `<block wx:elif="{{${exp}}}">${content}</block>`,
605
+ wrapIf: (exp, content, renderMustache) => `<block wx:if="${renderMustache(exp)}">${content}</block>`,
606
+ wrapElseIf: (exp, content, renderMustache) => `<block wx:elif="${renderMustache(exp)}">${content}</block>`,
607
607
  wrapElse: (content) => `<block wx:else>${content}</block>`,
608
- forAttrs: (listExp, item, index) => {
609
- const attrs = [`wx:for="{{${listExp}}}"`];
608
+ forAttrs: (listExp, renderMustache, item, index) => {
609
+ const attrs = [`wx:for="${renderMustache(listExp)}"`];
610
610
  if (item) attrs.push(`wx:for-item="${item}"`);
611
611
  if (index) attrs.push(`wx:for-index="${index}"`);
612
612
  return attrs;
@@ -1144,6 +1144,9 @@ function isTopLevel(path) {
1144
1144
 
1145
1145
  //#endregion
1146
1146
  //#region src/plugins/wevu/pageFeatures/flags.ts
1147
+ function injectWevuShareLifecycleHooksIntoOptionsObject(_optionsObject, _enabled) {
1148
+ return false;
1149
+ }
1147
1150
  /**
1148
1151
  * 扫描 AST,收集启用的 wevu 页面特性标识。
1149
1152
  */
@@ -1201,32 +1204,33 @@ function injectWevuPageFeatureFlagsIntoOptionsObject(optionsObject, enabled) {
1201
1204
  if (!enabled.size) return false;
1202
1205
  const expectedKeys = Array.from(enabled);
1203
1206
  const existingFeaturesProp = getObjectPropertyByKey$2(optionsObject, "features");
1207
+ let changed = false;
1204
1208
  if (!existingFeaturesProp) {
1205
1209
  const featuresObject = buildInjectedFeaturesObject(enabled);
1206
1210
  const setupIndex = getObjectMemberIndexByKey(optionsObject, "setup");
1207
1211
  const insertAt = setupIndex >= 0 ? setupIndex : 0;
1208
1212
  optionsObject.properties.splice(insertAt, 0, t.objectProperty(t.identifier("features"), featuresObject));
1209
- return true;
1210
- }
1211
- if (t.isObjectExpression(existingFeaturesProp.value)) {
1213
+ changed = true;
1214
+ } else if (t.isObjectExpression(existingFeaturesProp.value)) {
1212
1215
  const featuresObject = existingFeaturesProp.value;
1213
1216
  const injectedProps = [];
1214
1217
  for (const key of expectedKeys) {
1215
1218
  if (getObjectPropertyByKey$2(featuresObject, key)) continue;
1216
1219
  injectedProps.push(t.objectProperty(t.identifier(key), t.booleanLiteral(true)));
1217
1220
  }
1218
- if (!injectedProps.length) return false;
1219
- featuresObject.properties.splice(0, 0, ...injectedProps);
1220
- return true;
1221
- }
1222
- if (t.isIdentifier(existingFeaturesProp.value) || t.isMemberExpression(existingFeaturesProp.value)) {
1221
+ if (injectedProps.length) {
1222
+ featuresObject.properties.splice(0, 0, ...injectedProps);
1223
+ changed = true;
1224
+ }
1225
+ } else if (t.isIdentifier(existingFeaturesProp.value) || t.isMemberExpression(existingFeaturesProp.value)) {
1223
1226
  const base = t.cloneNode(existingFeaturesProp.value, true);
1224
1227
  const injected = buildInjectedFeaturesObject(enabled);
1225
1228
  injected.properties.push(t.spreadElement(base));
1226
1229
  existingFeaturesProp.value = injected;
1227
- return true;
1230
+ changed = true;
1228
1231
  }
1229
- return false;
1232
+ changed = injectWevuShareLifecycleHooksIntoOptionsObject(optionsObject, enabled) || changed;
1233
+ return changed;
1230
1234
  }
1231
1235
 
1232
1236
  //#endregion
@@ -1378,6 +1382,26 @@ function createModuleAnalysis(id, ast) {
1378
1382
 
1379
1383
  //#endregion
1380
1384
  //#region src/plugins/wevu/pageFeatures/optionsObjects.ts
1385
+ function unwrapTypeLikeExpression$1(node) {
1386
+ if (t.isTSAsExpression(node) || t.isTSSatisfiesExpression(node) || t.isTSNonNullExpression(node) || t.isTypeCastExpression(node)) return unwrapTypeLikeExpression$1(node.expression);
1387
+ if (t.isParenthesizedExpression(node)) return unwrapTypeLikeExpression$1(node.expression);
1388
+ return node;
1389
+ }
1390
+ function resolveOptionsObjectFromExpression(node) {
1391
+ const normalized = unwrapTypeLikeExpression$1(node);
1392
+ if (t.isObjectExpression(normalized)) return normalized;
1393
+ if (t.isIdentifier(normalized)) return null;
1394
+ if (t.isCallExpression(normalized)) {
1395
+ const callee = normalized.callee;
1396
+ if (t.isMemberExpression(callee) && !callee.computed && t.isIdentifier(callee.object, { name: "Object" }) && t.isIdentifier(callee.property, { name: "assign" })) for (let index = normalized.arguments.length - 1; index >= 0; index -= 1) {
1397
+ const argument = normalized.arguments[index];
1398
+ if (t.isSpreadElement(argument) || !t.isExpression(argument)) continue;
1399
+ const candidate = resolveOptionsObjectFromExpression(argument);
1400
+ if (candidate) return candidate;
1401
+ }
1402
+ }
1403
+ return null;
1404
+ }
1381
1405
  function getSetupFunctionFromOptionsObject(options) {
1382
1406
  for (const prop of options.properties) if (t.isObjectProperty(prop) && !prop.computed && isStaticObjectKeyMatch$1(prop.key, "setup")) {
1383
1407
  if (t.isFunctionExpression(prop.value) || t.isArrowFunctionExpression(prop.value)) return prop.value;
@@ -1411,7 +1435,8 @@ function collectTargetOptionsObjects(ast, moduleId) {
1411
1435
  if (objectBinding?.kind !== "namespace" || objectBinding.source !== WE_VU_MODULE_ID) return;
1412
1436
  if (node.callee.property.name !== WE_VU_RUNTIME_APIS.defineComponent && node.callee.property.name !== WE_VU_RUNTIME_APIS.createWevuComponent) return;
1413
1437
  } else return;
1414
- if (t.isObjectExpression(first)) optionsObjects.push(first);
1438
+ const inlineObject = resolveOptionsObjectFromExpression(first);
1439
+ if (inlineObject) optionsObjects.push(inlineObject);
1415
1440
  else if (t.isIdentifier(first)) {
1416
1441
  const target = constObjectBindings.get(first.name);
1417
1442
  if (target) optionsObjects.push(target);
@@ -1434,7 +1459,8 @@ function collectTargetOptionsObjects(ast, moduleId) {
1434
1459
  if (objectBinding?.kind !== "namespace" || objectBinding.source !== WE_VU_MODULE_ID) return;
1435
1460
  if (callee.property.name !== WE_VU_RUNTIME_APIS.defineComponent && callee.property.name !== WE_VU_RUNTIME_APIS.createWevuComponent) return;
1436
1461
  } else return;
1437
- if (t.isObjectExpression(first)) optionsObjects.push(first);
1462
+ const inlineObject = resolveOptionsObjectFromExpression(first);
1463
+ if (inlineObject) optionsObjects.push(inlineObject);
1438
1464
  else if (t.isIdentifier(first)) {
1439
1465
  const target = constObjectBindings.get(first.name);
1440
1466
  if (target) optionsObjects.push(target);
@@ -1870,6 +1896,21 @@ function isObjectAssignCall(node) {
1870
1896
  const callee = node.callee;
1871
1897
  return t.isMemberExpression(callee) && t.isIdentifier(callee.object, { name: "Object" }) && t.isIdentifier(callee.property, { name: "assign" });
1872
1898
  }
1899
+ function unwrapTypeLikeExpression(node) {
1900
+ if (t.isTSAsExpression(node) || t.isTSSatisfiesExpression(node) || t.isTSNonNullExpression(node) || t.isTypeCastExpression(node)) return unwrapTypeLikeExpression(node.expression);
1901
+ if (t.isParenthesizedExpression(node)) return unwrapTypeLikeExpression(node.expression);
1902
+ return node;
1903
+ }
1904
+ function resolveObjectExpressionFromAssignCall(node) {
1905
+ if (!isObjectAssignCall(node)) return null;
1906
+ for (let index = node.arguments.length - 1; index >= 0; index -= 1) {
1907
+ const arg = node.arguments[index];
1908
+ if (t.isSpreadElement(arg) || !t.isExpression(arg)) continue;
1909
+ const normalized = unwrapTypeLikeExpression(arg);
1910
+ if (t.isObjectExpression(normalized)) return normalized;
1911
+ }
1912
+ return null;
1913
+ }
1873
1914
  function unwrapDefineComponent(node, aliases) {
1874
1915
  if (t.isCallExpression(node) && isDefineComponentCall(node, aliases)) {
1875
1916
  const arg = node.arguments[0];
@@ -1887,6 +1928,7 @@ function resolveComponentExpression(declaration, defineComponentDecls, aliases)
1887
1928
  const matched = defineComponentDecls.get(arg.name);
1888
1929
  return matched ? t.cloneNode(matched, true) : null;
1889
1930
  }
1931
+ if (t.isExpression(arg)) return arg;
1890
1932
  return null;
1891
1933
  }
1892
1934
  if (t.isCallExpression(declaration) && isObjectAssignCall(declaration)) return declaration;
@@ -1896,6 +1938,13 @@ function resolveComponentExpression(declaration, defineComponentDecls, aliases)
1896
1938
  }
1897
1939
  return null;
1898
1940
  }
1941
+ function resolveComponentOptionsObject(componentExpr) {
1942
+ if (!componentExpr) return null;
1943
+ const normalized = unwrapTypeLikeExpression(componentExpr);
1944
+ if (t.isObjectExpression(normalized)) return normalized;
1945
+ if (t.isCallExpression(normalized)) return resolveObjectExpressionFromAssignCall(normalized);
1946
+ return null;
1947
+ }
1899
1948
 
1900
1949
  //#endregion
1901
1950
  //#region src/plugins/vue/transform/transformScript/collect.ts
@@ -2212,6 +2261,10 @@ function createValidIdentifier(name, fallback) {
2212
2261
  return t.identifier(fallback);
2213
2262
  }
2214
2263
  function buildNormalizedExpression(binding, helpers) {
2264
+ if (binding.type === "bind") {
2265
+ const exp = binding.expAst ? t.cloneNode(binding.expAst, true) : t.identifier("undefined");
2266
+ return t.callExpression(t.arrowFunctionExpression([], t.blockStatement([t.tryStatement(t.blockStatement([t.returnStatement(exp)]), t.catchClause(t.identifier("__wv_expr_err"), t.blockStatement([t.returnStatement(t.identifier("undefined"))])), null)])), []);
2267
+ }
2215
2268
  const normalizeHelper = binding.type === "class" ? helpers.normalizeClass : helpers.normalizeStyle;
2216
2269
  const exp = binding.expAst ? t.cloneNode(binding.expAst, true) : t.stringLiteral("");
2217
2270
  const normalizedCall = t.callExpression(t.cloneNode(normalizeHelper), [exp]);
@@ -2592,23 +2645,24 @@ function rewriteDefaultExport(ast, state, options, enabledPageFeatures, serializ
2592
2645
  let transformed = false;
2593
2646
  const exportPath = state.defaultExportPath;
2594
2647
  const componentExpr = resolveComponentExpression(exportPath.node.declaration, state.defineComponentDecls, state.defineComponentAliases);
2595
- if (componentExpr && t.isObjectExpression(componentExpr) && enabledPageFeatures.size) transformed = injectWevuPageFeatureFlagsIntoOptionsObject(componentExpr, enabledPageFeatures) || transformed;
2596
- if (componentExpr && t.isObjectExpression(componentExpr) && parsedWevuDefaults) transformed = applyWevuDefaultsToComponentOptions({
2597
- componentExpr,
2648
+ const componentOptionsObject = resolveComponentOptionsObject(componentExpr);
2649
+ if (componentOptionsObject && enabledPageFeatures.size) transformed = injectWevuPageFeatureFlagsIntoOptionsObject(componentOptionsObject, enabledPageFeatures) || transformed;
2650
+ if (componentOptionsObject && parsedWevuDefaults) transformed = applyWevuDefaultsToComponentOptions({
2651
+ componentExpr: componentOptionsObject,
2598
2652
  parsedWevuDefaults,
2599
2653
  options
2600
2654
  }) || transformed;
2601
2655
  const classStyleBindings = options?.classStyleBindings ?? [];
2602
- if (classStyleBindings.length) if (componentExpr && t.isObjectExpression(componentExpr)) {
2656
+ if (classStyleBindings.length) if (componentOptionsObject) {
2603
2657
  ensureClassStyleRuntimeImports(ast.program);
2604
- transformed = injectClassStyleComputed(componentExpr, classStyleBindings, warn) || transformed;
2658
+ transformed = injectClassStyleComputed(componentOptionsObject, classStyleBindings, warn) || transformed;
2605
2659
  } else warn("无法自动注入 class/style 计算属性:组件选项不是对象字面量。");
2606
2660
  const templateRefs = options?.templateRefs ?? [];
2607
- if (templateRefs.length) if (componentExpr && t.isObjectExpression(componentExpr)) transformed = injectTemplateRefs(componentExpr, templateRefs, warn) || transformed;
2661
+ if (templateRefs.length) if (componentOptionsObject) transformed = injectTemplateRefs(componentOptionsObject, templateRefs, warn) || transformed;
2608
2662
  else warn("无法自动注入 template ref 元数据:组件选项不是对象字面量。");
2609
2663
  const inlineExpressions = options?.inlineExpressions ?? [];
2610
- if (inlineExpressions.length) if (componentExpr && t.isObjectExpression(componentExpr)) {
2611
- const injected = injectInlineExpressions(componentExpr, inlineExpressions);
2664
+ if (inlineExpressions.length) if (componentOptionsObject) {
2665
+ const injected = injectInlineExpressions(componentOptionsObject, inlineExpressions);
2612
2666
  if (!injected) warn("无法自动注入内联表达式元数据:methods 不是对象字面量。");
2613
2667
  transformed = injected || transformed;
2614
2668
  } else warn("无法自动注入内联表达式元数据:组件选项不是对象字面量。");
@@ -2691,7 +2745,7 @@ function normalizeJsxText(value) {
2691
2745
  function printExpression(exp) {
2692
2746
  return generate(exp).code;
2693
2747
  }
2694
- function unwrapTsExpression$1(exp) {
2748
+ function unwrapTsExpression$2(exp) {
2695
2749
  let current = exp;
2696
2750
  while (t.isTSAsExpression(current) || t.isTSTypeAssertion(current) || t.isTSNonNullExpression(current) || t.isParenthesizedExpression(current) || t.isTSInstantiationExpression(current)) {
2697
2751
  if (t.isTSAsExpression(current) || t.isTSTypeAssertion(current) || t.isTSNonNullExpression(current)) {
@@ -2707,7 +2761,10 @@ function unwrapTsExpression$1(exp) {
2707
2761
  return current;
2708
2762
  }
2709
2763
  function normalizeInterpolationExpression(exp) {
2710
- return normalizeWxmlExpression(printExpression(unwrapTsExpression$1(exp)));
2764
+ return normalizeWxmlExpression(printExpression(unwrapTsExpression$2(exp)));
2765
+ }
2766
+ function renderMustache$1(expression, context) {
2767
+ return context.mustacheInterpolation === "spaced" ? `{{ ${expression} }}` : `{{${expression}}}`;
2711
2768
  }
2712
2769
  function pushScope$1(context, names) {
2713
2770
  for (const name of names) {
@@ -2771,20 +2828,20 @@ function toJsxTagName(name, context) {
2771
2828
  }
2772
2829
  function resolveRenderableExpression(node) {
2773
2830
  if (t.isObjectMethod(node)) {
2774
- for (const statement of node.body.body) if (t.isReturnStatement(statement) && statement.argument) return unwrapTsExpression$1(statement.argument);
2831
+ for (const statement of node.body.body) if (t.isReturnStatement(statement) && statement.argument) return unwrapTsExpression$2(statement.argument);
2775
2832
  return null;
2776
2833
  }
2777
2834
  if (!node.value) return null;
2778
2835
  const value = node.value;
2779
2836
  if (t.isArrowFunctionExpression(value)) {
2780
2837
  if (t.isBlockStatement(value.body)) {
2781
- for (const statement of value.body.body) if (t.isReturnStatement(statement) && statement.argument) return unwrapTsExpression$1(statement.argument);
2838
+ for (const statement of value.body.body) if (t.isReturnStatement(statement) && statement.argument) return unwrapTsExpression$2(statement.argument);
2782
2839
  return null;
2783
2840
  }
2784
- return unwrapTsExpression$1(value.body);
2841
+ return unwrapTsExpression$2(value.body);
2785
2842
  }
2786
2843
  if (t.isFunctionExpression(value)) {
2787
- for (const statement of value.body.body) if (t.isReturnStatement(statement) && statement.argument) return unwrapTsExpression$1(statement.argument);
2844
+ for (const statement of value.body.body) if (t.isReturnStatement(statement) && statement.argument) return unwrapTsExpression$2(statement.argument);
2788
2845
  }
2789
2846
  return null;
2790
2847
  }
@@ -2913,7 +2970,7 @@ function readJsxAttributeExpression(value) {
2913
2970
  if (t.isStringLiteral(value)) return value;
2914
2971
  if (!t.isJSXExpressionContainer(value)) return null;
2915
2972
  if (t.isJSXEmptyExpression(value.expression)) return null;
2916
- return unwrapTsExpression$1(value.expression);
2973
+ return unwrapTsExpression$2(value.expression);
2917
2974
  }
2918
2975
  function extractJsxKeyExpression(node) {
2919
2976
  for (const attr of node.openingElement.attributes) {
@@ -2936,17 +2993,17 @@ function compileEventAttribute(name, value, context) {
2936
2993
  const inline = registerInlineExpression$1(exp, context);
2937
2994
  const attrs = [`data-wv-inline-id="${inline.id}"`, `${bindAttr}="__weapp_vite_inline"`];
2938
2995
  inline.scopeKeys.forEach((scopeKey, index) => {
2939
- attrs.push(`data-wv-s${index}="{{${scopeKey}}}"`);
2996
+ attrs.push(`data-wv-s${index}="${renderMustache$1(scopeKey, context)}"`);
2940
2997
  });
2941
2998
  return attrs;
2942
2999
  }
2943
- function compileNormalAttribute(name, value) {
3000
+ function compileNormalAttribute(name, value, context) {
2944
3001
  const normalizedName = name === "className" ? "class" : name;
2945
3002
  const exp = readJsxAttributeExpression(value);
2946
3003
  if (!exp) return null;
2947
3004
  if (t.isStringLiteral(exp)) return `${normalizedName}="${escapeAttr(exp.value)}"`;
2948
- if (t.isBooleanLiteral(exp)) return `${normalizedName}="{{${exp.value}}}"`;
2949
- return `${normalizedName}="{{${normalizeInterpolationExpression(exp)}}}"`;
3005
+ if (t.isBooleanLiteral(exp)) return `${normalizedName}="${renderMustache$1(String(exp.value), context)}"`;
3006
+ return `${normalizedName}="${renderMustache$1(normalizeInterpolationExpression(exp), context)}"`;
2950
3007
  }
2951
3008
  function compileJsxAttributes(attributes, context) {
2952
3009
  const output = [];
@@ -2965,7 +3022,7 @@ function compileJsxAttributes(attributes, context) {
2965
3022
  output.push(...compileEventAttribute(name, attr.value, context));
2966
3023
  continue;
2967
3024
  }
2968
- const normalAttr = compileNormalAttribute(name, attr.value);
3025
+ const normalAttr = compileNormalAttribute(name, attr.value, context);
2969
3026
  if (normalAttr) output.push(normalAttr);
2970
3027
  }
2971
3028
  return output;
@@ -2982,6 +3039,7 @@ function compileMapExpression(exp, context) {
2982
3039
  return null;
2983
3040
  }
2984
3041
  const listExp = compileListExpression(callee.object);
3042
+ const renderTemplateMustache = (expression) => renderMustache$1(expression, context);
2985
3043
  const itemParam = callback.params[0];
2986
3044
  const indexParam = callback.params[1];
2987
3045
  const item = t.isIdentifier(itemParam) ? itemParam.name : "item";
@@ -2991,10 +3049,10 @@ function compileMapExpression(exp, context) {
2991
3049
  let bodyExp = null;
2992
3050
  if (t.isBlockStatement(callback.body)) {
2993
3051
  for (const statement of callback.body.body) if (t.isReturnStatement(statement) && statement.argument) {
2994
- bodyExp = unwrapTsExpression$1(statement.argument);
3052
+ bodyExp = unwrapTsExpression$2(statement.argument);
2995
3053
  break;
2996
3054
  }
2997
- } else bodyExp = unwrapTsExpression$1(callback.body);
3055
+ } else bodyExp = unwrapTsExpression$2(callback.body);
2998
3056
  const body = bodyExp ? compileRenderableExpression(bodyExp, context) : "";
2999
3057
  popScope$1(context, addedScope.length);
3000
3058
  if (!body) return "";
@@ -3004,30 +3062,32 @@ function compileMapExpression(exp, context) {
3004
3062
  if (extracted) keyValue = extracted;
3005
3063
  else if (index) keyValue = index;
3006
3064
  } else if (index) keyValue = index;
3007
- return `<block ${[...context.platform.forAttrs(listExp, item, index), context.platform.keyAttr(keyValue)].join(" ")}>${body}</block>`;
3065
+ return `<block ${[...context.platform.forAttrs(listExp, renderTemplateMustache, item, index), context.platform.keyAttr(keyValue)].join(" ")}>${body}</block>`;
3008
3066
  }
3009
3067
  function compileConditionalExpression(exp, context) {
3068
+ const renderTemplateMustache = (expression) => renderMustache$1(expression, context);
3010
3069
  const test = normalizeInterpolationExpression(exp.test);
3011
3070
  const consequent = compileRenderableExpression(exp.consequent, context);
3012
3071
  const alternate = compileRenderableExpression(exp.alternate, context);
3013
- if (!alternate) return context.platform.wrapIf(test, consequent);
3014
- return `${context.platform.wrapIf(test, consequent)}${context.platform.wrapElse(alternate)}`;
3072
+ if (!alternate) return context.platform.wrapIf(test, consequent, renderTemplateMustache);
3073
+ return `${context.platform.wrapIf(test, consequent, renderTemplateMustache)}${context.platform.wrapElse(alternate)}`;
3015
3074
  }
3016
3075
  function compileLogicalExpression(exp, context) {
3076
+ const renderTemplateMustache = (expression) => renderMustache$1(expression, context);
3017
3077
  if (exp.operator === "&&") {
3018
3078
  const test = normalizeInterpolationExpression(exp.left);
3019
3079
  const content = compileRenderableExpression(exp.right, context);
3020
- return context.platform.wrapIf(test, content);
3080
+ return context.platform.wrapIf(test, content, renderTemplateMustache);
3021
3081
  }
3022
3082
  if (exp.operator === "||") {
3023
3083
  const test = normalizeInterpolationExpression(t.unaryExpression("!", t.parenthesizedExpression(t.cloneNode(exp.left, true))));
3024
3084
  const content = compileRenderableExpression(exp.right, context);
3025
- return context.platform.wrapIf(test, content);
3085
+ return context.platform.wrapIf(test, content, renderTemplateMustache);
3026
3086
  }
3027
- return `{{${normalizeInterpolationExpression(exp)}}}`;
3087
+ return renderMustache$1(normalizeInterpolationExpression(exp), context);
3028
3088
  }
3029
3089
  function compileRenderableExpression(exp, context) {
3030
- const node = unwrapTsExpression$1(exp);
3090
+ const node = unwrapTsExpression$2(exp);
3031
3091
  if (t.isJSXElement(node)) return compileJsxElement(node, context);
3032
3092
  if (t.isJSXFragment(node)) return compileJsxFragment(node, context);
3033
3093
  if (t.isConditionalExpression(node)) return compileConditionalExpression(node, context);
@@ -3041,7 +3101,7 @@ function compileRenderableExpression(exp, context) {
3041
3101
  return compileRenderableExpression(element, context);
3042
3102
  }).join("");
3043
3103
  if (t.isNullLiteral(node) || t.isBooleanLiteral(node)) return "";
3044
- return `{{${normalizeInterpolationExpression(node)}}}`;
3104
+ return renderMustache$1(normalizeInterpolationExpression(node), context);
3045
3105
  }
3046
3106
  function compileExpressionContainer(node, context) {
3047
3107
  const exp = node.expression;
@@ -3183,6 +3243,7 @@ function collectJsxAutoComponentContext(source, filename, warn) {
3183
3243
  const importedComponents = collectImportedComponents(ast);
3184
3244
  const context = {
3185
3245
  platform: wechatPlatform,
3246
+ mustacheInterpolation: "compact",
3186
3247
  warnings: [],
3187
3248
  inlineExpressions: [],
3188
3249
  inlineExpressionSeed: 0,
@@ -3207,6 +3268,7 @@ function compileJsxTemplate(source, filename, options) {
3207
3268
  const ast = parse$2(source, BABEL_TS_MODULE_PARSER_OPTIONS);
3208
3269
  const context = {
3209
3270
  platform: options?.template?.platform ?? wechatPlatform,
3271
+ mustacheInterpolation: options?.template?.mustacheInterpolation ?? "compact",
3210
3272
  warnings: [],
3211
3273
  inlineExpressions: [],
3212
3274
  inlineExpressionSeed: 0,
@@ -4445,6 +4507,7 @@ const JS_RUNTIME_GLOBALS = new Set([
4445
4507
  "require",
4446
4508
  "arguments",
4447
4509
  "globalThis",
4510
+ "__wevuUnref",
4448
4511
  "wx",
4449
4512
  "getApp",
4450
4513
  "getCurrentPages"
@@ -4470,6 +4533,9 @@ function createMemberAccess(target, prop) {
4470
4533
  function createThisMemberAccess(prop) {
4471
4534
  return createMemberAccess(t.thisExpression(), prop);
4472
4535
  }
4536
+ function createUnrefCall(exp) {
4537
+ return t.callExpression(t.identifier("__wevuUnref"), [exp]);
4538
+ }
4473
4539
  function normalizeJsExpressionWithContext(exp, context, options) {
4474
4540
  const trimmed = exp.trim();
4475
4541
  if (!trimmed) return null;
@@ -4492,10 +4558,10 @@ function normalizeJsExpressionWithContext(exp, context, options) {
4492
4558
  if (context.rewriteScopedSlot) if (Object.prototype.hasOwnProperty.call(slotProps, name)) {
4493
4559
  const prop = slotProps[name];
4494
4560
  const base = createThisMemberAccess("__wvSlotPropsData");
4495
- replacement = prop ? createMemberAccess(base, prop) : base;
4496
- } else if (name === "__wvOwner" || name === "__wvSlotPropsData" || name === "__wvSlotProps" || name === "__wvSlotScope") replacement = createThisMemberAccess(name);
4497
- else replacement = createMemberAccess(createThisMemberAccess("__wvOwner"), name);
4498
- else replacement = createThisMemberAccess(name);
4561
+ replacement = createUnrefCall(prop ? createMemberAccess(base, prop) : base);
4562
+ } else if (name === "__wvOwner" || name === "__wvSlotPropsData" || name === "__wvSlotProps" || name === "__wvSlotScope") replacement = createUnrefCall(createThisMemberAccess(name));
4563
+ else replacement = createUnrefCall(createMemberAccess(createThisMemberAccess("__wvOwner"), name));
4564
+ else replacement = createUnrefCall(createThisMemberAccess(name));
4499
4565
  const parent = path.parentPath;
4500
4566
  if (parent.isObjectProperty() && parent.node.shorthand && parent.node.key === path.node) {
4501
4567
  parent.node.shorthand = false;
@@ -4508,6 +4574,12 @@ function normalizeJsExpressionWithContext(exp, context, options) {
4508
4574
  return (stmt && "expression" in stmt ? stmt.expression : null) || null;
4509
4575
  }
4510
4576
 
4577
+ //#endregion
4578
+ //#region src/plugins/vue/compiler/template/mustache.ts
4579
+ function renderMustache(expression, context) {
4580
+ return context.mustacheInterpolation === "spaced" ? `{{ ${expression} }}` : `{{${expression}}}`;
4581
+ }
4582
+
4511
4583
  //#endregion
4512
4584
  //#region src/plugins/vue/compiler/template/attributes.ts
4513
4585
  function toWxmlStringLiteral(value) {
@@ -4516,7 +4588,7 @@ function toWxmlStringLiteral(value) {
4516
4588
  function cloneForStack(context) {
4517
4589
  return context.forStack.map((info) => ({ ...info }));
4518
4590
  }
4519
- function buildForIndexAccess(context) {
4591
+ function buildForIndexAccess$1(context) {
4520
4592
  if (!context.forStack.length) return "";
4521
4593
  return context.forStack.map((info) => `[${info.index ?? "index"}]`).join("");
4522
4594
  }
@@ -4529,15 +4601,15 @@ function mergeJsExpressionParts(parts) {
4529
4601
  if (parts.length === 1) return parts[0];
4530
4602
  return t.arrayExpression(parts);
4531
4603
  }
4532
- function unwrapTsExpression(node) {
4533
- if (t.isTSAsExpression(node) || t.isTSNonNullExpression(node) || t.isTSTypeAssertion(node)) return unwrapTsExpression(node.expression);
4604
+ function unwrapTsExpression$1(node) {
4605
+ if (t.isTSAsExpression(node) || t.isTSNonNullExpression(node) || t.isTSTypeAssertion(node)) return unwrapTsExpression$1(node.expression);
4534
4606
  return node;
4535
4607
  }
4536
4608
  function shouldPreferJsClassStyleRuntime(exp) {
4537
4609
  const ast = parseBabelExpression(exp);
4538
4610
  if (!ast) return true;
4539
4611
  const visit = (node) => {
4540
- const current = unwrapTsExpression(node);
4612
+ const current = unwrapTsExpression$1(node);
4541
4613
  if (t.isIdentifier(current) || t.isMemberExpression(current) || t.isOptionalMemberExpression(current) || t.isCallExpression(current) || t.isOptionalCallExpression(current) || t.isThisExpression(current) || t.isSuper(current) || t.isAwaitExpression(current) || t.isYieldExpression(current) || t.isNewExpression(current)) return true;
4542
4614
  if (t.isStringLiteral(current) || t.isNumericLiteral(current) || t.isBooleanLiteral(current) || t.isNullLiteral(current) || t.isBigIntLiteral(current) || t.isRegExpLiteral(current)) return false;
4543
4615
  if (t.isTemplateLiteral(current)) return current.expressions.some((exp) => visit(exp));
@@ -4560,9 +4632,9 @@ function shouldPreferJsClassStyleRuntime(exp) {
4560
4632
  return visit(ast);
4561
4633
  }
4562
4634
  function createClassStyleBinding(context, type, exp, expAst) {
4563
- const index = context.classStyleBindings.length;
4635
+ const sameTypeCount = context.classStyleBindings.filter((binding) => binding.type === type).length;
4564
4636
  return {
4565
- name: type === "class" ? `__wv_cls_${index}` : `__wv_style_${index}`,
4637
+ name: type === "class" ? `__wv_cls_${sameTypeCount}` : type === "style" ? `__wv_style_${sameTypeCount}` : `__wv_bind_${sameTypeCount}`,
4566
4638
  type,
4567
4639
  exp,
4568
4640
  expAst,
@@ -4579,7 +4651,7 @@ function renderClassAttribute(staticClass, dynamicClassExp, context) {
4579
4651
  for (const part of normalizedParts) parts.push(`(${part})`);
4580
4652
  const mergedExp = parts.length > 1 ? `[${parts.join(",")}]` : parts[0];
4581
4653
  context.classStyleWxs = true;
4582
- return `class="{{__weapp_vite.cls(${mergedExp})}}"`;
4654
+ return `class="${renderMustache(`__weapp_vite.cls(${mergedExp})`, context)}"`;
4583
4655
  }
4584
4656
  const jsParts = [];
4585
4657
  if (staticValue) jsParts.push(t.stringLiteral(staticValue));
@@ -4588,8 +4660,8 @@ function renderClassAttribute(staticClass, dynamicClassExp, context) {
4588
4660
  const expAst = mergeJsExpressionParts(jsParts);
4589
4661
  const binding = createClassStyleBinding(context, "class", generateExpressionCode(expAst), expAst);
4590
4662
  context.classStyleBindings.push(binding);
4591
- const indexAccess = buildForIndexAccess(context);
4592
- return `class="{{${binding.name}${indexAccess}}}"`;
4663
+ const indexAccess = buildForIndexAccess$1(context);
4664
+ return `class="${renderMustache(`${binding.name}${indexAccess}`, context)}"`;
4593
4665
  }
4594
4666
  function renderStyleAttribute(staticStyle, dynamicStyleExp, vShowExp, context) {
4595
4667
  const staticValue = staticStyle?.trim();
@@ -4607,7 +4679,7 @@ function renderStyleAttribute(staticStyle, dynamicStyleExp, vShowExp, context) {
4607
4679
  }
4608
4680
  const mergedExp = parts.length > 1 ? `[${parts.join(",")}]` : parts[0] || "''";
4609
4681
  context.classStyleWxs = true;
4610
- return `style="{{__weapp_vite.style(${mergedExp})}}"`;
4682
+ return `style="${renderMustache(`__weapp_vite.style(${mergedExp})`, context)}"`;
4611
4683
  }
4612
4684
  const jsParts = [];
4613
4685
  if (staticValue) jsParts.push(t.stringLiteral(staticValue));
@@ -4622,8 +4694,8 @@ function renderStyleAttribute(staticStyle, dynamicStyleExp, vShowExp, context) {
4622
4694
  const expAst = mergeJsExpressionParts(jsParts);
4623
4695
  const binding = createClassStyleBinding(context, "style", generateExpressionCode(expAst), expAst);
4624
4696
  context.classStyleBindings.push(binding);
4625
- const indexAccess = buildForIndexAccess(context);
4626
- return `style="{{${binding.name}${indexAccess}}}"`;
4697
+ const indexAccess = buildForIndexAccess$1(context);
4698
+ return `style="${renderMustache(`${binding.name}${indexAccess}`, context)}"`;
4627
4699
  }
4628
4700
  function transformAttribute(node, _context) {
4629
4701
  const { name, value } = node;
@@ -4634,6 +4706,38 @@ function transformAttribute(node, _context) {
4634
4706
 
4635
4707
  //#endregion
4636
4708
  //#region src/plugins/vue/compiler/template/directives/bind.ts
4709
+ function unwrapTsExpression(node) {
4710
+ if (node.type === "TSAsExpression" || node.type === "TSNonNullExpression" || node.type === "TSTypeAssertion") return unwrapTsExpression(node.expression);
4711
+ return node;
4712
+ }
4713
+ function isTopLevelObjectLiteral(exp) {
4714
+ const parsed = parseBabelExpression(exp);
4715
+ if (!parsed) return false;
4716
+ return unwrapTsExpression(parsed).type === "ObjectExpression";
4717
+ }
4718
+ function buildForIndexAccess(context) {
4719
+ if (!context.forStack.length) return "";
4720
+ return context.forStack.map((info) => `[${info.index ?? "index"}]`).join("");
4721
+ }
4722
+ function createBindRuntimeAttr(argValue, rawExpValue, context) {
4723
+ const expAst = normalizeJsExpressionWithContext(rawExpValue, context, { hint: `:${argValue} 绑定` });
4724
+ if (!expAst) return null;
4725
+ const binding = {
4726
+ name: `__wv_bind_${context.classStyleBindings.filter((item) => item.type === "bind").length}`,
4727
+ type: "bind",
4728
+ exp: rawExpValue,
4729
+ expAst,
4730
+ forStack: context.forStack.map((info) => ({ ...info }))
4731
+ };
4732
+ context.classStyleBindings.push(binding);
4733
+ const indexAccess = buildForIndexAccess(context);
4734
+ return `${argValue}="${renderMustache(`${binding.name}${indexAccess}`, context)}"`;
4735
+ }
4736
+ function createInlineObjectLiteralAttr(argValue, rawExpValue, context) {
4737
+ const expValue = normalizeWxmlExpressionWithContext(rawExpValue, context).trim();
4738
+ if (context.mustacheInterpolation === "spaced") return `${argValue}="${renderMustache(expValue, context)}"`;
4739
+ return `${argValue}="{{ ${expValue} }}"`;
4740
+ }
4637
4741
  const isSimpleIdentifier = (value) => /^[A-Z_$][\w$]*$/i.test(value);
4638
4742
  const isSimpleMemberPath = (value) => /^[A-Z_$][\w$]*(?:\.[A-Z_$][\w$]*)*$/i.test(value);
4639
4743
  function transformBindDirective(node, context, forInfo) {
@@ -4641,8 +4745,10 @@ function transformBindDirective(node, context, forInfo) {
4641
4745
  if (!arg) return null;
4642
4746
  const argValue = arg.type === NodeTypes.SIMPLE_EXPRESSION ? arg.content : "";
4643
4747
  if (!exp) return null;
4644
- const expValue = normalizeWxmlExpressionWithContext(exp.type === NodeTypes.SIMPLE_EXPRESSION ? exp.content : "", context);
4748
+ const rawExpValue = exp.type === NodeTypes.SIMPLE_EXPRESSION ? exp.content : "";
4749
+ if (!rawExpValue) return null;
4645
4750
  if (argValue === "key") {
4751
+ const expValue = normalizeWxmlExpressionWithContext(rawExpValue, context);
4646
4752
  const trimmed = expValue.trim();
4647
4753
  const warnKeyFallback = (reason) => {
4648
4754
  if (!forInfo) return;
@@ -4666,7 +4772,11 @@ function transformBindDirective(node, context, forInfo) {
4666
4772
  }
4667
4773
  return context.platform.keyAttr(expValue);
4668
4774
  }
4669
- return `${argValue}="{{${expValue}}}"`;
4775
+ if (isTopLevelObjectLiteral(rawExpValue)) {
4776
+ if (context.objectLiteralBindMode === "inline") return createInlineObjectLiteralAttr(argValue, rawExpValue, context);
4777
+ return createBindRuntimeAttr(argValue, rawExpValue, context);
4778
+ }
4779
+ return `${argValue}="${renderMustache(normalizeWxmlExpressionWithContext(rawExpValue, context), context)}"`;
4670
4780
  }
4671
4781
 
4672
4782
  //#endregion
@@ -4690,8 +4800,8 @@ function transformCustomDirective(name, exp, arg, context) {
4690
4800
  const dataAttrName = `data-v-${name}`;
4691
4801
  if (exp && exp.type === NodeTypes.SIMPLE_EXPRESSION) {
4692
4802
  const expValue = normalizeWxmlExpressionWithContext(exp.content, context);
4693
- if (/^[a-z_$][\w$]*$/i.test(expValue)) return `${dataAttrName}="{{${expValue}}}"`;
4694
- return `${dataAttrName}="{{${expValue}}}"`;
4803
+ if (/^[a-z_$][\w$]*$/i.test(expValue)) return `${dataAttrName}="${renderMustache(expValue, context)}"`;
4804
+ return `${dataAttrName}="${renderMustache(expValue, context)}"`;
4695
4805
  }
4696
4806
  if (arg && arg.type === NodeTypes.SIMPLE_EXPRESSION) return `${dataAttrName}="${arg.content}"`;
4697
4807
  context.warnings.push(`自定义指令 v-${name} 可能需要运行时支持。已生成 data 属性:${dataAttrName}`);
@@ -4712,24 +4822,24 @@ function transformVModel(element, expValue, context) {
4712
4822
  const bindModel = (event) => {
4713
4823
  return `${context.platform.eventBindingAttr(event)}="__weapp_vite_model" data-wv-model="${escapedModel}"`;
4714
4824
  };
4715
- if (!element) return `value="{{${expValue}}}" ${bindModel("input")}`;
4825
+ if (!element) return `value="${renderMustache(expValue, context)}" ${bindModel("input")}`;
4716
4826
  const tag = element.tag;
4717
4827
  const typeAttr = getElementType(element);
4718
4828
  switch (tag) {
4719
4829
  case "input": switch (typeAttr) {
4720
- case "checkbox": return `checked="{{${expValue}}}" ${bindModel("change")}`;
4721
- case "radio": return `value="{{${expValue}}}" ${bindModel("change")}`;
4722
- default: return `value="{{${expValue}}}" ${bindModel("input")}`;
4830
+ case "checkbox": return `checked="${renderMustache(expValue, context)}" ${bindModel("change")}`;
4831
+ case "radio": return `value="${renderMustache(expValue, context)}" ${bindModel("change")}`;
4832
+ default: return `value="${renderMustache(expValue, context)}" ${bindModel("input")}`;
4723
4833
  }
4724
- case "textarea": return `value="{{${expValue}}}" ${bindModel("input")}`;
4725
- case "select": return `value="{{${expValue}}}" ${bindModel("change")}`;
4834
+ case "textarea": return `value="${renderMustache(expValue, context)}" ${bindModel("input")}`;
4835
+ case "select": return `value="${renderMustache(expValue, context)}" ${bindModel("change")}`;
4726
4836
  case "switch":
4727
- case "checkbox": return `checked="{{${expValue}}}" ${bindModel("change")}`;
4728
- case "slider": return `value="{{${expValue}}}" ${bindModel("change")}`;
4729
- case "picker": return `value="{{${expValue}}}" ${bindModel("change")}`;
4837
+ case "checkbox": return `checked="${renderMustache(expValue, context)}" ${bindModel("change")}`;
4838
+ case "slider": return `value="${renderMustache(expValue, context)}" ${bindModel("change")}`;
4839
+ case "picker": return `value="${renderMustache(expValue, context)}" ${bindModel("change")}`;
4730
4840
  default:
4731
4841
  context.warnings.push(`在 <${tag}> 上使用 v-model 可能无法按预期工作,已使用默认绑定。`);
4732
- return `value="{{${expValue}}}" ${bindModel("input")}`;
4842
+ return `value="${renderMustache(expValue, context)}" ${bindModel("input")}`;
4733
4843
  }
4734
4844
  }
4735
4845
  function transformModelDirective(node, context, elementNode) {
@@ -4741,9 +4851,9 @@ function transformModelDirective(node, context, elementNode) {
4741
4851
  //#endregion
4742
4852
  //#region src/plugins/vue/compiler/template/directives/on.ts
4743
4853
  const isSimpleHandler = (value) => /^[A-Z_$][\w$]*$/i.test(value);
4744
- function buildInlineScopeAttrs(scopeBindings) {
4854
+ function buildInlineScopeAttrs(scopeBindings, context) {
4745
4855
  return scopeBindings.map((binding, index) => {
4746
- return `data-wv-s${index}="{{${binding.replace(/"/g, "&quot;")}}}"`;
4856
+ return `data-wv-s${index}="${renderMustache(binding.replace(/"/g, "&quot;"), context)}"`;
4747
4857
  });
4748
4858
  }
4749
4859
  function resolveEventPrefix(modifiers) {
@@ -4770,7 +4880,7 @@ function transformOnDirective(node, context) {
4770
4880
  const bindAttr = context.platform.eventBindingAttr(`${eventPrefix}:${mappedEvent}`);
4771
4881
  if (context.rewriteScopedSlot) {
4772
4882
  if (inlineExpression) {
4773
- const scopeAttrs = buildInlineScopeAttrs(inlineExpression.scopeBindings);
4883
+ const scopeAttrs = buildInlineScopeAttrs(inlineExpression.scopeBindings, context);
4774
4884
  return [
4775
4885
  `data-wv-inline-id="${inlineExpression.id}"`,
4776
4886
  ...scopeAttrs,
@@ -4785,7 +4895,7 @@ function transformOnDirective(node, context) {
4785
4895
  }
4786
4896
  const expValue = normalizeWxmlExpressionWithContext(rawExpValue, context);
4787
4897
  if (inlineExpression) {
4788
- const scopeAttrs = buildInlineScopeAttrs(inlineExpression.scopeBindings);
4898
+ const scopeAttrs = buildInlineScopeAttrs(inlineExpression.scopeBindings, context);
4789
4899
  return [
4790
4900
  `data-wv-inline-id="${inlineExpression.id}"`,
4791
4901
  ...scopeAttrs,
@@ -4801,7 +4911,7 @@ function transformOnDirective(node, context) {
4801
4911
  function transformShowDirective(node, context) {
4802
4912
  const { exp } = node;
4803
4913
  if (!exp) return null;
4804
- return `style="{{${normalizeWxmlExpressionWithContext(exp.type === NodeTypes.SIMPLE_EXPRESSION ? exp.content : "", context)} ? '' : 'display: none'}}"`;
4914
+ return `style="${renderMustache(`${normalizeWxmlExpressionWithContext(exp.type === NodeTypes.SIMPLE_EXPRESSION ? exp.content : "", context)} ? '' : 'display: none'`, context)}"`;
4805
4915
  }
4806
4916
 
4807
4917
  //#endregion
@@ -4918,7 +5028,7 @@ function collectElementAttributes(node, context, options) {
4918
5028
  //#region src/plugins/vue/compiler/template/elements/tag-slot.ts
4919
5029
  function renderSlotNameAttribute(info, context, attrName) {
4920
5030
  if (info.type === "static" && info.value !== "default") return `${attrName}="${info.value}"`;
4921
- if (info.type === "dynamic") return `${attrName}="{{${normalizeWxmlExpressionWithContext(info.exp, context)}}}"`;
5031
+ if (info.type === "dynamic") return `${attrName}="${renderMustache(normalizeWxmlExpressionWithContext(info.exp, context), context)}"`;
4922
5032
  }
4923
5033
  function resolveSlotNameFromDirective(slotDirective) {
4924
5034
  if (!slotDirective.arg) return { type: "default" };
@@ -5116,8 +5226,9 @@ function transformSlotElement(node, context, transformNode) {
5116
5226
  if (context.scopedSlotsRequireProps && !slotPropsExp) return slotTag;
5117
5227
  const genericKey = `scoped-slots-${resolveSlotKey(context, slotNameInfo)}`;
5118
5228
  context.componentGenerics[genericKey] = true;
5119
- const scopedAttrs = [`__wv-owner-id="{{__wvSlotOwnerId}}"`, `__wv-slot-props="{{${slotPropsExp ?? "[]"}}}"`];
5120
- if (context.slotMultipleInstance) scopedAttrs.push(`__wv-slot-scope="{{__wvSlotScope}}"`);
5229
+ const resolvedSlotPropsExp = slotPropsExp ?? "[]";
5230
+ const scopedAttrs = [`__wv-owner-id="${renderMustache("__wvSlotOwnerId", context)}"`, `__wv-slot-props="${renderMustache(resolvedSlotPropsExp, context)}"`];
5231
+ if (context.slotMultipleInstance) scopedAttrs.push(`__wv-slot-scope="${renderMustache("__wvSlotScope", context)}"`);
5121
5232
  return `${slotTag}${`<${genericKey}${scopedAttrs.length ? ` ${scopedAttrs.join(" ")}` : ""} />`}`;
5122
5233
  }
5123
5234
  function transformSlotElementPlain(node, context, transformNode) {
@@ -5166,7 +5277,7 @@ function transformComponentWithSlots(node, context, transformNode, options) {
5166
5277
  isComponent: true
5167
5278
  });
5168
5279
  let children = node.children.map((child) => transformNode(child, context)).join("");
5169
- if (vTextExp !== void 0) children = `{{${vTextExp}}}`;
5280
+ if (vTextExp !== void 0) children = renderMustache(vTextExp, context);
5170
5281
  const attrString = attrs.length ? ` ${attrs.join(" ")}` : "";
5171
5282
  const { tag } = node;
5172
5283
  return children ? `<${tag}${attrString}>${children}</${tag}>` : `<${tag}${attrString} />`;
@@ -5196,11 +5307,11 @@ function transformComponentWithSlots(node, context, transformNode, options) {
5196
5307
  ...attrs,
5197
5308
  ...slotGenericAttrs
5198
5309
  ];
5199
- if (slotNames.length) mergedAttrs.push(`vue-slots="{{[${slotNames.join(",")}]}}"`);
5310
+ if (slotNames.length) mergedAttrs.push(`vue-slots="${renderMustache(`[${slotNames.join(",")}]`, context)}"`);
5200
5311
  if (scopedSlotDeclarations.length) {
5201
5312
  const scopePropsExp = buildScopePropsExpression(context);
5202
- if (scopePropsExp) mergedAttrs.push(`__wv-slot-scope="{{${scopePropsExp}}}"`);
5203
- mergedAttrs.push(`__wv-slot-owner-id="{{__wvOwnerId || ''}}"`);
5313
+ if (scopePropsExp) mergedAttrs.push(`__wv-slot-scope="${renderMustache(scopePropsExp, context)}"`);
5314
+ mergedAttrs.push(`__wv-slot-owner-id="${renderMustache(`__wvOwnerId || ''`, context)}"`);
5204
5315
  }
5205
5316
  const attrString = mergedAttrs.length ? ` ${mergedAttrs.join(" ")}` : "";
5206
5317
  const { tag } = node;
@@ -5236,7 +5347,7 @@ function transformComponentWithSlotsFallback(node, context, transformNode, optio
5236
5347
  isComponent: true
5237
5348
  });
5238
5349
  let children = node.children.map((child) => transformNode(child, context)).join("");
5239
- if (vTextExp !== void 0) children = `{{${vTextExp}}}`;
5350
+ if (vTextExp !== void 0) children = renderMustache(vTextExp, context);
5240
5351
  const attrString = attrs.length ? ` ${attrs.join(" ")}` : "";
5241
5352
  const { tag } = node;
5242
5353
  return children ? `<${tag}${attrString}>${children}</${tag}>` : `<${tag}${attrString} />`;
@@ -5273,7 +5384,7 @@ function transformComponentElement(node, context, transformNode) {
5273
5384
  if (slotDirective || templateSlotChildren.length > 0) return transformComponentWithSlots({
5274
5385
  ...node,
5275
5386
  props: otherProps
5276
- }, context, transformNode, { extraAttrs: [`data-is="{{${componentVar}}}"`] });
5387
+ }, context, transformNode, { extraAttrs: [`data-is="${renderMustache(componentVar, context)}"`] });
5277
5388
  for (const prop of otherProps) if (prop.type === NodeTypes.ATTRIBUTE) {
5278
5389
  const attr = transformAttribute(prop, context);
5279
5390
  if (attr) attrs.push(attr);
@@ -5284,7 +5395,7 @@ function transformComponentElement(node, context, transformNode) {
5284
5395
  const children = node.children.map((child) => transformNode(child, context)).join("");
5285
5396
  const attrString = attrs.length ? ` ${attrs.join(" ")}` : "";
5286
5397
  context.warnings.push("动态组件使用 data-is 属性,可能需要小程序运行时支持。");
5287
- return `<component data-is="{{${componentVar}}}"${attrString}>${children}</component>`;
5398
+ return `<component data-is="${renderMustache(componentVar, context)}"${attrString}>${children}</component>`;
5288
5399
  }
5289
5400
 
5290
5401
  //#endregion
@@ -5297,7 +5408,7 @@ function transformNormalElement(node, context, transformNode) {
5297
5408
  const { attrs, vTextExp } = collectElementAttributes(node, context);
5298
5409
  let children = "";
5299
5410
  if (node.children.length > 0) children = node.children.map((child) => transformNode(child, context)).join("");
5300
- if (vTextExp !== void 0) children = `{{${vTextExp}}}`;
5411
+ if (vTextExp !== void 0) children = renderMustache(vTextExp, context);
5301
5412
  const attrString = attrs.length ? ` ${attrs.join(" ")}` : "";
5302
5413
  return children ? `<${tag}${attrString}>${children}</${tag}>` : `<${tag}${attrString} />`;
5303
5414
  }
@@ -5305,6 +5416,7 @@ function transformNormalElement(node, context, transformNode) {
5305
5416
  //#endregion
5306
5417
  //#region src/plugins/vue/compiler/template/elements/tag-structural.ts
5307
5418
  function transformIfElement(node, context, transformNode) {
5419
+ const renderTemplateMustache = (exp) => renderMustache(exp, context);
5308
5420
  const ifDirective = node.props.find((prop) => prop.type === NodeTypes.DIRECTIVE && (prop.name === "if" || prop.name === "else-if" || prop.name === "else"));
5309
5421
  if (!ifDirective)
5310
5422
  /* istanbul ignore next */
@@ -5320,14 +5432,15 @@ function transformIfElement(node, context, transformNode) {
5320
5432
  const dir = ifDirective;
5321
5433
  if (dir.name === "if" && dir.exp) {
5322
5434
  const expValue = normalizeWxmlExpressionWithContext(dir.exp.type === NodeTypes.SIMPLE_EXPRESSION ? dir.exp.content : "", context);
5323
- return context.platform.wrapIf(expValue, content);
5435
+ return context.platform.wrapIf(expValue, content, renderTemplateMustache);
5324
5436
  } else if (dir.name === "else-if" && dir.exp) {
5325
5437
  const expValue = normalizeWxmlExpressionWithContext(dir.exp.type === NodeTypes.SIMPLE_EXPRESSION ? dir.exp.content : "", context);
5326
- return context.platform.wrapElseIf(expValue, content);
5438
+ return context.platform.wrapElseIf(expValue, content, renderTemplateMustache);
5327
5439
  } else if (dir.name === "else") return context.platform.wrapElse(content);
5328
5440
  return content;
5329
5441
  }
5330
5442
  function transformForElement(node, context, transformNode) {
5443
+ const renderTemplateMustache = (exp) => renderMustache(exp, context);
5331
5444
  const forDirective = node.props.find((prop) => prop.type === NodeTypes.DIRECTIVE && prop.name === "for");
5332
5445
  if (!forDirective || !forDirective.exp) return transformNormalElement(node, context, transformNode);
5333
5446
  const forInfo = parseForExpression(forDirective.exp.type === NodeTypes.SIMPLE_EXPRESSION ? forDirective.exp.content : "");
@@ -5353,7 +5466,7 @@ function transformForElement(node, context, transformNode) {
5353
5466
  ...node,
5354
5467
  props: otherProps
5355
5468
  };
5356
- const extraAttrs = listExp ? context.platform.forAttrs(listExp, forInfo.item, forInfo.index) : [];
5469
+ const extraAttrs = listExp ? context.platform.forAttrs(listExp, renderTemplateMustache, forInfo.item, forInfo.index) : [];
5357
5470
  const slotDirective = findSlotDirective(elementWithoutFor);
5358
5471
  const templateSlotChildren = elementWithoutFor.children.filter((child) => child.type === NodeTypes.ELEMENT && child.tag === "template" && findSlotDirective(child));
5359
5472
  if (slotDirective || templateSlotChildren.length > 0) return transformComponentWithSlots(elementWithoutFor, context, transformNode, {
@@ -5366,7 +5479,7 @@ function transformForElement(node, context, transformNode) {
5366
5479
  });
5367
5480
  let children = "";
5368
5481
  if (elementWithoutFor.children.length > 0) children = elementWithoutFor.children.map((child) => transformNode(child, context)).join("");
5369
- if (vTextExp !== void 0) children = `{{${vTextExp}}}`;
5482
+ if (vTextExp !== void 0) children = renderMustache(vTextExp, context);
5370
5483
  const { tag } = elementWithoutFor;
5371
5484
  const attrString = attrs.length ? ` ${attrs.join(" ")}` : "";
5372
5485
  return children ? `<${tag}${attrString}>${children}</${tag}>` : `<${tag}${attrString} />`;
@@ -5386,6 +5499,7 @@ function transformKeepAliveElement(node, context, transformNode) {
5386
5499
  return `<block data-keep-alive="true">${node.children.map((child) => transformNode(child, context)).join("")}</block>`;
5387
5500
  }
5388
5501
  function transformTemplateElement(node, context, transformNode) {
5502
+ const renderTemplateMustache = (exp) => renderMustache(exp, context);
5389
5503
  let nameAttr = "";
5390
5504
  let isAttr = "";
5391
5505
  let dataAttr = "";
@@ -5420,11 +5534,11 @@ function transformTemplateElement(node, context, transformNode) {
5420
5534
  };
5421
5535
  if (dir.name === "if" && dir.exp) {
5422
5536
  const expValue = normalizeWxmlExpressionWithContext(dir.exp.type === NodeTypes.SIMPLE_EXPRESSION ? dir.exp.content : "", context);
5423
- return context.platform.wrapIf(expValue, children);
5537
+ return context.platform.wrapIf(expValue, children, renderTemplateMustache);
5424
5538
  }
5425
5539
  if (dir.name === "else-if" && dir.exp) {
5426
5540
  const expValue = normalizeWxmlExpressionWithContext(dir.exp.type === NodeTypes.SIMPLE_EXPRESSION ? dir.exp.content : "", context);
5427
- return context.platform.wrapElseIf(expValue, children);
5541
+ return context.platform.wrapElseIf(expValue, children, renderTemplateMustache);
5428
5542
  }
5429
5543
  if (dir.name === "else") return context.platform.wrapElse(children);
5430
5544
  return transformIfElement(fakeNode, context, transformNode);
@@ -5465,9 +5579,9 @@ function transformText(node, _context) {
5465
5579
  }
5466
5580
  function transformInterpolation(node, context) {
5467
5581
  const { content } = node;
5468
- if (content.type === NodeTypes.SIMPLE_EXPRESSION) return `{{${normalizeWxmlExpressionWithContext(content.content, context)}}}`;
5582
+ if (content.type === NodeTypes.SIMPLE_EXPRESSION) return renderMustache(normalizeWxmlExpressionWithContext(content.content, context), context);
5469
5583
  /* istanbul ignore next */
5470
- return "{{}}";
5584
+ return renderMustache("", context);
5471
5585
  }
5472
5586
  function transformNode(node, context) {
5473
5587
  switch (node.type) {
@@ -5510,6 +5624,8 @@ function compileVueTemplateToWxml(template, filename, options) {
5510
5624
  slotPropStack: [],
5511
5625
  rewriteScopedSlot: false,
5512
5626
  classStyleRuntime: resolvedRuntime === "wxs" ? "wxs" : "js",
5627
+ objectLiteralBindMode: options?.objectLiteralBindMode ?? "runtime",
5628
+ mustacheInterpolation: options?.mustacheInterpolation ?? "compact",
5513
5629
  classStyleBindings: [],
5514
5630
  classStyleWxs: false,
5515
5631
  classStyleWxsExtension: wxsExtension,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wevu/compiler",
3
3
  "type": "module",
4
- "version": "0.1.1",
4
+ "version": "6.6.3",
5
5
  "description": "wevu 编译器基础包,面向小程序模板的编译与转换",
6
6
  "author": "ice breaker <1324318532@qq.com>",
7
7
  "license": "MIT",
@@ -53,8 +53,8 @@
53
53
  "merge": "^2.1.1",
54
54
  "pathe": "^2.0.3",
55
55
  "vue": "^3.5.28",
56
- "rolldown-require": "2.0.6",
57
- "@weapp-core/shared": "3.0.1"
56
+ "@weapp-core/shared": "3.0.1",
57
+ "rolldown-require": "2.0.6"
58
58
  },
59
59
  "publishConfig": {
60
60
  "access": "public",