mta-mcp 3.16.0 → 3.16.1
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/agents/flutter.agent.md
CHANGED
|
@@ -36,16 +36,18 @@
|
|
|
36
36
|
5. 只有当 compact 无法解释局部布局/样式时,再补用 measure/style
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
### 图标资产强制规则(v4.
|
|
39
|
+
### 图标资产强制规则(v4.8.0 更新)
|
|
40
40
|
|
|
41
41
|
- 默认流程改为:**先在 `assets/icons/` 查找用户手工导出的图标 PNG**,文件名优先匹配设计稿图层名对应的 `*_icon@4x.png`,找到即直接复用。
|
|
42
42
|
- 先看测量结果里的图层类型:`icon/svg` 才允许落地为 SVG;如果 Sketch 返回的是 `Image`,禁止伪造 SVG。
|
|
43
43
|
- `Image` 类型的 icon/button/arrow/help/customer-service 图层,优先做 **精确文件名查找**,不要先做语义联想或 canonical 合并。
|
|
44
44
|
- `Help Button`、`Customer Service Button`、`Customer Service Icon` 不能只因为位置相近就合并成同一个语义;先按 Sketch 图层名区分资产,再决定是否复用。
|
|
45
|
+
- 如果 `restorationContract.blockOrder` 中的顶部入口测得是 `Image`,回复里必须明确写出:测得的真实块名、最终采用的 assetPath、以及它来自 `bitmapLookupCandidates` 还是 canonical 副本;未确认前禁止继续猜图标。
|
|
45
46
|
- 只有当 `assets/icons/` 中不存在对应的手工导出资源时,才允许提示用户补导;不要再优先产出 page-local PNG 副本。
|
|
46
47
|
- 手工 `*_icon@4x.png` 约定下,默认不再强制要求补齐 `2.0x/3.0x`;只有旧位图流程才继续要求多倍率变体。
|
|
47
48
|
- 已存在但内容损坏的 SVG 视为无效资产,必须修复或替换;禁止为了绕过损坏文件再平行创建第二个语义相同的新图标。
|
|
48
49
|
- 设计源是 `Image` 时,回复里必须明确说明“来源优先是 assets/icons 下的手工导出 PNG,不是设计稿原生 SVG”,避免误报为高清 SVG。
|
|
50
|
+
- 若 `bitmapLookupCandidates` 与代码实际资产名都未命中,必须停止并说明“设计资产未确认”,而不是回退到 help/customer-service 等语义相近资源。
|
|
49
51
|
|
|
50
52
|
**注意:**
|
|
51
53
|
- 不要手动读取 artboard-measure.js(已废弃,合并进 sketch-tools.js)
|
package/dist/index.js
CHANGED
|
@@ -6406,7 +6406,7 @@ var OUTPUT_GUIDE = {
|
|
|
6406
6406
|
"- **rp**: [left,top,right,bottom] \u76F8\u5BF9\u7236\u5BB9\u5668\u8FB9\u8DDD",
|
|
6407
6407
|
"- **vf**: [x,y,w,h] \u89C6\u89C9\u8FB9\u754C\uFF1B\u5F53\u80CC\u666F\u5C42/\u9634\u5F71\u8D85\u51FA\u7236 Group frame \u65F6\uFF0C\u5BB9\u5668\u5C3A\u5BF8\u548C\u89C6\u89C9\u5E95\u8FB9\u8DDD\u4F18\u5148\u770B vf",
|
|
6408
6408
|
"- **icon/svg/cs/xs**: \u56FE\u6807\u6807\u8BC6/\u771F\u5B9E SvgPicture.string(...) \u4EE3\u7801/containerSize/contentSize",
|
|
6409
|
-
"- **image/img/bitmapPath/bitmapScales/bitmapLookupCandidates**: \u4F4D\u56FE\u56FE\u5C42\u6807\u8BC6/Image.asset \u4EE3\u7801/\u5EFA\u8BAE\u843D\u76D8\u8DEF\u5F84/\u5BFC\u51FA\u7EA6\u5B9A/\u4F18\u5148\u641C\u7D22\u7684\u624B\u5DE5\u56FE\u6807\u6587\u4EF6\u540D",
|
|
6409
|
+
"- **image/img/bitmapPath/bitmapScales/bitmapLookupCandidates/bitmapReuseMode**: \u4F4D\u56FE\u56FE\u5C42\u6807\u8BC6/Image.asset \u4EE3\u7801/\u5EFA\u8BAE\u843D\u76D8\u8DEF\u5F84/\u5BFC\u51FA\u7EA6\u5B9A/\u4F18\u5148\u641C\u7D22\u7684\u624B\u5DE5\u56FE\u6807\u6587\u4EF6\u540D/\u662F\u5426 shared-canonical",
|
|
6410
6410
|
"- **svgMode/svgReason/svgFile**: preserve|tint / \u989C\u8272\u7B56\u7565\u539F\u56E0 / \u5EFA\u8BAE\u843D\u76D8\u6587\u4EF6\u540D",
|
|
6411
6411
|
"- **text/style/family/textHeight**: \u6587\u672C\u5185\u5BB9/\u5B8C\u6574 TextStyle/\u5B57\u4F53\u65CF/\u884C\u9AD8\u6BD4",
|
|
6412
6412
|
"- **lh/strut**: strutHeight / \u5B8C\u6574 StrutStyle(...)",
|
|
@@ -6423,7 +6423,8 @@ var OUTPUT_GUIDE = {
|
|
|
6423
6423
|
"- \u56FE\u6807\u662F\u5426\u8BEF\u7528\u65E7\u9875\u9762\u8D44\u4EA7\uFF1A\u540C\u540D\u7BAD\u5934/\u56FE\u6807\u9ED8\u8BA4\u4E0D\u53EF\u4FE1\uFF0C\u5148\u6838\u5BF9\u6765\u6E90\u56FE\u5C42",
|
|
6424
6424
|
"- SVG \u662F\u5426\u8BEF\u52A0 ColorFilter\uFF1A\u4FDD\u7559\u539F\u8272\u7684 SVG \u4E0D\u5F97\u4E8C\u6B21\u67D3\u8272",
|
|
6425
6425
|
"- \u56FE\u6807\u662F\u5426\u7528\u9519\u5C3A\u5BF8\uFF1A16x16 \u69FD\u4F4D\u4E0D\u7B49\u4E8E 16x16 \u56FE\u5F62\uFF0C\u6309 xs/cs \u5206\u79BB\u5360\u4F4D\u4E0E\u6E32\u67D3",
|
|
6426
|
-
"- Bitmap \u662F\u5426\u8BEF\u5F53 SVG\uFF1ASketch Image \u56FE\u5C42\u5FC5\u987B\u4F18\u5148\u5728 assets/icons/ \u4E2D\u67E5\u627E\
|
|
6426
|
+
"- Bitmap \u662F\u5426\u8BEF\u5F53 SVG\uFF1ASketch Image \u56FE\u5C42\u5FC5\u987B\u4F18\u5148\u5728 assets/icons/ \u4E2D\u67E5\u627E\u8BBE\u8BA1\u539F\u540D\u6216 bitmapLookupCandidates \u6307\u5411\u7684\u4F4D\u56FE\uFF0C\u547D\u4E2D\u540E\u76F4\u63A5\u590D\u7528\uFF0C\u4E0D\u518D\u4F2A\u9020 SVG",
|
|
6427
|
+
"- \u9876\u90E8 Help/Customer Service/Support Entry \u82E5\u5728 blockOrder \u4E2D\u662F Image\uFF0C\u5FC5\u987B\u5148\u6309\u771F\u5B9E\u5757\u540D\u548C bitmapLookupCandidates \u590D\u7528\uFF0C\u4E0D\u5F97\u7528\u8BED\u4E49\u76F8\u8FD1\u6309\u94AE\u66FF\u4EE3",
|
|
6427
6428
|
"- \u5168\u5C4F app \u9875\u9762\u5728\u5BBD\u5C4F\u5E94\u8DDF\u968F\u5BBF\u4E3B Scaffold/SafeArea/AppBar \u548C\u9875\u9762 padding\uFF0C\u7981\u6B62\u628A\u6574\u9875\u9501\u6210 390 \u753B\u677F\u58F3\u5B50",
|
|
6428
6429
|
"- Sketch \u9876\u90E8\u65F6\u95F4/\u4FE1\u53F7/WiFi/\u7535\u6C60\u5C5E\u4E8E\u8BBE\u5907\u7CFB\u7EDF chrome\uFF0C\u4E0D\u5C5E\u4E8E\u9875\u9762\u4E1A\u52A1 UI\uFF0C\u7981\u6B62\u76F4\u63A5\u8FD8\u539F\u5230 Flutter \u9875\u9762",
|
|
6429
6430
|
"- \u82E5\u8282\u70B9\u540C\u65F6\u7ED9\u51FA f \u4E0E vf\uFF0C\u8BF4\u660E\u80CC\u666F\u5C42/\u9634\u5F71\u8D85\u51FA\u903B\u8F91 frame\uFF1B\u5BB9\u5668\u5C3A\u5BF8\u548C\u5E95\u90E8\u89C6\u89C9\u95F4\u8DDD\u4F18\u5148\u4F7F\u7528 vf",
|
|
@@ -6527,14 +6528,15 @@ async function sketchMeasure(args) {
|
|
|
6527
6528
|
scriptPath: tempScriptPath,
|
|
6528
6529
|
scriptLength: fullScript.length,
|
|
6529
6530
|
pluginInstall: installStatus,
|
|
6530
|
-
instruction: "\u5C06 loaderScript \u4F20\u5165 mcp_sketch_run_code({ code: loaderScript }) \u6267\u884C\u3002\u8BBE\u8BA1\u7A3F\u8FD8\u539F\u9996\u8F6E\u4F18\u5148\u4F7F\u7528 cmd=compact\uFF1B\u53EA\u6709\u5F53 compact contract \u4E0D\u8DB3\u4EE5\u89E3\u91CA\u5C40\u90E8\u5E03\u5C40\u6216\u6837\u5F0F\u65F6\uFF0C\u518D\u8865\u7528 measure/style\u3002\u82E5\u504F\u5DEE\u96C6\u4E2D\u5728\u5355\u4E2A icon/svg/bitmap\uFF0C\u8BF7\u5148\u5728 assets/icons/ \u4E2D\u6309\u8BBE\u8BA1\u7A3F\u56FE\u5C42\u540D\u67E5\u627E\
|
|
6531
|
+
instruction: "\u5C06 loaderScript \u4F20\u5165 mcp_sketch_run_code({ code: loaderScript }) \u6267\u884C\u3002\u8BBE\u8BA1\u7A3F\u8FD8\u539F\u9996\u8F6E\u4F18\u5148\u4F7F\u7528 cmd=compact\uFF1B\u53EA\u6709\u5F53 compact contract \u4E0D\u8DB3\u4EE5\u89E3\u91CA\u5C40\u90E8\u5E03\u5C40\u6216\u6837\u5F0F\u65F6\uFF0C\u518D\u8865\u7528 measure/style\u3002\u82E5\u504F\u5DEE\u96C6\u4E2D\u5728\u5355\u4E2A icon/svg/bitmap\uFF0C\u8BF7\u5148\u5728 assets/icons/ \u4E2D\u6309\u8BBE\u8BA1\u7A3F\u56FE\u5C42\u540D\u3001bitmapLookupCandidates \u548C bitmapReuseMode \u67E5\u627E\u771F\u5B9E\u4F4D\u56FE\u6216\u89C4\u8303\u5316\u526F\u672C\uFF0C\u907F\u514D\u7EE7\u7EED\u63A8\u65AD\u65E7\u9875\u9762\u8D44\u4EA7\u6216\u4F2A\u9020 SVG\u3002\u9876\u90E8 Help/Customer Service/Support Entry \u82E5 blockOrder \u6807\u8BB0\u4E3A Image\uFF0C\u5FC5\u987B\u5148\u590D\u7528\u5BF9\u5E94\u4F4D\u56FE\uFF0C\u672A\u547D\u4E2D\u65F6\u5E94\u505C\u6B62\u731C\u6D4B\u3002\u5168\u5C4F app \u9875\u9762\u5728\u5BBD\u5C4F\u5E94\u8DDF\u968F\u5BBF\u4E3B Scaffold/SafeArea/AppBar \u548C\u9875\u9762 padding \u9002\u914D\uFF1BSketch \u9876\u90E8\u65F6\u95F4/\u4FE1\u53F7/WiFi/\u7535\u6C60\u5C5E\u4E8E\u8BBE\u5907\u7CFB\u7EDF chrome\uFF0C\u7981\u6B62\u76F4\u63A5\u8FD8\u539F\u5230 Flutter \u9875\u9762\u3002compact \u82E5\u68C0\u6D4B\u5230\u4F60\u9009\u4E2D\u7684\u662F\u5185\u5C42 glyph\uFF0C\u4F1A\u81EA\u52A8\u63D0\u5347\u5230\u6240\u5C5E\u753B\u677F\u5E76\u901A\u8FC7 selectionContext \u56DE\u62A5\u3002\u8BF7\u5148\u5728 Sketch \u4E2D\u9009\u4E2D\u76EE\u6807\u753B\u677F/\u56FE\u5C42\u3002",
|
|
6531
6532
|
measureOutputPath,
|
|
6532
6533
|
restoreChecklist: [
|
|
6533
6534
|
"\u5148\u6309 restorationContract \u9501\u5B9A\u9875\u9762\u9AA8\u67B6\uFF0C\u518D\u5904\u7406\u5C40\u90E8\u6837\u5F0F",
|
|
6534
|
-
"\u5355\u4E2A\u56FE\u6807\u504F\u5DEE\u5148\u67E5 assets/icons/ \u4E2D\u8BBE\u8BA1\u7A3F\u540C\u540D
|
|
6535
|
+
"\u5355\u4E2A\u56FE\u6807\u504F\u5DEE\u5148\u67E5 assets/icons/ \u4E2D\u8BBE\u8BA1\u7A3F\u540C\u540D\u3001bitmapLookupCandidates \u5217\u51FA\u7684\u771F\u5B9E\u4F4D\u56FE\uFF0C\u518D\u51B3\u5B9A\u662F\u5426\u8865\u5BFC",
|
|
6535
6536
|
"preserve \u6A21\u5F0F SVG \u7981\u6B62\u8FFD\u52A0 ColorFilter",
|
|
6536
6537
|
"16x16 \u69FD\u4F4D\u4E0E 6x8/12x12 \u56FE\u5F62\u8981\u5206\u5F00\u5904\u7406",
|
|
6537
|
-
"Sketch Image \u56FE\u5C42\u4F18\u5148\u590D\u7528 assets/icons
|
|
6538
|
+
"Sketch Image \u56FE\u5C42\u4F18\u5148\u590D\u7528 assets/icons \u4E2D\u6309\u56FE\u5C42\u539F\u540D\u5BFC\u51FA\u7684\u4F4D\u56FE\u6216 bitmapLookupCandidates \u547D\u4E2D\u7684\u8D44\u6E90\uFF0C\u4E0D\u8981\u4F2A\u88C5\u6210 SVG\uFF1B\u53EA\u6709\u65E7\u4F4D\u56FE\u6D41\u7A0B\u624D\u8865 2.0x/3.0x",
|
|
6539
|
+
"\u9876\u90E8 Help/Customer Service/Support Entry \u82E5\u6D4B\u5F97\u4E3A Image\uFF0C\u7981\u6B62\u7528\u8BED\u4E49\u76F8\u8FD1\u7684\u5176\u4ED6\u6309\u94AE\u4F4D\u56FE\u6216 help glyph \u66FF\u4EE3",
|
|
6538
6540
|
"\u5168\u5C4F app \u9875\u9762\u5728\u5BBD\u5C4F\u5E94\u8DDF\u968F\u5BBF\u4E3B Scaffold/SafeArea/AppBar \u548C\u9875\u9762 padding\uFF0C\u53EA\u6709\u660E\u786E\u6D4B\u5F97\u7684\u5C40\u90E8\u6D6E\u5C42/\u5361\u7247\u5BB9\u5668\u624D\u505A clamp",
|
|
6539
6541
|
"Sketch \u9876\u90E8\u65F6\u95F4/\u4FE1\u53F7/WiFi/\u7535\u6C60\u5C5E\u4E8E\u8BBE\u5907\u7CFB\u7EDF chrome\uFF0C\u4E0D\u5C5E\u4E8E\u9875\u9762\u4E1A\u52A1 UI\uFF0C\u7981\u6B62\u76F4\u63A5\u8FD8\u539F\u5230 Flutter \u9875\u9762",
|
|
6540
6542
|
"\u82E5\u8282\u70B9\u540C\u65F6\u51FA\u73B0 f \u4E0E vf\uFF0C\u5BB9\u5668\u5C3A\u5BF8\u548C\u5E95\u90E8\u89C6\u89C9\u95F4\u8DDD\u4F18\u5148\u4F7F\u7528 vf\uFF0C\u4E0D\u8981\u53EA\u6284\u903B\u8F91 frame",
|
|
@@ -6630,6 +6632,9 @@ function loadMeasurePayload(args) {
|
|
|
6630
6632
|
}
|
|
6631
6633
|
return parsed;
|
|
6632
6634
|
}
|
|
6635
|
+
function normalizeSemanticKey(value) {
|
|
6636
|
+
return value.replace(/[\s_-]+/g, "").toLowerCase();
|
|
6637
|
+
}
|
|
6633
6638
|
function hasAnyPattern(source, patterns) {
|
|
6634
6639
|
return patterns.some((pattern) => pattern.test(source));
|
|
6635
6640
|
}
|
|
@@ -6653,6 +6658,7 @@ function collectAssetContracts(node, bucket = []) {
|
|
|
6653
6658
|
fileName: typeof node.bitmapFile === "string" ? path20.posix.basename(node.bitmapFile) : typeof node.bitmapPath === "string" ? path20.posix.basename(node.bitmapPath) : void 0,
|
|
6654
6659
|
sourceType: "bitmap",
|
|
6655
6660
|
scaleVariants: node.bitmapScales,
|
|
6661
|
+
lookupCandidates: node.bitmapLookupCandidates,
|
|
6656
6662
|
reuseMode: node.bitmapReuseMode,
|
|
6657
6663
|
reuseKey: node.bitmapReuseKey
|
|
6658
6664
|
});
|
|
@@ -6669,6 +6675,37 @@ function extractCodeAssets(codeContent) {
|
|
|
6669
6675
|
function isManualExport4xBitmapAsset(assetPath) {
|
|
6670
6676
|
return /_icon@4x\.(png|jpg|jpeg|webp)$/i.test(path20.posix.basename(assetPath));
|
|
6671
6677
|
}
|
|
6678
|
+
function isCriticalBitmapEntryName(name) {
|
|
6679
|
+
return /help[_ -]?button|customer[_ -]?service(?:[_ -]?(button|icon))?|support(?:[_ -]?entry)?|帮助|客服/i.test(name);
|
|
6680
|
+
}
|
|
6681
|
+
function buildBitmapCandidateSet(contract) {
|
|
6682
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
6683
|
+
if (contract.fileName) {
|
|
6684
|
+
candidates.add(path20.posix.basename(contract.fileName).toLowerCase());
|
|
6685
|
+
}
|
|
6686
|
+
for (const candidate of contract.lookupCandidates || []) {
|
|
6687
|
+
candidates.add(path20.posix.basename(candidate).toLowerCase());
|
|
6688
|
+
}
|
|
6689
|
+
return candidates;
|
|
6690
|
+
}
|
|
6691
|
+
function collectCriticalBitmapContracts(payload, assetContracts) {
|
|
6692
|
+
var _a;
|
|
6693
|
+
const criticalBitmapKeys = new Set(
|
|
6694
|
+
(((_a = payload.restorationContract) == null ? void 0 : _a.blockOrder) || []).flatMap((block) => {
|
|
6695
|
+
const blockIdentity = `${block.name || ""} ${block.label || ""}`;
|
|
6696
|
+
if (block.type !== "Image" || !isCriticalBitmapEntryName(blockIdentity)) {
|
|
6697
|
+
return [];
|
|
6698
|
+
}
|
|
6699
|
+
return [block.name, block.label].filter((value) => typeof value === "string" && value.trim().length > 0).map((value) => normalizeSemanticKey(value));
|
|
6700
|
+
})
|
|
6701
|
+
);
|
|
6702
|
+
if (criticalBitmapKeys.size === 0) {
|
|
6703
|
+
return [];
|
|
6704
|
+
}
|
|
6705
|
+
return assetContracts.filter(
|
|
6706
|
+
(contract) => contract.sourceType === "bitmap" && criticalBitmapKeys.has(normalizeSemanticKey(contract.sketchName))
|
|
6707
|
+
);
|
|
6708
|
+
}
|
|
6672
6709
|
function hasCodePropertyLiteral(codeContent, property, value) {
|
|
6673
6710
|
const escapedValue = String(value).replace(".", "\\.");
|
|
6674
6711
|
return new RegExp(`${property}\\s*:\\s*${escapedValue}(?:\\.0+)?\\b`).test(codeContent);
|
|
@@ -6867,6 +6904,7 @@ function buildContractValidator(payload, codeContent) {
|
|
|
6867
6904
|
function buildAssetValidator(payload, codeContent, args) {
|
|
6868
6905
|
const findings = [];
|
|
6869
6906
|
const assetContracts = collectAssetContracts(payload.tree);
|
|
6907
|
+
const criticalBitmapContracts = collectCriticalBitmapContracts(payload, assetContracts);
|
|
6870
6908
|
const expectedVectorFiles = new Set(
|
|
6871
6909
|
assetContracts.filter((item) => item.sourceType === "vector" && item.fileName).map((item) => item.fileName.toLowerCase())
|
|
6872
6910
|
);
|
|
@@ -6874,6 +6912,9 @@ function buildAssetValidator(payload, codeContent, args) {
|
|
|
6874
6912
|
const codeAssets = extractCodeAssets(codeContent);
|
|
6875
6913
|
const codeVectorAssets = codeAssets.filter((asset) => asset.endsWith(".svg"));
|
|
6876
6914
|
const codeBitmapAssets = codeAssets.filter((asset) => /\.(png|jpg|jpeg|webp)$/.test(asset));
|
|
6915
|
+
const codeBitmapFileNames = new Set(
|
|
6916
|
+
codeBitmapAssets.map((asset) => path20.posix.basename(asset).toLowerCase())
|
|
6917
|
+
);
|
|
6877
6918
|
const unexpectedVectorAssets = codeVectorAssets.filter((asset) => !expectedVectorFiles.has(path20.posix.basename(asset).toLowerCase()));
|
|
6878
6919
|
if (unexpectedVectorAssets.length > 0) {
|
|
6879
6920
|
findings.push({
|
|
@@ -6887,11 +6928,27 @@ function buildAssetValidator(payload, codeContent, args) {
|
|
|
6887
6928
|
if (expectedBitmapCount > 0 && codeBitmapAssets.length === 0) {
|
|
6888
6929
|
findings.push({
|
|
6889
6930
|
id: "missing_bitmap_assets",
|
|
6890
|
-
severity: "warning",
|
|
6891
|
-
message: `\u5F53\u524D\u8BBE\u8BA1\u7A3F\u5305\u542B ${expectedBitmapCount} \u4E2A Image \u56FE\u5C42\uFF0C\u4F46\u4EE3\u7801\u91CC\u6CA1\u6709\u4EFB\u4F55\u4F4D\u56FE\u8D44\u6E90\u5F15\u7528\u3002`,
|
|
6892
|
-
suggestion: "\u68C0\u67E5\u662F\u5426\u628A Sketch Image \u56FE\u5C42\u9519\u8BEF\u5F53\u6210 SVG \u6216\u4EE3\u7801\u7ED8\u5236\u4E86\u3002"
|
|
6931
|
+
severity: criticalBitmapContracts.length > 0 ? "error" : "warning",
|
|
6932
|
+
message: criticalBitmapContracts.length > 0 ? `\u5F53\u524D\u8BBE\u8BA1\u7A3F\u5305\u542B ${expectedBitmapCount} \u4E2A Image \u56FE\u5C42\uFF0C\u4E14\u5173\u952E\u5165\u53E3\u4F4D\u56FE\u4E0D\u80FD\u88AB\u8BED\u4E49\u76F8\u8FD1\u7684 SVG/\u81EA\u7ED8\u5B9E\u73B0\u66FF\u4EE3\uFF0C\u4F46\u4EE3\u7801\u91CC\u6CA1\u6709\u4EFB\u4F55\u4F4D\u56FE\u8D44\u6E90\u5F15\u7528\u3002` : `\u5F53\u524D\u8BBE\u8BA1\u7A3F\u5305\u542B ${expectedBitmapCount} \u4E2A Image \u56FE\u5C42\uFF0C\u4F46\u4EE3\u7801\u91CC\u6CA1\u6709\u4EFB\u4F55\u4F4D\u56FE\u8D44\u6E90\u5F15\u7528\u3002`,
|
|
6933
|
+
suggestion: criticalBitmapContracts.length > 0 ? "\u5173\u952E\u5165\u53E3\u7C7B Image block \u5FC5\u987B\u5148\u6309\u8BBE\u8BA1\u56FE\u5C42\u540D\u548C bitmapLookupCandidates \u590D\u7528\u771F\u5B9E\u4F4D\u56FE\uFF1B\u4E0D\u8981\u518D\u628A Help / Customer Service / Support Entry \u753B\u6210\u81EA\u5B9A\u4E49 SVG \u6216\u58F3\u5B50\u7EC4\u4EF6\u3002" : "\u68C0\u67E5\u662F\u5426\u628A Sketch Image \u56FE\u5C42\u9519\u8BEF\u5F53\u6210 SVG \u6216\u4EE3\u7801\u7ED8\u5236\u4E86\u3002"
|
|
6893
6934
|
});
|
|
6894
6935
|
}
|
|
6936
|
+
if (criticalBitmapContracts.length > 0 && codeBitmapAssets.length > 0) {
|
|
6937
|
+
const mismatchedCriticalBitmapEntries = criticalBitmapContracts.map((contract) => {
|
|
6938
|
+
const candidateSet = buildBitmapCandidateSet(contract);
|
|
6939
|
+
const matched = [...codeBitmapFileNames].some((fileName) => candidateSet.has(fileName));
|
|
6940
|
+
return matched ? null : `${contract.sketchName} -> expected one of ${[...candidateSet].join(", ")}`;
|
|
6941
|
+
}).filter((item) => item !== null);
|
|
6942
|
+
if (mismatchedCriticalBitmapEntries.length > 0) {
|
|
6943
|
+
findings.push({
|
|
6944
|
+
id: "critical_bitmap_entry_not_reused",
|
|
6945
|
+
severity: "error",
|
|
6946
|
+
message: "\u5173\u952E Image \u5165\u53E3\u6CA1\u6709\u590D\u7528\u8BBE\u8BA1\u6E90\u4F4D\u56FE\uFF0C\u5B58\u5728\u628A Help / Customer Service \u7B49\u8BED\u4E49\u76F8\u8FD1\u56FE\u6807\u4E92\u6362\u7684\u98CE\u9669\u3002",
|
|
6947
|
+
evidence: mismatchedCriticalBitmapEntries,
|
|
6948
|
+
suggestion: "\u5148\u5BF9\u7167 restorationContract.blockOrder \u4E2D\u7684\u771F\u5B9E\u5757\u540D\uFF0C\u518D\u6309 bitmapLookupCandidates \u6216 canonical \u6587\u4EF6\u540D\u590D\u7528\u4F4D\u56FE\uFF1B\u672A\u547D\u4E2D\u65F6\u5E94\u505C\u6B62\u731C\u6D4B\u5E76\u8981\u6C42\u91CD\u65B0\u786E\u8BA4\u8BBE\u8BA1\u5BFC\u51FA\u3002"
|
|
6949
|
+
});
|
|
6950
|
+
}
|
|
6951
|
+
}
|
|
6895
6952
|
if (codeBitmapAssets.length > 0) {
|
|
6896
6953
|
findings.push({
|
|
6897
6954
|
id: "bitmap_asset_source_check_required",
|