mta-mcp 3.16.1 → 3.16.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mta-mcp",
3
- "version": "3.16.1",
3
+ "version": "3.16.2",
4
4
  "description": "MTA - 智能编码助手 MCP 服务器(规范 + 技能 + 诊断 + 模板 + 记忆 + 思考)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -116,7 +116,7 @@ class TipCardConfig {
116
116
  titleColor: Color(0xFFFF9800),
117
117
  contentColor: Color(0xFFB45309),
118
118
  buttonShadowColor: Color(0x40FF9800),
119
- iconPath: 'assets/icons/warning_icon.svg',
119
+ iconPath: '<asset-dir>/warning_icon.svg',
120
120
  );
121
121
 
122
122
  /// Error: #f4433614 (8%透明), border #ffcacaff
@@ -126,7 +126,7 @@ class TipCardConfig {
126
126
  titleColor: Color(0xFFF44336),
127
127
  contentColor: Color(0xFFCA4F57),
128
128
  buttonShadowColor: Color(0x40D0121B),
129
- iconPath: 'assets/icons/error_icon.svg',
129
+ iconPath: '<asset-dir>/error_icon.svg',
130
130
  );
131
131
 
132
132
  static TipCardConfig fromType(TipCardType type) {
@@ -83,14 +83,14 @@ extractIconInternalSize('Frame Name');
83
83
  ```dart
84
84
  // ✅ 使用内部图形的实际尺寸
85
85
  SvgPicture.asset(
86
- 'assets/icons/recipient.svg',
86
+ '<asset-dir>/recipient.svg',
87
87
  width: 15.0, // 14.7 取整
88
88
  height: 15.0,
89
89
  )
90
90
 
91
91
  // ❌ 错误:使用外层 Group 尺寸
92
92
  SvgPicture.asset(
93
- 'assets/icons/recipient.svg',
93
+ '<asset-dir>/recipient.svg',
94
94
  width: 22.0, // 这是 Group 尺寸,图标会偏大
95
95
  height: 22.0,
96
96
  )
@@ -111,13 +111,13 @@ selection.forEach(layer => {
111
111
 
112
112
  ```bash
113
113
  # 1. 查看文件大小:纯图标通常 < 3KB
114
- ls -lh assets/icons/ic_face_id.svg
114
+ ls -lh <asset-dir>/ic_face_id.svg
115
115
 
116
116
  # 2. 搜索是否含圆形元素
117
- grep -c "<circle\|fill-opacity" assets/icons/ic_face_id.svg
117
+ grep -c "<circle\|fill-opacity" <asset-dir>/ic_face_id.svg
118
118
 
119
119
  # 3. 检查 viewBox 是否等于图标本身尺寸(如 60×60)
120
- grep "viewBox" assets/icons/ic_face_id.svg
120
+ grep "viewBox" <asset-dir>/ic_face_id.svg
121
121
  ```
122
122
 
123
123
  ### Flutter 代码中的正确用法
@@ -134,7 +134,7 @@ Container(
134
134
  child: Center(
135
135
  // SVG 只含纯图标路径,不含圆形背景
136
136
  child: SvgPicture.asset(
137
- 'assets/icons/ic_face_id.svg',
137
+ '<asset-dir>/ic_face_id.svg',
138
138
  width: 60,
139
139
  height: 60,
140
140
  ),
@@ -142,6 +142,8 @@ Container(
142
142
  )
143
143
  ```
144
144
 
145
+ 其中 <asset-dir> 表示当前项目的实际素材目录。
146
+
145
147
  ---
146
148
 
147
149
  ## 📝 验证检查清单
@@ -91,7 +91,7 @@ SizedBox(
91
91
  height: 16,
92
92
  child: Center(
93
93
  child: SvgPicture.asset(
94
- 'assets/icons/recipient_chevron_right.svg',
94
+ '<asset-dir>/recipient_chevron_right.svg',
95
95
  width: 6,
96
96
  height: 8,
97
97
  ),
@@ -99,7 +99,7 @@ SizedBox(
99
99
  )
100
100
 
101
101
  // ❌ 错误 - 直接把 6×8 箭头按 16×16 渲染,视觉会偏大
102
- SvgPicture.asset('assets/icons/recipient_chevron_right.svg', width: 16, height: 16)
102
+ SvgPicture.asset('<asset-dir>/recipient_chevron_right.svg', width: 16, height: 16)
103
103
  ```
104
104
 
105
105
  ---
@@ -113,7 +113,7 @@ SvgPicture.asset('assets/icons/recipient_chevron_right.svg', width: 16, height:
113
113
  2. **验证导出的 viewBox**
114
114
  ```bash
115
115
  # 检查 SVG 文件的 viewBox
116
- head -3 assets/icons/arrow.svg
116
+ head -3 <asset-dir>/arrow.svg
117
117
  # 应该看到 viewBox="0 0 12 12" 而非 viewBox="0 0 6 3"
118
118
  ```
119
119
 
@@ -53,7 +53,7 @@ SvgPicture.asset(
53
53
  ```dart
54
54
  // ✅ 不使用 colorFilter,保留 SVG 原有颜色和透明度
55
55
  SvgPicture.asset(
56
- 'assets/icons/dropdown_arrow.svg',
56
+ '<asset-dir>/dropdown_arrow.svg',
57
57
  width: 12,
58
58
  height: 12,
59
59
  // 不传 colorFilter
@@ -65,14 +65,14 @@ SvgPicture.asset(
65
65
  ```dart
66
66
  // ✅ sketch_measure 已判定保留原色
67
67
  SvgPicture.asset(
68
- 'assets/icons/recipient_chevron_right.svg',
68
+ '<asset-dir>/recipient_chevron_right.svg',
69
69
  width: 6,
70
70
  height: 8,
71
71
  )
72
72
 
73
73
  // ❌ 错误 - preserve 模式又二次染色
74
74
  SvgPicture.asset(
75
- 'assets/icons/recipient_chevron_right.svg',
75
+ '<asset-dir>/recipient_chevron_right.svg',
76
76
  width: 6,
77
77
  height: 8,
78
78
  colorFilter: ColorFilter.mode(AppColors.textDarkTertiary, BlendMode.srcIn),
@@ -2819,7 +2819,7 @@ function measureRecursively(layer, depth, parentFrame, siblings) {
2819
2819
 
2820
2820
  if (element.isIcon) {
2821
2821
  element.iconAssetFileName = buildLayerAssetFileName(layer, 'icon', 'svg');
2822
- element.iconExportPath = 'icons/' + element.iconAssetFileName;
2822
+ element.iconExportPath = element.iconAssetFileName;
2823
2823
  element.iconSketchName = layer.name;
2824
2824
  if (looksLikeSvgExportCandidate(layer)) {
2825
2825
  var svgExport = exportLayerToSvgMarkup(layer, element.iconAssetFileName);
@@ -2835,7 +2835,7 @@ function measureRecursively(layer, depth, parentFrame, siblings) {
2835
2835
  element.iconSvgExportSkipped = '该图层包含常规文本或位图,不适合作为纯 SVG 图标导出';
2836
2836
  }
2837
2837
  element.iconPathWarning = '优先使用插件返回的真实 SVG(iconSvgMarkup/flutterSvgCode)。' +
2838
- '若需要落盘文件,建议保存为 assets/icons/' + element.iconAssetFileName + '。禁止用 Icons.xxx 替代——SVG 不存在时必须报错,不得静默降级。';
2838
+ '若需要落盘文件,请放入项目现有素材目录并保留建议文件名 ' + element.iconAssetFileName + '。禁止用 Icons.xxx 替代——SVG 不存在时必须报错,不得静默降级。';
2839
2839
  // 提取 Icon 内容边界 (区分容器尺寸 vs 内容尺寸)
2840
2840
  if (layer.type === 'Group' && layer.layers) {
2841
2841
  var bounds = extractIconContentBounds(layer);
@@ -2884,7 +2884,7 @@ function measureRecursively(layer, depth, parentFrame, siblings) {
2884
2884
  effectiveColor
2885
2885
  );
2886
2886
  } else {
2887
- element.flutterSvgCode = 'SvgPicture.asset(\'assets/' + element.iconExportPath + '\' /* TODO: 若插件未返回 iconSvgMarkup,请将 Sketch 导出的真实 SVG 落盘到该路径 */, width: ' + iw + ', height: ' + ih + ', colorFilter: ColorFilter.mode(' + effectiveColor + ', BlendMode.srcIn),)';
2887
+ element.flutterSvgCode = 'SvgPicture.asset(\'<asset-path>/' + element.iconAssetFileName + '\' /* TODO: 将真实 SVG 放入项目素材目录并替换占位路径 */, width: ' + iw + ', height: ' + ih + ', colorFilter: ColorFilter.mode(' + effectiveColor + ', BlendMode.srcIn),)';
2888
2888
  }
2889
2889
  }
2890
2890
  } else if (element.iconSvgMarkup) {
@@ -2995,7 +2995,7 @@ function measureRecursively(layer, depth, parentFrame, siblings) {
2995
2995
  if (nativeImgFills && nativeImgFills[0] && nativeImgFills[0].hex) {
2996
2996
  element.imageInfo.nativeTint = formatNativeColor(nativeImgFills[0]);
2997
2997
  }
2998
- element.imageInfo.note = '此图层为嵌入式位图(Bitmap)。若它是 icon/button/arrow 等图标类位图,先去 assets/icons/ 查找用户手工导出的 *_icon@4x.png;找到即直接用 Image.asset 复用。只有明确缺失时才补导 PNG,禁止再把 Bitmap 伪装成 SVG。';
2998
+ element.imageInfo.note = '此图层为嵌入式位图(Bitmap)。若它是 icon/button/arrow 等图标类位图,先在项目素材目录中按图层文件名主体查找现有高倍率 PNG(例如 xxx@4x.png);找到即直接复用。只有明确缺失时才补导 PNG,禁止再把 Bitmap 伪装成 SVG。';
2999
2999
  // 生成 Image.asset 代码片段,开发者直接复制使用
3000
3000
  var bitmapW = Math.round(layer.frame.width);
3001
3001
  var bitmapH = Math.round(layer.frame.height);
@@ -3006,30 +3006,29 @@ function measureRecursively(layer, depth, parentFrame, siblings) {
3006
3006
  var bitmapName = sharedBitmapName || buildLayerAssetBaseName(layer, 'image');
3007
3007
  var bitmapFileName = manualBitmapName || (bitmapName + '.png');
3008
3008
  element.imageInfo.reuseMode = element.isIcon
3009
- ? 'assets-icons-search-first'
3009
+ ? 'project-asset-search-first'
3010
3010
  : (sharedBitmapName ? 'shared-canonical' : 'page-local');
3011
3011
  if (sharedBitmapName && !element.isIcon) {
3012
3012
  element.imageInfo.reuseKey = sharedBitmapName;
3013
3013
  }
3014
3014
  element.imageInfo.bitmapFileName = bitmapFileName;
3015
- element.imageInfo.bitmapExportPath = 'icons/' + bitmapFileName;
3015
+ element.imageInfo.bitmapExportPath = bitmapFileName;
3016
3016
  element.imageInfo.exportScaleVariants = element.isIcon ? ['@4x'] : ['1.0x', '2.0x', '3.0x'];
3017
3017
  if (bitmapLookupCandidates.length > 0) {
3018
- element.imageInfo.lookupDir = 'assets/icons/';
3019
3018
  element.imageInfo.lookupCandidates = bitmapLookupCandidates;
3020
3019
  }
3021
3020
  if (element.isIcon) {
3022
- element.imageInfo.pathWarning = '先在 assets/icons/ 中按设计稿图层名查找用户手工导出的 @4x PNG。优先候选: ' + manualBitmapCandidates.join(' / ') + '。找到即直接复用,不要再推导 SVG 或继续生成新的 page-local PNG。';
3023
- element.imageInfo.exportHint = ' assets/icons/ 中缺少对应图标,请由用户手动从设计稿导出 PNG assets/icons/,文件名优先使用 ' + bitmapFileName + '';
3021
+ element.imageInfo.pathWarning = '先在项目素材目录中按设计稿图层名主体查找用户手工导出的高倍率 PNG。优先候选: ' + manualBitmapCandidates.join(' / ') + '。文件名匹配重点看 xxx 主体,@4x 只是倍率后缀。找到即直接复用,不要再推导 SVG 或继续生成新的 page-local PNG。';
3022
+ element.imageInfo.exportHint = '若项目素材目录中缺少对应图标,请由用户手动从设计稿导出 PNG,并沿用建议文件名主体 ' + bitmapName + '(例如 ' + bitmapName + '.png 或 ' + bitmapName + '@4x.png)。';
3024
3023
  } else {
3025
3024
  element.imageInfo.pathWarning = sharedBitmapName
3026
- ? '检测到重复出现的共享位图图标。先按设计稿图层原名查找手工导出文件(优先候选: ' + bitmapLookupCandidates.join(' / ') + ');若项目已做运行时规范化,再复用 canonical 资产 assets/icons/' + bitmapName + '.png。禁止把 Help / Customer Service 等语义相近位图互换。'
3025
+ ? '检测到重复出现的共享位图图标。先按设计稿图层原名或文件名主体查找现有资源(优先候选: ' + bitmapLookupCandidates.join(' / ') + ');若项目已做运行时规范化,再复用 canonical 文件名 ' + bitmapName + '.png。禁止把 Help / Customer Service 等语义相近位图互换。'
3027
3026
  : '⚠️ 位图资源必须从当前画板局部导出并使用 page-local 文件名,禁止继续复用其它页面的旧 PNG。';
3028
3027
  element.imageInfo.exportHint = sharedBitmapName
3029
- ? 'Sketch 导出命令: 先确认 assets/icons/ 中是否已存在设计稿原名导出文件;若需要生成运行时稳定路径,可复制为 assets/icons/' + bitmapName + '.png,并保持像素内容与设计导出一致。'
3030
- : 'Sketch 导出命令: File > Export Layers > 选择此图层 > 格式 PNG @1x/@2x/@3x, 分别放入 assets/icons/、assets/icons/2.0x/、assets/icons/3.0x/';
3028
+ ? 'Sketch 导出命令: 先确认项目素材目录中是否已存在设计稿原名或同主体导出文件;若需要生成运行时稳定路径,可复制为 ' + bitmapName + '.png,并保持像素内容与设计导出一致。'
3029
+ : 'Sketch 导出命令: File > Export Layers > 选择此图层 > 格式 PNG;输出目录遵循当前项目约定,若仍走多倍率目录流程再补齐同目录 2.0x/3.0x';
3031
3030
  }
3032
- element.flutterImageCode = 'Image.asset(\'assets/' + element.imageInfo.bitmapExportPath + '\', width: ' + bitmapW + ', height: ' + bitmapH + ', filterQuality: FilterQuality.high, isAntiAlias: true,)';
3031
+ element.flutterImageCode = 'Image.asset(\'<asset-path>/' + bitmapFileName + '\', width: ' + bitmapW + ', height: ' + bitmapH + ', filterQuality: FilterQuality.high, isAntiAlias: true,)';
3033
3032
  }
3034
3033
 
3035
3034
  // Symbol Instance — override 真实值