@proteus-vue/compiler 0.3.0-beta.12 → 0.3.0-beta.15
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.js +184 -2
- package/dist/validate.d.ts +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14677,7 +14677,87 @@ var TAG_MAP = {
|
|
|
14677
14677
|
video: "video",
|
|
14678
14678
|
canvas: "canvas",
|
|
14679
14679
|
"scroll-view": "scroll-view",
|
|
14680
|
-
slot: "slot"
|
|
14680
|
+
slot: "slot",
|
|
14681
|
+
// ★★2026-09-20(外部实战报告第二十三/二十四节):**补全常见 HTML 标签 → WXML 等价映射**。
|
|
14682
|
+
// 此前这些标签落到「未知标签逃生舱」**原样输出** → 微信 wxml 编译器直接拒绝(或渲染异常):
|
|
14683
|
+
// 外部工程实测因 <details>/<summary>/<pre>/<table>/<select>/<option>/<label>/<br> 等
|
|
14684
|
+
// 导致**模拟器整屏黑屏**(构建期零报错、产物看似齐全)。
|
|
14685
|
+
// 语义映射原则:块级 → view;行内/文本类 → text;表格/列表/折叠等无对等物 → view/text
|
|
14686
|
+
// (样式与交互由 CSS + 显式状态承担,见报告第二十四节的正当适配)。
|
|
14687
|
+
// 块级容器
|
|
14688
|
+
section: "view",
|
|
14689
|
+
article: "view",
|
|
14690
|
+
aside: "view",
|
|
14691
|
+
nav: "view",
|
|
14692
|
+
main: "view",
|
|
14693
|
+
header: "view",
|
|
14694
|
+
footer: "view",
|
|
14695
|
+
figure: "view",
|
|
14696
|
+
figcaption: "text",
|
|
14697
|
+
details: "view",
|
|
14698
|
+
summary: "text",
|
|
14699
|
+
dialog: "view",
|
|
14700
|
+
form: "form",
|
|
14701
|
+
fieldset: "view",
|
|
14702
|
+
legend: "text",
|
|
14703
|
+
// 列表
|
|
14704
|
+
ul: "view",
|
|
14705
|
+
ol: "view",
|
|
14706
|
+
li: "view",
|
|
14707
|
+
dl: "view",
|
|
14708
|
+
dt: "text",
|
|
14709
|
+
dd: "text",
|
|
14710
|
+
// 表格(微信无表格组件 → view 结构 + CSS)
|
|
14711
|
+
table: "view",
|
|
14712
|
+
thead: "view",
|
|
14713
|
+
tbody: "view",
|
|
14714
|
+
tfoot: "view",
|
|
14715
|
+
tr: "view",
|
|
14716
|
+
th: "text",
|
|
14717
|
+
td: "text",
|
|
14718
|
+
caption: "text",
|
|
14719
|
+
// 行内 / 语义文本
|
|
14720
|
+
strong: "text",
|
|
14721
|
+
b: "text",
|
|
14722
|
+
em: "text",
|
|
14723
|
+
i: "text",
|
|
14724
|
+
u: "text",
|
|
14725
|
+
s: "text",
|
|
14726
|
+
small: "text",
|
|
14727
|
+
mark: "text",
|
|
14728
|
+
sub: "text",
|
|
14729
|
+
sup: "text",
|
|
14730
|
+
code: "text",
|
|
14731
|
+
pre: "text",
|
|
14732
|
+
kbd: "text",
|
|
14733
|
+
samp: "text",
|
|
14734
|
+
var: "text",
|
|
14735
|
+
abbr: "text",
|
|
14736
|
+
cite: "text",
|
|
14737
|
+
q: "text",
|
|
14738
|
+
blockquote: "view",
|
|
14739
|
+
time: "text",
|
|
14740
|
+
address: "text",
|
|
14741
|
+
// 表单控件(无对等物者映射为 view/text,交互由 picker/state 承担)
|
|
14742
|
+
select: "view",
|
|
14743
|
+
option: "view",
|
|
14744
|
+
optgroup: "view",
|
|
14745
|
+
// ★注:`label` / `audio` **不映射**——它们是微信 wxml 原生组件(表单组件/媒体组件),
|
|
14746
|
+
// 映射会把可用能力降级(p-label 的 `for` 关联、p-media 的 audio 分支都会失效;
|
|
14747
|
+
// 实测被 tests/component-b6 与 tests/p-batch3-contract 抓住)。
|
|
14748
|
+
datalist: "view",
|
|
14749
|
+
output: "text",
|
|
14750
|
+
meter: "view",
|
|
14751
|
+
progress: "progress",
|
|
14752
|
+
// 其它常见
|
|
14753
|
+
hr: "view",
|
|
14754
|
+
br: "view",
|
|
14755
|
+
picture: "image",
|
|
14756
|
+
source: "view",
|
|
14757
|
+
track: "view",
|
|
14758
|
+
iframe: "web-view"
|
|
14759
|
+
// ★注:`template` **不映射**——它在 WXML 里是定义块(is=/data=),语义与 Vue 的片段容器不同,
|
|
14760
|
+
// 属「须改写法」而非「可映射」(见第二十四节:`<template v-if>` 应改为 `<view v-if>`)。
|
|
14681
14761
|
};
|
|
14682
14762
|
var EVENT_MAP = {
|
|
14683
14763
|
click: "tap",
|
|
@@ -17043,6 +17123,99 @@ function scanWxmlPlatformIssues(wxml) {
|
|
|
17043
17123
|
seenKeys.add(key);
|
|
17044
17124
|
}
|
|
17045
17125
|
}
|
|
17126
|
+
for (const m of wxml.matchAll(/\{\{([\s\S]*?)\}\}/g)) {
|
|
17127
|
+
const expr = m[1] ?? "";
|
|
17128
|
+
if (expr.includes(String.fromCharCode(96)) || expr.includes("${")) {
|
|
17129
|
+
issues.push({
|
|
17130
|
+
code: "TemplateLiteralInExpression",
|
|
17131
|
+
message: `\u7ED1\u5B9A\u8868\u8FBE\u5F0F\u542B\u6A21\u677F\u5B57\u9762\u91CF\uFF08\u53CD\u5F15\u53F7 / \u7F8E\u5143\u5927\u62EC\u53F7\uFF09\uFF1A{{ ${expr.trim().slice(0, 60)} }}\u2014\u2014WXML \u8868\u8FBE\u5F0F\u4E0D\u652F\u6301\uFF0C\u5FAE\u4FE1\u62A5 "unexpected character inside expression"\u3002\u8BF7\u628A\u5B57\u7B26\u4E32\u62FC\u63A5\u79FB\u5230 script \u9884\u8BA1\u7B97\uFF08computed \u6216 data \u5B57\u6BB5\uFF09`,
|
|
17132
|
+
at: m.index ?? 0
|
|
17133
|
+
});
|
|
17134
|
+
}
|
|
17135
|
+
}
|
|
17136
|
+
for (const m of wxml.matchAll(/<template\b([^>]*?)>([\s\S]*?)<\/template>/g)) {
|
|
17137
|
+
const attrs = m[1] ?? "";
|
|
17138
|
+
const body = m[2] ?? "";
|
|
17139
|
+
const hasChildren = /<[a-zA-Z]/.test(body.trim());
|
|
17140
|
+
if (hasChildren && /wx:(if|elif|else|for)\b/.test(attrs)) {
|
|
17141
|
+
issues.push({
|
|
17142
|
+
code: "TemplateChildNodes",
|
|
17143
|
+
message: `<template${attrs.trim() ? " " + attrs.trim().slice(0, 40) : ""}> \u542B\u5B50\u5143\u7D20\u2014\u2014WXML \u7684 <template> \u662F\u5B9A\u4E49\u5757\uFF08is=/data=\uFF09\uFF0C\u4E0D\u662F Vue \u7684\u7247\u6BB5\u5BB9\u5668\uFF08\u5FAE\u4FE1\u62A5 "child nodes are not allowed"/"missing module name"\uFF09\u3002\u8BF7\u6539\u7528 <view wx:if>`,
|
|
17144
|
+
at: m.index ?? 0
|
|
17145
|
+
});
|
|
17146
|
+
}
|
|
17147
|
+
}
|
|
17148
|
+
const KNOWN_HTML_TAGS = /* @__PURE__ */ new Set([
|
|
17149
|
+
"section",
|
|
17150
|
+
"article",
|
|
17151
|
+
"aside",
|
|
17152
|
+
"nav",
|
|
17153
|
+
"main",
|
|
17154
|
+
"header",
|
|
17155
|
+
"footer",
|
|
17156
|
+
"figure",
|
|
17157
|
+
"figcaption",
|
|
17158
|
+
"details",
|
|
17159
|
+
"summary",
|
|
17160
|
+
"dialog",
|
|
17161
|
+
"fieldset",
|
|
17162
|
+
"legend",
|
|
17163
|
+
"ul",
|
|
17164
|
+
"ol",
|
|
17165
|
+
"li",
|
|
17166
|
+
"dl",
|
|
17167
|
+
"dt",
|
|
17168
|
+
"dd",
|
|
17169
|
+
"table",
|
|
17170
|
+
"thead",
|
|
17171
|
+
"tbody",
|
|
17172
|
+
"tfoot",
|
|
17173
|
+
"tr",
|
|
17174
|
+
"th",
|
|
17175
|
+
"td",
|
|
17176
|
+
"caption",
|
|
17177
|
+
"strong",
|
|
17178
|
+
"b",
|
|
17179
|
+
"em",
|
|
17180
|
+
"i",
|
|
17181
|
+
"u",
|
|
17182
|
+
"s",
|
|
17183
|
+
"small",
|
|
17184
|
+
"mark",
|
|
17185
|
+
"sub",
|
|
17186
|
+
"sup",
|
|
17187
|
+
"code",
|
|
17188
|
+
"pre",
|
|
17189
|
+
"kbd",
|
|
17190
|
+
"samp",
|
|
17191
|
+
"var",
|
|
17192
|
+
"abbr",
|
|
17193
|
+
"cite",
|
|
17194
|
+
"q",
|
|
17195
|
+
"blockquote",
|
|
17196
|
+
"time",
|
|
17197
|
+
"address",
|
|
17198
|
+
"select",
|
|
17199
|
+
"option",
|
|
17200
|
+
"optgroup",
|
|
17201
|
+
"datalist",
|
|
17202
|
+
"output",
|
|
17203
|
+
"meter",
|
|
17204
|
+
"hr",
|
|
17205
|
+
"br",
|
|
17206
|
+
"picture",
|
|
17207
|
+
"source",
|
|
17208
|
+
"track",
|
|
17209
|
+
"iframe"
|
|
17210
|
+
]);
|
|
17211
|
+
for (const tag of scanOpenTags(wxml)) {
|
|
17212
|
+
if (!KNOWN_HTML_TAGS.has(tag.name)) continue;
|
|
17213
|
+
issues.push({
|
|
17214
|
+
code: "UnknownHtmlTag",
|
|
17215
|
+
message: `\u6807\u7B7E <${tag.name}> \u662F HTML \u6807\u7B7E\u3001\u5FAE\u4FE1 wxml \u65E0\u6B64\u539F\u751F\u6807\u7B7E\u2014\u2014\u672A\u88AB\u6620\u5C04\uFF08TAG_MAP \u9057\u6F0F\uFF09\u800C\u539F\u6837\u8FDB\u4EA7\u7269\uFF0C\u5FAE\u4FE1\u7F16\u8BD1\u4F1A\u5931\u8D25\u6216\u6E32\u67D3\u5F02\u5E38\u3002\u8BF7\u6539\u7528 WXML \u7B49\u4EF7\u7ED3\u6784\uFF08\u5757\u7EA7 \u2192 <view>\u3001\u6587\u672C\u7C7B \u2192 <text>\uFF09`,
|
|
17216
|
+
at: tag.at
|
|
17217
|
+
});
|
|
17218
|
+
}
|
|
17046
17219
|
return issues;
|
|
17047
17220
|
}
|
|
17048
17221
|
function splitStyleDecls(styleVal) {
|
|
@@ -21968,7 +22141,16 @@ function transformScriptToPage(source, _opts = { px2rpx: true, rpxRatio: 2 }, ex
|
|
|
21968
22141
|
}
|
|
21969
22142
|
for (const ni of reactiveInits) dataExtra[ni.name] = null;
|
|
21970
22143
|
const storeBindings = extra.storeBindings ?? [];
|
|
21971
|
-
const
|
|
22144
|
+
const storeCandidates = runtimeInits.filter((i) => /^use\w*Store\(/.test(i.call));
|
|
22145
|
+
const strict = storeCandidates.find((i) => i.name === "store");
|
|
22146
|
+
const storeVar = strict?.name ?? (storeCandidates.length === 1 ? storeCandidates[0].name : void 0);
|
|
22147
|
+
if (storeBindings.length && !storeVar) {
|
|
22148
|
+
warnings.push(
|
|
22149
|
+
`\u6A21\u677F\u5F15\u7528\u4E86 store \u5B57\u6BB5\uFF08${storeBindings.join(" / ")}\uFF09\uFF0C\u4F46\u672A\u80FD\u8BC6\u522B\u51FA store \u53D8\u91CF\u2014\u2014MP \u7AEF\u7ED1\u5B9A\u4E0D\u4F1A\u751F\u6548\uFF08\u6784\u5EFA\u901A\u8FC7\u4F46\u771F\u673A\u53D6\u4E0D\u5230\u503C\uFF09\u3002
|
|
22150
|
+
\u8BC6\u522B\u8981\u6C42\uFF1A\u2460 \u53D8\u91CF\u58F0\u660E\u4E3A \`const store = useXxxStore()\`\uFF08\u53D8\u91CF\u540D\u987B\u4E3A store\uFF09\uFF0C\u6216 \u2461 \u672C\u6587\u4EF6**\u53EA\u6709\u4E00\u4E2A** \`useXxxStore()\` \u8C03\u7528\u3002
|
|
22151
|
+
\u5F53\u524D\u672A\u6EE1\u8DB3${storeCandidates.length > 1 ? `\uFF08\u68C0\u6D4B\u5230\u591A\u4E2A useXxxStore()\uFF1A${storeCandidates.map((i) => i.name).join(" / ")}\u2014\u2014\u8BF7\u628A\u7528\u4E8E\u6A21\u677F\u7ED1\u5B9A\u7684\u90A3\u4E2A\u547D\u540D\u4E3A store\uFF09` : "\uFF08\u672A\u68C0\u6D4B\u5230\u4EFB\u4F55 useXxxStore() \u5F62\u6001\u7684\u8C03\u7528\uFF09"}\u3002`
|
|
22152
|
+
);
|
|
22153
|
+
}
|
|
21972
22154
|
const storeBindingInit = storeVar && storeBindings.length ? storeBindingLine(storeBindings, storeVar) : "";
|
|
21973
22155
|
if (storeBindingInit) {
|
|
21974
22156
|
trace?.add("script/store-binding", {
|
package/dist/validate.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export declare function validateWxml(wxml: string): {
|
|
|
34
34
|
export declare function assertValidResult(result: CompileResult, filename: string): void;
|
|
35
35
|
/** 单条 wxml 平台违规(code = 官方 ParseErrorKind 蓝本) */
|
|
36
36
|
export interface WxmlPlatformIssue {
|
|
37
|
-
code: 'DataBindingNotAllowed' | 'DuplicatedAttribute' | 'AvoidUppercaseLetters' | 'UnsupportedSyntax' | 'InvalidAttribute' | 'DuplicatedStylePropertyNames';
|
|
37
|
+
code: 'DataBindingNotAllowed' | 'DuplicatedAttribute' | 'AvoidUppercaseLetters' | 'UnsupportedSyntax' | 'InvalidAttribute' | 'DuplicatedStylePropertyNames' | 'TemplateLiteralInExpression' | 'TemplateChildNodes' | 'UnknownHtmlTag';
|
|
38
38
|
message: string;
|
|
39
39
|
/** wxml 字符偏移(定位用) */
|
|
40
40
|
at: number;
|