@dongmingzhixiu/vuexir-compiler 0.4.6 → 0.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codegen/swiftui.js +64 -5
- package/package.json +1 -1
package/dist/codegen/swiftui.js
CHANGED
|
@@ -716,6 +716,10 @@ function emitNodeInner(node, ctx) {
|
|
|
716
716
|
const align = isRow ? (ALIGN_MAP[alignRaw] ?? '.top') : (FLEX_START_MAP[alignRaw] ?? '.leading');
|
|
717
717
|
const stack = hasAbsolute ? 'ZStack' : isRow ? 'HStack' : 'VStack';
|
|
718
718
|
const stackAlign = hasAbsolute ? '.topLeading' : align;
|
|
719
|
+
// R132:ZStack 里必须把「非绝对定位」的兄弟包成一个流式子容器,
|
|
720
|
+
// 否则它们会全部叠在左上角互相覆盖(主卡名字与日期重叠就是这个原因)
|
|
721
|
+
const flowChildren = hasAbsolute ? children.filter((c) => c.props?.position !== 'absolute') : [];
|
|
722
|
+
const absChildren = hasAbsolute ? children.filter((c) => c.props?.position === 'absolute') : [];
|
|
719
723
|
const just = props.justifyContent;
|
|
720
724
|
// R-H4:justify-content 的弹性分配仅在「分配方向」有确定空间时有意义。
|
|
721
725
|
// column(主轴=垂直)需要容器高度确定(CSS:auto 高容器无剩余空间);
|
|
@@ -727,6 +731,49 @@ function emitNodeInner(node, ctx) {
|
|
|
727
731
|
}
|
|
728
732
|
// hasAbsolute 时无 flex 语义(ZStack 叠放)
|
|
729
733
|
const justActive = justFlex && (isRow || selfDefinite) && !hasAbsolute;
|
|
734
|
+
// R132:绝对定位容器 → 非绝对子节点先包成一个流式 VStack(保持原有纵向排布),
|
|
735
|
+
// 绝对定位子节点再叠上去;否则全部叠在左上角互相覆盖
|
|
736
|
+
if (hasAbsolute && flowChildren.length > 0) {
|
|
737
|
+
const flowNode = {
|
|
738
|
+
type: 'group',
|
|
739
|
+
props: { ...props, position: undefined, absTop: undefined, absLeft: undefined, absRight: undefined, absBottom: undefined },
|
|
740
|
+
children: flowChildren,
|
|
741
|
+
};
|
|
742
|
+
const flowCode = emitNode(flowNode, {
|
|
743
|
+
parentAxis: dir,
|
|
744
|
+
level: L + 1,
|
|
745
|
+
definiteHeight: selfDefinite,
|
|
746
|
+
warnings: ctx.warnings,
|
|
747
|
+
runtime: ctx.runtime,
|
|
748
|
+
path: `${ctx.path}{flow}`,
|
|
749
|
+
inheritGap: ctx.inheritGap,
|
|
750
|
+
loop: ctx.loop,
|
|
751
|
+
dataProps: ctx.dataProps,
|
|
752
|
+
});
|
|
753
|
+
const absCode = absChildren
|
|
754
|
+
.map((c, i) => emitNode(c, {
|
|
755
|
+
parentAxis: dir,
|
|
756
|
+
level: L + 1,
|
|
757
|
+
definiteHeight: selfDefinite,
|
|
758
|
+
warnings: ctx.warnings,
|
|
759
|
+
runtime: ctx.runtime,
|
|
760
|
+
path: `${ctx.path}{abs${i}}`,
|
|
761
|
+
inheritGap: undefined,
|
|
762
|
+
loop: ctx.loop,
|
|
763
|
+
dataProps: ctx.dataProps,
|
|
764
|
+
}))
|
|
765
|
+
.join('\n');
|
|
766
|
+
const bg = props.background !== undefined ? pad(`Color(${props.background})`) : null;
|
|
767
|
+
return [
|
|
768
|
+
pad('ZStack(alignment: .topLeading) {'),
|
|
769
|
+
bg ? indent(L + 1) + bg.trim() : null,
|
|
770
|
+
flowCode,
|
|
771
|
+
absCode || null,
|
|
772
|
+
pad('}'),
|
|
773
|
+
]
|
|
774
|
+
.filter((x) => x !== null)
|
|
775
|
+
.join('\n');
|
|
776
|
+
}
|
|
730
777
|
// justifyContent:center → 首尾 Spacer;spaceBetween → 子间 Spacer(仅 column 需高度确定)
|
|
731
778
|
const body = [];
|
|
732
779
|
if (just === 'center' && justActive) {
|
|
@@ -832,7 +879,15 @@ function emitNodeInner(node, ctx) {
|
|
|
832
879
|
// M1:页面级 {{ state }} → props.bind / node.bind → Text(<@State 名>)(状态引用,非字面量)
|
|
833
880
|
const isRef = props.ref !== undefined;
|
|
834
881
|
const bindKey = props.bind ?? node.bind?.key;
|
|
835
|
-
|
|
882
|
+
// R133:bind 指向的名字必须是真实状态(或循环变量),否则说明作用域丢失 →
|
|
883
|
+
// 输出空串并告警,绝不能把状态名当文本渲染(日历页出现 Text("_vrnE1") 即是此因)
|
|
884
|
+
const bindValid = bindKey !== undefined &&
|
|
885
|
+
(currentStateNames.has(bindKey.split('.')[0]) ||
|
|
886
|
+
(ctx.loop !== undefined && (ctx.loop.itemKey === bindKey.split('.')[0] || ctx.loop.indexKey === bindKey.split('.')[0])));
|
|
887
|
+
const isBind = bindKey !== undefined && bindValid;
|
|
888
|
+
if (bindKey !== undefined && !bindValid) {
|
|
889
|
+
ctx.warnings.push(`${ctx.path}: 绑定「${bindKey}」在原生端无对应状态/循环变量 → 输出空串(R133)`);
|
|
890
|
+
}
|
|
836
891
|
const content = props.text !== undefined ? props.text : '';
|
|
837
892
|
const fs = props.fontSize ?? 15;
|
|
838
893
|
let line = isRef
|
|
@@ -848,10 +903,14 @@ function emitNodeInner(node, ctx) {
|
|
|
848
903
|
.map((p) => 'text' in p
|
|
849
904
|
? swiftStringEscape(p.text)
|
|
850
905
|
: 'bind' in p
|
|
851
|
-
?
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
906
|
+
? currentStateNames.has(p.bind.split('.')[0])
|
|
907
|
+
? `\\(${p.bind})`
|
|
908
|
+
: '' // R133:无效绑定 → 空串,避免把状态名当文本
|
|
909
|
+
: false
|
|
910
|
+
? ''
|
|
911
|
+
: 'fieldOf' in p
|
|
912
|
+
? `\\(vrnField(${p.fieldOf.obj}, "${p.fieldOf.field}"${p.fieldOf.fallback !== undefined ? `, "${swiftStringEscape(p.fieldOf.fallback)}"` : ''}))`
|
|
913
|
+
: `\\(${dictFieldExpr(p.dynField.var, p.dynField.field)})`)
|
|
855
914
|
.join('')}")`)
|
|
856
915
|
: isBind
|
|
857
916
|
? ctx.loop && (bindKey === ctx.loop.itemKey || bindKey === ctx.loop.indexKey)
|