mta-mcp 3.15.2 → 3.15.4
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
CHANGED
|
@@ -6403,13 +6403,17 @@ var OUTPUT_GUIDE = {
|
|
|
6403
6403
|
"- **token**: AppShadows.xxx token \u540D\uFF0C\u4F18\u5148\u4F7F\u7528\u4EE3\u66FF\u786C\u7F16\u7801 BoxShadow",
|
|
6404
6404
|
"- **r**: borderRadius \u6570\u503C",
|
|
6405
6405
|
"- **rp**: [left,top,right,bottom] \u76F8\u5BF9\u7236\u5BB9\u5668\u8FB9\u8DDD",
|
|
6406
|
+
"- **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",
|
|
6406
6407
|
"- **icon/svg/cs/xs**: \u56FE\u6807\u6807\u8BC6/\u771F\u5B9E SvgPicture.string(...) \u4EE3\u7801/containerSize/contentSize",
|
|
6408
|
+
"- **image/img/bitmapPath/bitmapScales**: \u4F4D\u56FE\u56FE\u5C42\u6807\u8BC6/Image.asset \u4EE3\u7801/\u5EFA\u8BAE\u843D\u76D8\u8DEF\u5F84/1x-3x \u5BFC\u51FA\u8981\u6C42",
|
|
6407
6409
|
"- **svgMode/svgReason/svgFile**: preserve|tint / \u989C\u8272\u7B56\u7565\u539F\u56E0 / \u5EFA\u8BAE\u843D\u76D8\u6587\u4EF6\u540D",
|
|
6408
6410
|
"- **text/style/family/textHeight**: \u6587\u672C\u5185\u5BB9/\u5B8C\u6574 TextStyle/\u5B57\u4F53\u65CF/\u884C\u9AD8\u6BD4",
|
|
6409
6411
|
"- **lh/strut**: strutHeight / \u5B8C\u6574 StrutStyle(...)",
|
|
6410
6412
|
"- **tag**: {bg,ph,pv,r,text} Tag\u5BB9\u5668\u4FE1\u606F",
|
|
6411
6413
|
"- **layout**: {dir,gap,main,cross,pad} \u5E03\u5C40\u610F\u56FE",
|
|
6412
6414
|
"- **ch**: \u5B50\u5143\u7D20\u6570\u7EC4\uFF08\u9012\u5F52\uFF09",
|
|
6415
|
+
"- **designSurface**: {width,height,maxWidth,wideScreenRule} \u8BBE\u8BA1\u753B\u677F\u7EA6\u675F\uFF1B\u79FB\u52A8\u7AEF\u7A84\u753B\u677F\u5728\u5BBD\u5C4F\u5FC5\u987B\u505A\u5C45\u4E2D\u5939\u6301",
|
|
6416
|
+
"- **selectionContext**: compact \u82E5\u53D1\u73B0\u9009\u4E2D\u7684\u662F\u5B50\u56FE\u5C42\uFF0C\u4F1A\u81EA\u52A8\u63D0\u5347\u5230\u6240\u5C5E\u753B\u677F/\u9876\u5C42\u5BB9\u5668\u5E76\u8BB0\u5F55 warning",
|
|
6413
6417
|
"",
|
|
6414
6418
|
"### \u4F7F\u7528\u65B9\u5F0F",
|
|
6415
6419
|
"\u5148\u8BFB\u53D6 restorationContract.blockOrder/bodyCopyLedger/hardRules \u9501\u5B9A\u7ED3\u6784\uFF0C\u518D\u7528 tree \u4E2D\u7684 flutter* \u5B57\u6BB5\u586B\u5145\u6837\u5F0F\u548C\u5E03\u5C40\u7EC6\u8282\u3002",
|
|
@@ -6418,7 +6422,10 @@ var OUTPUT_GUIDE = {
|
|
|
6418
6422
|
"- \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",
|
|
6419
6423
|
"- SVG \u662F\u5426\u8BEF\u52A0 ColorFilter\uFF1A\u4FDD\u7559\u539F\u8272\u7684 SVG \u4E0D\u5F97\u4E8C\u6B21\u67D3\u8272",
|
|
6420
6424
|
"- \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",
|
|
6421
|
-
"- Bitmap \u662F\u5426\u8BEF\u5F53 SVG\uFF1ASketch Image \u56FE\u5C42\u5FC5\u987B\u5BFC\u51FA PNG + Image.asset",
|
|
6425
|
+
"- Bitmap \u662F\u5426\u8BEF\u5F53 SVG\uFF1ASketch Image \u56FE\u5C42\u5FC5\u987B\u5BFC\u51FA PNG + Image.asset\uFF0C\u4E14\u8865\u9F50 2.0x/3.0x \u53D8\u4F53",
|
|
6426
|
+
"- \u79FB\u52A8\u7AEF\u7A84\u753B\u677F\uFF08\u5982 390 \u5BBD\uFF09\u5728\u5BBD\u5C4F\u5FC5\u987B\u7528 Center + ConstrainedBox(maxWidth: designSurface.maxWidth) \u5939\u6301\uFF0C\u7981\u6B62\u8BA9 Positioned(left/right) \u76F4\u63A5\u62C9\u4F38\u5230\u5168\u5C4F",
|
|
6427
|
+
"- \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",
|
|
6428
|
+
"- \u82E5 selectionContext.autoPromoted=true\uFF0C\u8BF4\u660E\u4E4B\u524D\u9009\u4E2D\u4E86\u5185\u5C42 glyph\uFF1B\u540E\u7EED\u5C40\u90E8\u5BFC\u51FA\u56FE\u6807\u65F6\u5E94\u6539\u7528 cmd=svg \u9009\u4E2D\u5177\u4F53\u56FE\u5C42",
|
|
6422
6429
|
"- \u9875\u9762\u9AA8\u67B6\u662F\u5426\u88AB\u4E1A\u52A1\u7EC4\u4EF6\u6539\u5199\uFF1A\u6807\u9898\u3001\u9876\u90E8\u5165\u53E3\u3001\u641C\u7D22\u5757\u548C\u5E95\u5BFC\u987A\u5E8F\u5FC5\u987B\u56DE\u770B restorationContract"
|
|
6423
6430
|
].join("\n")
|
|
6424
6431
|
};
|
|
@@ -6509,13 +6516,16 @@ async function sketchMeasure(args) {
|
|
|
6509
6516
|
scriptPath: tempScriptPath,
|
|
6510
6517
|
scriptLength: fullScript.length,
|
|
6511
6518
|
pluginInstall: installStatus,
|
|
6512
|
-
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\u91CD\u65B0\u9009\u4E2D\u8BE5\u56FE\u5C42\u6267\u884C svg \u6216\u5C40\u90E8\u5BFC\u51FA\uFF0C\u5E76\u590D\u67E5 colorStrategy\u3001viewBox\u3001containerSize/contentSize\uFF0C\u907F\u514D\u590D\u7528\u65E7\u9875\u9762\u8D44\u4EA7\u3002\u8BF7\u5148\u5728 Sketch \u4E2D\u9009\u4E2D\u76EE\u6807\u753B\u677F/\u56FE\u5C42\u3002",
|
|
6519
|
+
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\u91CD\u65B0\u9009\u4E2D\u8BE5\u56FE\u5C42\u6267\u884C svg \u6216\u5C40\u90E8\u5BFC\u51FA\uFF0C\u5E76\u590D\u67E5 colorStrategy\u3001viewBox\u3001containerSize/contentSize\u3001vf \u4E0E bitmapScales\uFF0C\u907F\u514D\u590D\u7528\u65E7\u9875\u9762\u8D44\u4EA7\u3002\u79FB\u52A8\u7AEF\u7A84\u753B\u677F\u8981\u6309 designSurface.maxWidth \u505A\u5BBD\u5C4F\u5939\u6301\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",
|
|
6513
6520
|
restoreChecklist: [
|
|
6514
6521
|
"\u5148\u6309 restorationContract \u9501\u5B9A\u9875\u9762\u9AA8\u67B6\uFF0C\u518D\u5904\u7406\u5C40\u90E8\u6837\u5F0F",
|
|
6515
6522
|
"\u5355\u4E2A\u56FE\u6807\u504F\u5DEE\u4F18\u5148\u5C40\u90E8\u91CD\u5BFC\u51FA\uFF0C\u4E0D\u590D\u7528\u5176\u5B83\u9875\u9762\u65E7\u8D44\u4EA7",
|
|
6516
6523
|
"preserve \u6A21\u5F0F SVG \u7981\u6B62\u8FFD\u52A0 ColorFilter",
|
|
6517
6524
|
"16x16 \u69FD\u4F4D\u4E0E 6x8/12x12 \u56FE\u5F62\u8981\u5206\u5F00\u5904\u7406",
|
|
6518
|
-
"Sketch Image \u56FE\u5C42\u5BFC\u51FA PNG\uFF0C\u4E0D\u8981\u4F2A\u88C5\u6210 SVG \u4F7F\u7528",
|
|
6525
|
+
"Sketch Image \u56FE\u5C42\u5BFC\u51FA PNG\uFF0C\u4E0D\u8981\u4F2A\u88C5\u6210 SVG \u4F7F\u7528\uFF0C\u5E76\u8865\u9F50 2.0x/3.0x \u53D8\u4F53",
|
|
6526
|
+
"\u79FB\u52A8\u7AEF\u7A84\u753B\u677F\u5728\u5BBD\u5C4F\u5FC5\u987B\u7528 Center + ConstrainedBox(maxWidth: designSurface.maxWidth) \u5939\u6301\uFF0C\u7981\u6B62\u5168\u5C4F\u62C9\u4F38",
|
|
6527
|
+
"\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",
|
|
6528
|
+
"\u82E5 compact \u8FD4\u56DE selectionContext.autoPromoted=true\uFF0C\u8BF4\u660E\u4E4B\u524D\u8BEF\u9009\u4E2D\u4E86\u5B50\u56FE\u5C42\uFF0C\u4E0D\u8981\u628A\u5185\u5C42 glyph \u5F53\u6574\u9875\u5408\u540C",
|
|
6519
6529
|
"\u4EE3\u7801\u751F\u6210\u540E\u5FC5\u987B\u8C03\u7528 validate_restoration \u6821\u9A8C\u9875\u9762\u9AA8\u67B6\u3001\u8D44\u4EA7\u6765\u6E90\u548C\u771F\u5B9E\u8DEF\u7531"
|
|
6520
6530
|
],
|
|
6521
6531
|
postRestoreValidator: {
|
|
@@ -6600,7 +6610,9 @@ function collectAssetContracts(node, bucket = []) {
|
|
|
6600
6610
|
if (node.t === "Image") {
|
|
6601
6611
|
bucket.push({
|
|
6602
6612
|
sketchName: node.n || "Image",
|
|
6603
|
-
|
|
6613
|
+
fileName: typeof node.bitmapFile === "string" ? path20.posix.basename(node.bitmapFile) : typeof node.bitmapPath === "string" ? path20.posix.basename(node.bitmapPath) : void 0,
|
|
6614
|
+
sourceType: "bitmap",
|
|
6615
|
+
scaleVariants: node.bitmapScales
|
|
6604
6616
|
});
|
|
6605
6617
|
}
|
|
6606
6618
|
for (const child of node.ch || []) {
|
|
@@ -6612,12 +6624,77 @@ function extractCodeAssets(codeContent) {
|
|
|
6612
6624
|
const matches = codeContent.match(/assets\/[A-Za-z0-9_./-]+\.(svg|png|jpg|jpeg|webp)/g);
|
|
6613
6625
|
return matches ? [...new Set(matches)] : [];
|
|
6614
6626
|
}
|
|
6627
|
+
function hasCodePropertyLiteral(codeContent, property, value) {
|
|
6628
|
+
const escapedValue = String(value).replace(".", "\\.");
|
|
6629
|
+
return new RegExp(`${property}\\s*:\\s*${escapedValue}(?:\\.0+)?\\b`).test(codeContent);
|
|
6630
|
+
}
|
|
6631
|
+
function hasResponsiveSurfaceConstraint(codeContent, designWidth) {
|
|
6632
|
+
const escapedWidth = String(designWidth).replace(".", "\\.");
|
|
6633
|
+
const directPatterns = [
|
|
6634
|
+
new RegExp(`maxWidth\\s*:\\s*${escapedWidth}(?:\\.0+)?\\b`),
|
|
6635
|
+
new RegExp(`width\\s*:\\s*${escapedWidth}(?:\\.0+)?\\b`),
|
|
6636
|
+
/ConstrainedBox\s*\(/,
|
|
6637
|
+
/BoxConstraints\s*\([^)]*maxWidth\s*:/,
|
|
6638
|
+
/LayoutBuilder\s*\(/,
|
|
6639
|
+
/MediaQuery\.(sizeOf|of)\(/,
|
|
6640
|
+
/math\.(min|max)\(/,
|
|
6641
|
+
/clamp\(/
|
|
6642
|
+
];
|
|
6643
|
+
return directPatterns.some((pattern) => pattern.test(codeContent));
|
|
6644
|
+
}
|
|
6645
|
+
function hasWideStretchRisk(codeContent) {
|
|
6646
|
+
const edgePinnedPositioned = /Positioned\([\s\S]{0,220}left\s*:\s*[-\d.]+[\s\S]{0,220}right\s*:\s*[-\d.]+/.test(codeContent) || /Positioned\([\s\S]{0,220}right\s*:\s*[-\d.]+[\s\S]{0,220}left\s*:\s*[-\d.]+/.test(codeContent);
|
|
6647
|
+
return edgePinnedPositioned || /SizedBox\.expand\s*\(/.test(codeContent) || /double\.infinity/.test(codeContent);
|
|
6648
|
+
}
|
|
6649
|
+
function collectVisualFrameContracts(node, bucket = []) {
|
|
6650
|
+
var _a;
|
|
6651
|
+
if (!node) {
|
|
6652
|
+
return bucket;
|
|
6653
|
+
}
|
|
6654
|
+
if (node.f && node.vf) {
|
|
6655
|
+
const hasVisualDelta = node.f.some((value, index) => value !== node.vf[index]);
|
|
6656
|
+
const hasVisualDecoration = Boolean(
|
|
6657
|
+
node.bg || node.gd || node.bd || node.token || ((_a = node.sh) == null ? void 0 : _a.length) || node.r !== void 0
|
|
6658
|
+
);
|
|
6659
|
+
if (hasVisualDelta && hasVisualDecoration) {
|
|
6660
|
+
bucket.push({
|
|
6661
|
+
nodeName: node.n || node.t || "unknown",
|
|
6662
|
+
frame: node.f,
|
|
6663
|
+
visualFrame: node.vf
|
|
6664
|
+
});
|
|
6665
|
+
}
|
|
6666
|
+
}
|
|
6667
|
+
for (const child of node.ch || []) {
|
|
6668
|
+
collectVisualFrameContracts(child, bucket);
|
|
6669
|
+
}
|
|
6670
|
+
return bucket;
|
|
6671
|
+
}
|
|
6672
|
+
function extractRouteChunk(routeContent, routeIndex) {
|
|
6673
|
+
const blockStart = routeContent.lastIndexOf("GetPage(", routeIndex);
|
|
6674
|
+
const start = blockStart === -1 ? routeIndex : blockStart;
|
|
6675
|
+
const nextBlockStart = routeContent.indexOf("GetPage(", routeIndex + 1);
|
|
6676
|
+
if (nextBlockStart === -1) {
|
|
6677
|
+
return routeContent.slice(start);
|
|
6678
|
+
}
|
|
6679
|
+
return routeContent.slice(start, nextBlockStart);
|
|
6680
|
+
}
|
|
6681
|
+
function resolveProjectAssetPath(projectPath, assetPath) {
|
|
6682
|
+
return path20.join(projectPath, assetPath);
|
|
6683
|
+
}
|
|
6684
|
+
function getBitmapScaleVariantPaths(projectPath, assetPath) {
|
|
6685
|
+
const relativeDir = path20.posix.dirname(assetPath);
|
|
6686
|
+
const fileName = path20.posix.basename(assetPath);
|
|
6687
|
+
return [
|
|
6688
|
+
path20.join(projectPath, relativeDir, "2.0x", fileName),
|
|
6689
|
+
path20.join(projectPath, relativeDir, "3.0x", fileName)
|
|
6690
|
+
];
|
|
6691
|
+
}
|
|
6615
6692
|
function extractPageClassName(codeContent) {
|
|
6616
6693
|
const match = codeContent.match(/class\s+([A-Za-z0-9_]+)\s+extends\s+(StatelessWidget|StatefulWidget)/);
|
|
6617
6694
|
return (match == null ? void 0 : match[1]) || null;
|
|
6618
6695
|
}
|
|
6619
6696
|
function buildContractValidator(payload, codeContent) {
|
|
6620
|
-
var _a, _b, _c;
|
|
6697
|
+
var _a, _b, _c, _d, _e;
|
|
6621
6698
|
const findings = [];
|
|
6622
6699
|
const blockOrder = ((_a = payload.restorationContract) == null ? void 0 : _a.blockOrder) || [];
|
|
6623
6700
|
const navCopyLedger = ((_b = payload.restorationContract) == null ? void 0 : _b.navCopyLedger) || [];
|
|
@@ -6694,6 +6771,34 @@ function buildContractValidator(payload, codeContent) {
|
|
|
6694
6771
|
});
|
|
6695
6772
|
}
|
|
6696
6773
|
}
|
|
6774
|
+
const designWidth = ((_d = payload.designSurface) == null ? void 0 : _d.maxWidth) || ((_e = payload.artboard) == null ? void 0 : _e.w);
|
|
6775
|
+
if (designWidth && designWidth <= 430) {
|
|
6776
|
+
const isClamped = hasResponsiveSurfaceConstraint(codeContent, designWidth);
|
|
6777
|
+
if (hasWideStretchRisk(codeContent) && !isClamped) {
|
|
6778
|
+
findings.push({
|
|
6779
|
+
id: "design_surface_constraint_missing",
|
|
6780
|
+
severity: "error",
|
|
6781
|
+
message: `\u5F53\u524D\u8BBE\u8BA1\u7A3F\u4E3A ${designWidth} \u5BBD\u79FB\u52A8\u7AEF\u753B\u677F\uFF0C\u4F46\u4EE3\u7801\u672A\u68C0\u6D4B\u5230\u5BBD\u5C4F\u5939\u6301\u7EA6\u675F\uFF0C\u5BBD\u7A97\u53E3\u4E0B\u4F1A\u88AB\u76F4\u63A5\u62C9\u4F38\u3002`,
|
|
6782
|
+
suggestion: "\u5916\u5C42\u5148\u7528 Center + ConstrainedBox(maxWidth: designSurface.maxWidth) \u6216\u7B49\u6548\u7EA6\u675F\uFF0C\u518D\u5728\u7EA6\u675F\u5185\u4F7F\u7528 Positioned/Stack\u3002"
|
|
6783
|
+
});
|
|
6784
|
+
}
|
|
6785
|
+
}
|
|
6786
|
+
const visualFrameContracts = collectVisualFrameContracts(payload.tree);
|
|
6787
|
+
for (const contract of visualFrameContracts) {
|
|
6788
|
+
const [, , frameWidth, frameHeight] = contract.frame;
|
|
6789
|
+
const [, , visualWidth, visualHeight] = contract.visualFrame;
|
|
6790
|
+
const widthMismatch = frameWidth !== visualWidth && hasCodePropertyLiteral(codeContent, "width", frameWidth) && !hasCodePropertyLiteral(codeContent, "width", visualWidth);
|
|
6791
|
+
const heightMismatch = frameHeight !== visualHeight && hasCodePropertyLiteral(codeContent, "height", frameHeight) && !hasCodePropertyLiteral(codeContent, "height", visualHeight);
|
|
6792
|
+
if (widthMismatch || heightMismatch) {
|
|
6793
|
+
findings.push({
|
|
6794
|
+
id: "visual_frame_literal_mismatch",
|
|
6795
|
+
severity: "warning",
|
|
6796
|
+
message: `${contract.nodeName} \u7684\u89C6\u89C9\u8FB9\u754C\u662F ${visualWidth}x${visualHeight}\uFF0C\u4F46\u4EE3\u7801\u770B\u8D77\u6765\u4ECD\u5728\u4F7F\u7528\u903B\u8F91 frame ${frameWidth}x${frameHeight}\uFF0C\u5BB9\u6613\u9020\u6210\u5E95\u8FB9\u8DDD\u6216\u9634\u5F71\u89C6\u89C9\u8BEF\u5DEE\u3002`,
|
|
6797
|
+
evidence: [`${contract.nodeName}: frame=${contract.frame.join(",")} visualFrame=${contract.visualFrame.join(",")}`],
|
|
6798
|
+
suggestion: "\u5F53 compact \u540C\u65F6\u7ED9\u51FA f \u4E0E vf \u65F6\uFF0C\u5916\u5C42\u5BB9\u5668\u5C3A\u5BF8\u548C\u7531\u6B64\u63A8\u5BFC\u7684\u5E95\u90E8\u89C6\u89C9\u95F4\u8DDD\u4F18\u5148\u4EE5 vf \u4E3A\u51C6\u3002"
|
|
6799
|
+
});
|
|
6800
|
+
}
|
|
6801
|
+
}
|
|
6697
6802
|
return {
|
|
6698
6803
|
passed: !findings.some((item) => item.severity === "error"),
|
|
6699
6804
|
requiredBlocks,
|
|
@@ -6701,7 +6806,7 @@ function buildContractValidator(payload, codeContent) {
|
|
|
6701
6806
|
findings
|
|
6702
6807
|
};
|
|
6703
6808
|
}
|
|
6704
|
-
function buildAssetValidator(payload, codeContent) {
|
|
6809
|
+
function buildAssetValidator(payload, codeContent, args) {
|
|
6705
6810
|
const findings = [];
|
|
6706
6811
|
const assetContracts = collectAssetContracts(payload.tree);
|
|
6707
6812
|
const expectedVectorFiles = new Set(
|
|
@@ -6738,6 +6843,54 @@ function buildAssetValidator(payload, codeContent) {
|
|
|
6738
6843
|
suggestion: "\u4F4D\u56FE\u8D44\u6E90\u4F18\u5148\u6309\u5F53\u524D\u753B\u677F\u76F4\u63A5\u5BFC\u51FA\u5230 assets/icons/\uFF0C\u907F\u514D\u7EE7\u7EED\u590D\u7528\u65E7\u9875\u9762 PNG\u3002"
|
|
6739
6844
|
});
|
|
6740
6845
|
}
|
|
6846
|
+
if (expectedBitmapCount > 0 && codeBitmapAssets.length > 0) {
|
|
6847
|
+
const pageClassName = extractPageClassName(codeContent) || "";
|
|
6848
|
+
const normalizedStem = pageClassName.replace(/Page$/, "").replace(/([a-z])([A-Z])/g, "$1_$2").toLowerCase();
|
|
6849
|
+
if (normalizedStem) {
|
|
6850
|
+
const hasPageLocalBitmap = codeBitmapAssets.some(
|
|
6851
|
+
(asset) => path20.posix.basename(asset).toLowerCase().includes(normalizedStem)
|
|
6852
|
+
);
|
|
6853
|
+
if (!hasPageLocalBitmap) {
|
|
6854
|
+
findings.push({
|
|
6855
|
+
id: "bitmap_assets_not_page_local",
|
|
6856
|
+
severity: "warning",
|
|
6857
|
+
message: "\u5F53\u524D\u9875\u9762\u4F4D\u56FE\u8D44\u6E90\u770B\u8D77\u6765\u4E0D\u662F page-local \u547D\u540D\uFF0C\u5B58\u5728\u7EE7\u7EED\u590D\u7528\u65E7\u9875\u9762 PNG \u7684\u98CE\u9669\u3002",
|
|
6858
|
+
evidence: codeBitmapAssets,
|
|
6859
|
+
suggestion: "\u4F4D\u56FE\u8D44\u6E90\u4F18\u5148\u6309\u5F53\u524D\u9875\u9762\u547D\u540D\u5BFC\u51FA\uFF0C\u4F8B\u5982\u5E26\u4E0A\u9875\u9762 stem\uFF0C\u907F\u514D\u6DF7\u5165\u65E7\u9875\u9762\u901A\u7528 PNG\u3002"
|
|
6860
|
+
});
|
|
6861
|
+
}
|
|
6862
|
+
}
|
|
6863
|
+
}
|
|
6864
|
+
const expectedBitmapScales = new Set(
|
|
6865
|
+
assetContracts.filter((item) => item.sourceType === "bitmap").flatMap((item) => item.scaleVariants || [])
|
|
6866
|
+
);
|
|
6867
|
+
if (expectedBitmapCount > 0 && codeBitmapAssets.length > 0 && args.projectPath) {
|
|
6868
|
+
const requiresRetinaVariants = expectedBitmapScales.size === 0 || expectedBitmapScales.has("2.0x") || expectedBitmapScales.has("3.0x");
|
|
6869
|
+
if (requiresRetinaVariants) {
|
|
6870
|
+
const missingRetinaEvidence = [];
|
|
6871
|
+
for (const asset of codeBitmapAssets) {
|
|
6872
|
+
const assetOnDisk = resolveProjectAssetPath(args.projectPath, asset);
|
|
6873
|
+
if (!fs20.existsSync(assetOnDisk)) {
|
|
6874
|
+
missingRetinaEvidence.push(`${asset} (base missing)`);
|
|
6875
|
+
continue;
|
|
6876
|
+
}
|
|
6877
|
+
const variantPaths = getBitmapScaleVariantPaths(args.projectPath, asset);
|
|
6878
|
+
const missingVariants = variantPaths.filter((variantPath) => !fs20.existsSync(variantPath)).map((variantPath) => path20.relative(args.projectPath, variantPath));
|
|
6879
|
+
if (missingVariants.length > 0) {
|
|
6880
|
+
missingRetinaEvidence.push(`${asset} -> missing ${missingVariants.join(", ")}`);
|
|
6881
|
+
}
|
|
6882
|
+
}
|
|
6883
|
+
if (missingRetinaEvidence.length > 0) {
|
|
6884
|
+
findings.push({
|
|
6885
|
+
id: "bitmap_retina_variants_missing",
|
|
6886
|
+
severity: "error",
|
|
6887
|
+
message: "\u4F4D\u56FE\u8D44\u6E90\u7F3A\u5C11 2.0x/3.0x \u53D8\u4F53\uFF0C\u9AD8\u5206\u5C4F\u4E0B\u5BB9\u6613\u53D1\u7CCA\u3002",
|
|
6888
|
+
evidence: missingRetinaEvidence,
|
|
6889
|
+
suggestion: "\u6309\u5F53\u524D\u753B\u677F\u91CD\u65B0\u5BFC\u51FA PNG\uFF0C\u5E76\u8865\u9F50 assets/.../2.0x \u4E0E 3.0x \u53D8\u4F53\u540E\u518D\u9A8C\u6536\u3002"
|
|
6890
|
+
});
|
|
6891
|
+
}
|
|
6892
|
+
}
|
|
6893
|
+
}
|
|
6741
6894
|
const preserveContracts = assetContracts.filter((item) => item.mode === "preserve");
|
|
6742
6895
|
if (preserveContracts.length > 0 && /colorFilter\s*:|ColorFilter\./.test(codeContent)) {
|
|
6743
6896
|
findings.push({
|
|
@@ -6772,7 +6925,7 @@ function buildRouteReviewValidator(args, codeContent) {
|
|
|
6772
6925
|
suggestion: "\u751F\u6210\u9875\u9762\u540E\u5FC5\u987B\u786E\u8BA4\u771F\u5B9E\u8DEF\u7531\u5DF2\u7ECF\u63A5\u901A\uFF0C\u4E0D\u80FD\u505C\u7559\u5728\u5B64\u7ACB\u9875\u9762\u6587\u4EF6\u3002"
|
|
6773
6926
|
});
|
|
6774
6927
|
} else {
|
|
6775
|
-
const routeChunk = routeContent
|
|
6928
|
+
const routeChunk = extractRouteChunk(routeContent, routeIndex);
|
|
6776
6929
|
routeConnected = true;
|
|
6777
6930
|
if (/_ComingSoonPage/.test(routeChunk)) {
|
|
6778
6931
|
routeConnected = false;
|
|
@@ -6849,7 +7002,7 @@ async function validateRestoration(args) {
|
|
|
6849
7002
|
const payload = loadMeasurePayload(args);
|
|
6850
7003
|
const codeContent = fs20.readFileSync(args.codeFilePath, "utf-8");
|
|
6851
7004
|
const contractValidator = buildContractValidator(payload, codeContent);
|
|
6852
|
-
const assetValidator = buildAssetValidator(payload, codeContent);
|
|
7005
|
+
const assetValidator = buildAssetValidator(payload, codeContent, args);
|
|
6853
7006
|
const routeReviewValidator = buildRouteReviewValidator(args, codeContent);
|
|
6854
7007
|
return {
|
|
6855
7008
|
artboardName: (_a = payload.artboard) == null ? void 0 : _a.name,
|