@sangheepark/figma-ds-mcp 0.2.4 → 0.2.5

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.
@@ -112,18 +112,52 @@ function enrichSpec(traversal, mapping) {
112
112
  if (component) {
113
113
  node['library-key'] = component['library-key'];
114
114
  // Step 2: _ds_props → variant-props + overrides 분리
115
+ // value 역검색 + default fallback 로직 포함
115
116
  if (node._ds_props) {
116
117
  const variantProps = {};
117
118
  const overrides = {};
118
119
  for (const [key, value] of Object.entries(node._ds_props)) {
119
120
  if (component.variants && key in component.variants) {
120
- // variant axis에 해당하는 prop
121
+ // 1) exact key match → variant-props
121
122
  if (typeof value === 'string' && component.defaults?.[key] !== value) {
122
123
  variantProps[key] = value;
123
124
  }
124
125
  }
126
+ else if (component.variants && typeof value === 'string') {
127
+ // 2) exact match 실패 → value 역검색: 이 값을 가진 variant axis 찾기
128
+ const matchingAxes = [];
129
+ for (const [axis, options] of Object.entries(component.variants)) {
130
+ if (axis in variantProps)
131
+ continue; // 이미 매핑된 axis 스킵
132
+ if (options.includes(value) && component.defaults?.[axis] !== value) {
133
+ matchingAxes.push(axis);
134
+ }
135
+ }
136
+ if (matchingAxes.length === 1) {
137
+ // 정확히 1개 axis에서만 발견 → 매핑
138
+ variantProps[matchingAxes[0]] = value;
139
+ }
140
+ // 0개 또는 2개 이상 → 매핑 포기 (default variant 사용)
141
+ }
142
+ else if (component.properties && typeof value === 'string') {
143
+ // 3) variant가 아닌 prop → property name 역검색
144
+ if (key in component.properties) {
145
+ // exact property name match
146
+ overrides[key] = value;
147
+ }
148
+ else {
149
+ // exact match 실패 → TEXT property 자동 매핑
150
+ const textProps = Object.entries(component.properties)
151
+ .filter(([, type]) => type === 'TEXT')
152
+ .map(([name]) => name);
153
+ if (textProps.length === 1) {
154
+ overrides[textProps[0]] = value;
155
+ }
156
+ // 0개 또는 2개 이상 → 매핑 포기
157
+ }
158
+ }
125
159
  else {
126
- // variant가 아닌 prop → overrides (text, boolean, swap)
160
+ // boolean 기타 → overrides 직접
127
161
  overrides[key] = value;
128
162
  }
129
163
  }
@@ -222,6 +256,19 @@ function enrichSpec(traversal, mapping) {
222
256
  node.layout.direction = 'column';
223
257
  }
224
258
  }
259
+ // 6-D: absolute + fill 정규화
260
+ // Figma에서 absolute 요소는 parent auto-layout에 참여하지 않으므로
261
+ // fill은 layoutSizingHorizontal/Vertical = 'FILL'로 처리 → constraints STRETCH 동작
262
+ // 별도 변환 불필요 — NodeBuilder가 absolute child에 fill을 적용하면 STRETCH로 동작
263
+ // 다만 x/y가 없으면 0으로 기본값 설정하여 parent 좌상단 정렬
264
+ if (node.layout?.positioning === 'absolute') {
265
+ if ((node.layout.width === 'fill' || node.layout.width === '100%') && node.layout.x === undefined) {
266
+ node.layout.x = '0';
267
+ }
268
+ if ((node.layout.height === 'fill' || node.layout.height === '100%') && node.layout.y === undefined) {
269
+ node.layout.y = '0';
270
+ }
271
+ }
225
272
  // children 재귀
226
273
  if (node.children) {
227
274
  node.children.forEach((child, i) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sangheepark/figma-ds-mcp",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "MCP server for Code to Figma Bridge — bridges Claude Code to Figma plugin via WebSocket",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",