@wevu/compiler 6.16.7 → 6.16.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.mjs +141 -37
  2. package/package.json +3 -3
package/dist/index.mjs CHANGED
@@ -4756,10 +4756,10 @@ function resolveMappedHtmlTagClassName(tag, context, resolvedTag) {
4756
4756
  }
4757
4757
  //#endregion
4758
4758
  //#region src/plugins/vue/compiler/template/elements/forExpression.ts
4759
- const IDENTIFIER_RE$4 = /^[A-Z_$][\w$]*$/i;
4759
+ const IDENTIFIER_RE$5 = /^[A-Z_$][\w$]*$/i;
4760
4760
  const FOR_ITEM_ALIAS_PLACEHOLDER = "__wv_for_item__";
4761
4761
  function isIdentifier(value) {
4762
- return IDENTIFIER_RE$4.test(value);
4762
+ return IDENTIFIER_RE$5.test(value);
4763
4763
  }
4764
4764
  function splitTopLevelByComma(input) {
4765
4765
  const out = [];
@@ -5033,7 +5033,7 @@ function withSlotProps(context, mapping, fn) {
5033
5033
  popSlotProps(context);
5034
5034
  }
5035
5035
  }
5036
- const IDENTIFIER_RE$3 = /^[A-Z_$][\w$]*$/i;
5036
+ const IDENTIFIER_RE$4 = /^[A-Z_$][\w$]*$/i;
5037
5037
  const BIND_SHORTHAND_ARG_RE = /^[A-Z_$][\w$]*(?:-[A-Z_$][\w$]*)*$/i;
5038
5038
  const BACKSLASH_RE$2 = /\\/g;
5039
5039
  const SINGLE_QUOTE_RE$2 = /'/g;
@@ -5054,7 +5054,7 @@ function collectScopePropMapping(context) {
5054
5054
  const mapping = {};
5055
5055
  if (!context.slotMultipleInstance) return mapping;
5056
5056
  for (const scope of context.scopeStack) for (const name of scope) {
5057
- if (!IDENTIFIER_RE$3.test(name)) continue;
5057
+ if (!IDENTIFIER_RE$4.test(name)) continue;
5058
5058
  if (!hasOwn(mapping, name)) mapping[name] = name;
5059
5059
  }
5060
5060
  return mapping;
@@ -5143,7 +5143,7 @@ function replaceIdentifierWithExpression(path, replacement) {
5143
5143
  }
5144
5144
  path.replaceWith(replacement);
5145
5145
  }
5146
- const IDENTIFIER_RE$2 = /^[A-Z_$][\w$]*$/i;
5146
+ const IDENTIFIER_RE$3 = /^[A-Z_$][\w$]*$/i;
5147
5147
  function rewriteScopedSlotExpression(exp, context) {
5148
5148
  const normalized = normalizeWxmlExpression(exp);
5149
5149
  const parsed = parseBabelExpressionFile(normalized);
@@ -5154,7 +5154,7 @@ function rewriteScopedSlotExpression(exp, context) {
5154
5154
  const forAliases = collectForAliasMapping$2(context);
5155
5155
  const createMemberAccess = (target, prop) => {
5156
5156
  if (!prop) return t.identifier(target);
5157
- if (IDENTIFIER_RE$2.test(prop)) return t.memberExpression(t.identifier(target), t.identifier(prop));
5157
+ if (IDENTIFIER_RE$3.test(prop)) return t.memberExpression(t.identifier(target), t.identifier(prop));
5158
5158
  return t.memberExpression(t.identifier(target), t.stringLiteral(prop), true);
5159
5159
  };
5160
5160
  traverse(ast, { Identifier(path) {
@@ -5351,10 +5351,10 @@ const INLINE_GLOBALS = new Set([
5351
5351
  "scope",
5352
5352
  ...getMiniProgramRuntimeGlobalKeys()
5353
5353
  ]);
5354
- const IDENTIFIER_RE$1 = /^[A-Z_$][\w$]*$/i;
5354
+ const IDENTIFIER_RE$2 = /^[A-Z_$][\w$]*$/i;
5355
5355
  const SIMPLE_PATH_RE = /^[A-Z_$][\w$]*(?:\.[A-Z_$][\w$]*)*$/i;
5356
5356
  function createMemberAccess$1(target, prop) {
5357
- if (IDENTIFIER_RE$1.test(prop)) return t.memberExpression(t.identifier(target), t.identifier(prop));
5357
+ if (IDENTIFIER_RE$2.test(prop)) return t.memberExpression(t.identifier(target), t.identifier(prop));
5358
5358
  return t.memberExpression(t.identifier(target), t.stringLiteral(prop), true);
5359
5359
  }
5360
5360
  function resolveSlotPropBinding(slotProps, name) {
@@ -5880,7 +5880,7 @@ function transformBindDirective(node, context, forInfo) {
5880
5880
  }
5881
5881
  //#endregion
5882
5882
  //#region src/plugins/vue/compiler/template/directives/custom.ts
5883
- const IDENTIFIER_RE = /^[a-z_$][\w$]*$/i;
5883
+ const IDENTIFIER_RE$1 = /^[a-z_$][\w$]*$/i;
5884
5884
  function transformCustomDirective(name, exp, arg, context) {
5885
5885
  if (new Set([
5886
5886
  "bind",
@@ -5900,7 +5900,7 @@ function transformCustomDirective(name, exp, arg, context) {
5900
5900
  const dataAttrName = `data-v-${name}`;
5901
5901
  if (exp && exp.type === NodeTypes.SIMPLE_EXPRESSION) {
5902
5902
  const expValue = normalizeWxmlExpressionWithContext(exp.content, context);
5903
- if (IDENTIFIER_RE.test(expValue)) return `${dataAttrName}="${renderMustache(expValue, context)}"`;
5903
+ if (IDENTIFIER_RE$1.test(expValue)) return `${dataAttrName}="${renderMustache(expValue, context)}"`;
5904
5904
  return `${dataAttrName}="${renderMustache(expValue, context)}"`;
5905
5905
  }
5906
5906
  if (arg && arg.type === NodeTypes.SIMPLE_EXPRESSION) return `${dataAttrName}="${arg.content}"`;
@@ -5917,6 +5917,28 @@ function getElementType(element) {
5917
5917
  return "";
5918
5918
  }
5919
5919
  const QUOTE_RE$1 = /"/g;
5920
+ const CAMELIZE_RE = /-([a-z0-9])/gi;
5921
+ const IDENTIFIER_RE = /^[A-Z_$][\w$]*$/i;
5922
+ const NATIVE_MODEL_TAGS = new Set([
5923
+ "input",
5924
+ "textarea",
5925
+ "select",
5926
+ "switch",
5927
+ "checkbox",
5928
+ "slider",
5929
+ "picker"
5930
+ ]);
5931
+ function camelize(value) {
5932
+ return value.replace(CAMELIZE_RE, (_, char) => char.toUpperCase());
5933
+ }
5934
+ function buildModelAssignmentExpression(rawExpValue) {
5935
+ if (IDENTIFIER_RE.test(rawExpValue)) return `ctx.${rawExpValue} = $event`;
5936
+ return `${rawExpValue} = $event`;
5937
+ }
5938
+ function isNativeModelElement(element) {
5939
+ if (!element || element.tag !== element.tag.toLowerCase()) return false;
5940
+ return NATIVE_MODEL_TAGS.has(element.tag);
5941
+ }
5920
5942
  function transformVModel(element, expValue, context) {
5921
5943
  const escapedModel = expValue.replace(QUOTE_RE$1, """);
5922
5944
  const bindModel = (event) => {
@@ -5942,9 +5964,48 @@ function transformVModel(element, expValue, context) {
5942
5964
  return `value="${renderMustache(expValue, context)}" ${bindModel("input")}`;
5943
5965
  }
5944
5966
  }
5945
- function transformModelDirective(node, context, elementNode) {
5967
+ function transformComponentModelDirective(node, context) {
5968
+ const rawExpValue = getBindDirectiveExpression(node).trim();
5969
+ if (!rawExpValue) return null;
5970
+ const rawModelName = node.arg?.type === NodeTypes.SIMPLE_EXPRESSION ? node.arg.content.trim() : "";
5971
+ if (node.arg?.type === NodeTypes.SIMPLE_EXPRESSION && !node.arg.isStatic) {
5972
+ context.warnings.push("暂不支持动态 v-model 参数,已忽略该 v-model。");
5973
+ return null;
5974
+ }
5975
+ const modelProp = rawModelName || "modelValue";
5976
+ if (!modelProp) return null;
5977
+ const updateEvent = `update:${camelize(modelProp)}`;
5978
+ const eventSuffix = normalizeEventDatasetSuffix(updateEvent);
5979
+ const bindAttr = context.platform.eventBindingAttr(updateEvent);
5980
+ const inlineExpression = registerInlineExpression(buildModelAssignmentExpression(rawExpValue), context);
5981
+ if (!inlineExpression) {
5982
+ context.warnings.push(`v-model="${rawExpValue}" 需要是可赋值的成员表达式。`);
5983
+ return null;
5984
+ }
5985
+ const modelAttr = modelProp === "modelValue" ? `modelValue="${renderMustache(normalizeWxmlExpressionWithContext(rawExpValue, context), context)}"` : transformBindDirective(node, context);
5986
+ const updateAttr = [
5987
+ `data-wd-${eventSuffix}="1"`,
5988
+ `data-wi-${eventSuffix}="${inlineExpression.id}"`,
5989
+ `${bindAttr}="${WEVU_INLINE_HANDLER}"`
5990
+ ].filter(Boolean).join(" ");
5991
+ const modifierNames = node.modifiers.map((modifier) => modifier.content.trim()).filter(Boolean);
5992
+ const modifierProperties = modifierNames.map((name) => `${JSON.stringify(name)}:true`).join(",");
5993
+ const modifiersProp = modelProp === "modelValue" ? "modelModifiers" : `${modelProp}Modifiers`;
5994
+ const modifiersRef = modifierNames.length ? registerRuntimeBindingExpression(`{${modifierProperties}}`, context, { hint: "v-model modifiers" }) : null;
5995
+ return [
5996
+ modelAttr,
5997
+ updateAttr,
5998
+ modifiersRef ? `${modifiersProp}="${renderMustache(modifiersRef, context)}"` : null
5999
+ ].filter(Boolean).join(" ");
6000
+ }
6001
+ function transformModelDirective(node, context, elementNode, options) {
5946
6002
  const { exp } = node;
5947
6003
  if (!exp) return null;
6004
+ if (options?.isComponent === true && !isNativeModelElement(elementNode)) return transformComponentModelDirective(node, context);
6005
+ if (node.arg) {
6006
+ context.warnings.push("原生小程序元素不支持 v-model 参数,已忽略该 v-model。");
6007
+ return null;
6008
+ }
5948
6009
  return transformVModel(elementNode, normalizeWxmlExpressionWithContext(exp.type === NodeTypes.SIMPLE_EXPRESSION ? exp.content : "", context), context);
5949
6010
  }
5950
6011
  //#endregion
@@ -6045,7 +6106,7 @@ function transformDirective(node, context, elementNode, forInfo, options) {
6045
6106
  const { name, exp, arg } = node;
6046
6107
  if (name === "bind") return transformBindDirective(node, context, forInfo);
6047
6108
  if (name === "on") return transformOnDirective(node, context, options);
6048
- if (name === "model") return transformModelDirective(node, context, elementNode);
6109
+ if (name === "model") return transformModelDirective(node, context, elementNode, options);
6049
6110
  if (name === "show") return transformShowDirective(node, context);
6050
6111
  if (name === "html") {
6051
6112
  context.warnings.push("小程序不支持 v-html,请使用 rich-text 组件替代。");
@@ -6406,24 +6467,59 @@ function injectAttributeIntoOpeningTag(source, attr) {
6406
6467
  if (tagNameEnd <= 1) return null;
6407
6468
  return `${source.slice(0, tagNameEnd)} ${attr}${source.slice(tagNameEnd)}`;
6408
6469
  }
6470
+ function createSlotAttributeNode(sourceNode, attr) {
6471
+ const match = /^slot="([\s\S]*)"$/.exec(attr);
6472
+ if (!match) return null;
6473
+ return {
6474
+ type: NodeTypes.ATTRIBUTE,
6475
+ name: "slot",
6476
+ nameLoc: sourceNode.loc,
6477
+ value: {
6478
+ type: NodeTypes.TEXT,
6479
+ content: match[1],
6480
+ loc: sourceNode.loc
6481
+ },
6482
+ loc: sourceNode.loc
6483
+ };
6484
+ }
6485
+ function injectSlotAttributeIntoElementNode(child, slotAttr, transformNode, context) {
6486
+ if (child.type !== NodeTypes.ELEMENT || child.tag === "template") return null;
6487
+ const sourceNode = child;
6488
+ const slotAttribute = createSlotAttributeNode(sourceNode, slotAttr);
6489
+ if (!slotAttribute) return null;
6490
+ return transformNode({
6491
+ ...sourceNode,
6492
+ props: [slotAttribute, ...sourceNode.props]
6493
+ }, context);
6494
+ }
6495
+ function isRenderableFallbackChild(child) {
6496
+ if (child.type === NodeTypes.COMMENT) return false;
6497
+ if (child.type === NodeTypes.TEXT) return child.content.trim().length > 0;
6498
+ return true;
6499
+ }
6409
6500
  function renderSlotFallback(decl, context, transformNode) {
6410
- const rawRenderedChildren = decl.children.map((child) => ({ code: transformNode(child, context) }));
6411
- const rawContent = rawRenderedChildren.map((item) => item.code).join("");
6412
- if (!rawContent) return "";
6413
6501
  const slotAttr = renderSlotNameAttribute(decl.name, context, "slot");
6414
6502
  const wrapCondition = (content) => {
6415
6503
  return decl.condition ? context.platform.wrapIf(decl.condition, content, (exp) => renderMustache(exp, context)) : content;
6416
6504
  };
6417
- if (!slotAttr) return wrapCondition(rawContent);
6418
- if (!context.slotSingleRootNoWrapper) return wrapCondition(`<view ${slotAttr}>${rawContent}</view>`);
6419
- const renderedChildren = rawRenderedChildren.filter((item) => item.code.trim().length > 0);
6420
- if (!renderedChildren.length) return "";
6421
- const content = renderedChildren.map((item) => item.code).join("");
6422
- if (renderedChildren.length === 1) {
6423
- const projected = injectAttributeIntoOpeningTag(renderedChildren[0].code, slotAttr);
6505
+ if (!slotAttr) {
6506
+ const rawContent = decl.children.map((child) => transformNode(child, context)).join("");
6507
+ if (!rawContent) return "";
6508
+ return wrapCondition(rawContent);
6509
+ }
6510
+ const renderableChildren = decl.children.filter(isRenderableFallbackChild);
6511
+ if (!renderableChildren.length) return "";
6512
+ if (!context.slotSingleRootNoWrapper) {
6513
+ const rawContent = decl.children.map((child) => transformNode(child, context)).join("");
6514
+ if (!rawContent) return "";
6515
+ return wrapCondition(`<view ${slotAttr}>${rawContent}</view>`);
6516
+ }
6517
+ if (renderableChildren.length === 1) {
6518
+ const child = renderableChildren[0];
6519
+ const projected = child.type === NodeTypes.ELEMENT && isStructuralDirective(child).type ? injectSlotAttributeIntoElementNode(child, slotAttr, transformNode, context) : injectAttributeIntoOpeningTag(transformNode(child, context), slotAttr);
6424
6520
  if (projected) return wrapCondition(projected);
6425
6521
  }
6426
- return wrapCondition(`<view ${slotAttr}>${content}</view>`);
6522
+ return wrapCondition(`<view ${slotAttr}>${renderableChildren.map((child) => transformNode(child, context)).join("")}</view>`);
6427
6523
  }
6428
6524
  function transformSlotElement(node, context, transformNode) {
6429
6525
  if (isScopedSlotsDisabled(context)) return transformSlotElementPlain(node, context, transformNode);
@@ -6535,6 +6631,13 @@ function shouldExposePlainSlotPresence(node) {
6535
6631
  function isWevuComponentTag(node, context) {
6536
6632
  return context.wevuComponentTags ? context.wevuComponentTags.has(node.tag) : /^[A-Z]/.test(node.tag);
6537
6633
  }
6634
+ function shouldTransformAsComponentWithSlots(node, context, resolvedTag = resolveTemplateTagName(node.tag, context)) {
6635
+ const slotDirective = findSlotDirective(node);
6636
+ const templateSlotChildren = node.children.filter((child) => child.type === NodeTypes.ELEMENT && child.tag === "template" && findSlotDirective(child));
6637
+ const shouldUseAugmentedDefaultSlot = node.children.length > 0 && !context.scopedSlotsRequireProps && !isBuiltinTag(resolvedTag);
6638
+ const shouldUseSlotPresenceMetadata = node.children.length > 0 && isWevuComponentTag(node, context);
6639
+ return slotDirective || templateSlotChildren.length > 0 || shouldUseAugmentedDefaultSlot || shouldUseSlotPresenceMetadata;
6640
+ }
6538
6641
  function transformComponentWithSlots(node, context, transformNode, options) {
6539
6642
  if (isScopedSlotsDisabled(context)) return transformComponentWithSlotsFallback(node, context, transformNode, options);
6540
6643
  const extraAttrs = options?.extraAttrs ?? [];
@@ -6569,7 +6672,8 @@ function transformComponentWithSlots(node, context, transformNode, options) {
6569
6672
  let children = node.children.map((child) => transformNode(child, context)).join("");
6570
6673
  if (vTextExp !== void 0) children = renderMustache(vTextExp, context);
6571
6674
  if (children && defaultSlotChildren.length && !hasLegacySlotAttribute(defaultSlotChildren) && isWevuComponentTag(node, context)) pushSlotNamesAttr(attrs, [{ name: "'default'" }], context);
6572
- const attrString = attrs.length ? ` ${attrs.join(" ")}` : "";
6675
+ const mergedAttrs = [...extraAttrs, ...attrs];
6676
+ const attrString = mergedAttrs.length ? ` ${mergedAttrs.join(" ")}` : "";
6573
6677
  const { tag } = node;
6574
6678
  return children ? `<${tag}${attrString}>${children}</${tag}>` : `<${tag}${attrString} />`;
6575
6679
  }
@@ -6645,7 +6749,8 @@ function transformComponentWithSlotsFallback(node, context, transformNode, optio
6645
6749
  let children = node.children.map((child) => transformNode(child, context)).join("");
6646
6750
  if (vTextExp !== void 0) children = renderMustache(vTextExp, context);
6647
6751
  if (children && defaultSlotChildren.length && !hasLegacySlotAttribute(defaultSlotChildren) && isWevuComponentTag(node, context)) pushSlotNamesAttr(attrs, [{ name: "'default'" }], context);
6648
- const attrString = attrs.length ? ` ${attrs.join(" ")}` : "";
6752
+ const mergedAttrs = [...extraAttrs, ...attrs];
6753
+ const attrString = mergedAttrs.length ? ` ${mergedAttrs.join(" ")}` : "";
6649
6754
  const { tag } = node;
6650
6755
  return children ? `<${tag}${attrString}>${children}</${tag}>` : `<${tag}${attrString} />`;
6651
6756
  }
@@ -6707,11 +6812,7 @@ function transformComponentElement(node, context, transformNode) {
6707
6812
  //#region src/plugins/vue/compiler/template/elements/tag-normal.ts
6708
6813
  function transformNormalElement(node, context, transformNode) {
6709
6814
  const tag = resolveTemplateTagName(node.tag, context);
6710
- const slotDirective = findSlotDirective(node);
6711
- const templateSlotChildren = node.children.filter((child) => child.type === NodeTypes.ELEMENT && child.tag === "template" && findSlotDirective(child));
6712
- const shouldUseAugmentedDefaultSlot = node.children.length > 0 && !context.scopedSlotsRequireProps && !isBuiltinTag(tag);
6713
- const shouldUseSlotPresenceMetadata = node.children.length > 0 && (context.wevuComponentTags ? context.wevuComponentTags.has(node.tag) : /^[A-Z]/.test(node.tag));
6714
- if (slotDirective || templateSlotChildren.length > 0 || shouldUseAugmentedDefaultSlot || shouldUseSlotPresenceMetadata) return transformComponentWithSlots(node, context, transformNode);
6815
+ if (shouldTransformAsComponentWithSlots(node, context, tag)) return transformComponentWithSlots(node, context, transformNode);
6715
6816
  const { attrs, vTextExp } = collectElementAttributes(node, context, { resolvedTag: tag });
6716
6817
  let children = "";
6717
6818
  if (node.children.length > 0) children = node.children.map((child) => transformNode(child, context)).join("");
@@ -6789,21 +6890,20 @@ function transformForElement(node, context, transformNode) {
6789
6890
  props: otherProps
6790
6891
  };
6791
6892
  const extraAttrs = listExp ? context.platform.forAttrs(listExp, renderTemplateMustache, forInfo.item, forInfo.index) : [];
6792
- const slotDirective = findSlotDirective(elementWithoutFor);
6793
- const templateSlotChildren = elementWithoutFor.children.filter((child) => child.type === NodeTypes.ELEMENT && child.tag === "template" && findSlotDirective(child));
6794
- if (slotDirective || templateSlotChildren.length > 0) return transformComponentWithSlots(elementWithoutFor, context, transformNode, {
6893
+ const resolvedTag = resolveTemplateTagName(elementWithoutFor.tag, context);
6894
+ if (shouldTransformAsComponentWithSlots(elementWithoutFor, context, resolvedTag)) return transformComponentWithSlots(elementWithoutFor, context, transformNode, {
6795
6895
  extraAttrs,
6796
6896
  forInfo
6797
6897
  });
6798
6898
  const { attrs, vTextExp } = collectElementAttributes(elementWithoutFor, context, {
6799
6899
  forInfo,
6800
6900
  extraAttrs,
6801
- resolvedTag: resolveTemplateTagName(elementWithoutFor.tag, context)
6901
+ resolvedTag
6802
6902
  });
6803
6903
  let children = "";
6804
6904
  if (elementWithoutFor.children.length > 0) children = elementWithoutFor.children.map((child) => transformNode(child, context)).join("");
6805
6905
  if (vTextExp !== void 0) children = renderMustache(vTextExp, context);
6806
- const tag = resolveTemplateTagName(elementWithoutFor.tag, context);
6906
+ const tag = resolvedTag;
6807
6907
  const attrString = attrs.length ? ` ${attrs.join(" ")}` : "";
6808
6908
  return children ? `<${tag}${attrString}>${children}</${tag}>` : `<${tag}${attrString} />`;
6809
6909
  }));
@@ -7936,11 +8036,15 @@ async function compileVueFile(source, filename, options) {
7936
8036
  autoUsingComponents,
7937
8037
  autoImportTags
7938
8038
  });
7939
- const templateOptions = componentSourceInfo.wevuComponentTags.size ? {
8039
+ const baseTemplateOptions = parsed.isAppFile ? {
7940
8040
  ...options?.template,
8041
+ scopedSlotsRequireProps: true
8042
+ } : options?.template;
8043
+ const templateOptions = componentSourceInfo.wevuComponentTags.size ? {
8044
+ ...baseTemplateOptions,
7941
8045
  wevuComponentTags: componentSourceInfo.wevuComponentTags
7942
8046
  } : {
7943
- ...options?.template,
8047
+ ...baseTemplateOptions,
7944
8048
  wevuComponentTags: []
7945
8049
  };
7946
8050
  const templateCompiled = compileTemplatePhase(parsed.descriptor, filename, templateOptions, result);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wevu/compiler",
3
3
  "type": "module",
4
- "version": "6.16.7",
4
+ "version": "6.16.9",
5
5
  "description": "wevu 编译器基础包,面向小程序模板的编译与转换",
6
6
  "author": "ice breaker <1324318532@qq.com>",
7
7
  "license": "MIT",
@@ -50,9 +50,9 @@
50
50
  "merge": "^2.1.1",
51
51
  "pathe": "^2.0.3",
52
52
  "vue": "^3.5.34",
53
- "@weapp-core/constants": "^0.1.4",
53
+ "@weapp-core/constants": "^0.1.6",
54
54
  "@weapp-core/shared": "3.0.4",
55
- "@weapp-vite/ast": "6.16.7",
55
+ "@weapp-vite/ast": "6.16.9",
56
56
  "rolldown-require": "2.0.15"
57
57
  },
58
58
  "publishConfig": {