@biolab/talk-to-figma 0.5.0 → 0.7.0
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/README.md +0 -125
- package/dist/cli.cjs +104 -0
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +104 -0
- package/dist/cli.js.map +1 -1
- package/dist/talk_to_figma_mcp/server.cjs +104 -0
- package/dist/talk_to_figma_mcp/server.cjs.map +1 -1
- package/dist/talk_to_figma_mcp/server.js +104 -0
- package/dist/talk_to_figma_mcp/server.js.map +1 -1
- package/figma-plugin/code.js +118 -1
- package/figma-plugin/figma-plugin.zip +0 -0
- package/figma-plugin/ui.html +869 -832
- package/package.json +1 -1
package/figma-plugin/code.js
CHANGED
|
@@ -157,6 +157,12 @@ async function handleCommand(command, params) {
|
|
|
157
157
|
return await setCornerRadius(params);
|
|
158
158
|
case "set_text_content":
|
|
159
159
|
return await setTextContent(params);
|
|
160
|
+
case "set_font_family":
|
|
161
|
+
return await setFontFamily(params);
|
|
162
|
+
case "set_font_size":
|
|
163
|
+
return await setFontSize(params);
|
|
164
|
+
case "set_font_weight":
|
|
165
|
+
return await setFontWeight(params);
|
|
160
166
|
case "clone_node":
|
|
161
167
|
return await cloneNode(params);
|
|
162
168
|
case "scan_text_nodes":
|
|
@@ -1466,7 +1472,36 @@ async function setVariableBinding(params) {
|
|
|
1466
1472
|
if (!variable) {
|
|
1467
1473
|
throw new Error(`Variable not found: ${variableId}`);
|
|
1468
1474
|
}
|
|
1469
|
-
|
|
1475
|
+
|
|
1476
|
+
// Handle paint color bindings (fills/N/color, strokes/N/color)
|
|
1477
|
+
const paintMatch = field.match(/^(fills|strokes)\/(\d+)\/color$/);
|
|
1478
|
+
if (paintMatch) {
|
|
1479
|
+
const [, paintType, indexStr] = paintMatch;
|
|
1480
|
+
const index = parseInt(indexStr, 10);
|
|
1481
|
+
const paints = node[paintType];
|
|
1482
|
+
|
|
1483
|
+
if (!paints || !Array.isArray(paints) || index >= paints.length) {
|
|
1484
|
+
// Create a default solid paint if none exists at the index
|
|
1485
|
+
const alias = figma.variables.createVariableAlias(variable);
|
|
1486
|
+
const newPaint = figma.util.solidPaint({ r: 0, g: 0, b: 0 }, 1);
|
|
1487
|
+
newPaint.boundVariables = { color: alias };
|
|
1488
|
+
if (paintType === "fills") {
|
|
1489
|
+
node.fills = [newPaint];
|
|
1490
|
+
} else {
|
|
1491
|
+
node.strokes = [newPaint];
|
|
1492
|
+
}
|
|
1493
|
+
} else {
|
|
1494
|
+
const alias = figma.variables.createVariableAlias(variable);
|
|
1495
|
+
const paintsCopy = paints.slice();
|
|
1496
|
+
const paint = Object.assign({}, paintsCopy[index]);
|
|
1497
|
+
paint.boundVariables = Object.assign({}, paint.boundVariables, { color: alias });
|
|
1498
|
+
paintsCopy[index] = paint;
|
|
1499
|
+
node[paintType] = paintsCopy;
|
|
1500
|
+
}
|
|
1501
|
+
} else {
|
|
1502
|
+
node.setBoundVariable(field, variable);
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1470
1505
|
return {
|
|
1471
1506
|
success: true,
|
|
1472
1507
|
nodeId: node.id,
|
|
@@ -1809,6 +1844,88 @@ async function setTextContent(params) {
|
|
|
1809
1844
|
}
|
|
1810
1845
|
}
|
|
1811
1846
|
|
|
1847
|
+
function mapFontWeight(weight) {
|
|
1848
|
+
switch (weight) {
|
|
1849
|
+
case 100: return "Thin";
|
|
1850
|
+
case 200: return "Extra Light";
|
|
1851
|
+
case 300: return "Light";
|
|
1852
|
+
case 400: return "Regular";
|
|
1853
|
+
case 500: return "Medium";
|
|
1854
|
+
case 600: return "Semi Bold";
|
|
1855
|
+
case 700: return "Bold";
|
|
1856
|
+
case 800: return "Extra Bold";
|
|
1857
|
+
case 900: return "Black";
|
|
1858
|
+
default: return "Regular";
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
async function setFontFamily(params) {
|
|
1863
|
+
const { nodeId, fontFamily, fontStyle = "Regular" } = params || {};
|
|
1864
|
+
|
|
1865
|
+
if (!nodeId) throw new Error("Missing nodeId parameter");
|
|
1866
|
+
if (!fontFamily) throw new Error("Missing fontFamily parameter");
|
|
1867
|
+
|
|
1868
|
+
const node = await figma.getNodeByIdAsync(nodeId);
|
|
1869
|
+
if (!node) throw new Error(`Node not found with ID: ${nodeId}`);
|
|
1870
|
+
if (node.type !== "TEXT") throw new Error(`Node is not a text node: ${nodeId}`);
|
|
1871
|
+
|
|
1872
|
+
try {
|
|
1873
|
+
const newFont = { family: fontFamily, style: fontStyle };
|
|
1874
|
+
await figma.loadFontAsync(newFont);
|
|
1875
|
+
node.fontName = newFont;
|
|
1876
|
+
return { id: node.id, name: node.name, fontName: node.fontName };
|
|
1877
|
+
} catch (error) {
|
|
1878
|
+
throw new Error(`Error setting font family: ${error.message}`);
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1882
|
+
async function setFontSize(params) {
|
|
1883
|
+
const { nodeId, fontSize } = params || {};
|
|
1884
|
+
|
|
1885
|
+
if (!nodeId) throw new Error("Missing nodeId parameter");
|
|
1886
|
+
if (fontSize === undefined) throw new Error("Missing fontSize parameter");
|
|
1887
|
+
|
|
1888
|
+
const node = await figma.getNodeByIdAsync(nodeId);
|
|
1889
|
+
if (!node) throw new Error(`Node not found with ID: ${nodeId}`);
|
|
1890
|
+
if (node.type !== "TEXT") throw new Error(`Node is not a text node: ${nodeId}`);
|
|
1891
|
+
|
|
1892
|
+
try {
|
|
1893
|
+
// Load current font before modifying
|
|
1894
|
+
const currentFont = node.fontName === figma.mixed
|
|
1895
|
+
? node.getRangeFontName(0, 1)
|
|
1896
|
+
: node.fontName;
|
|
1897
|
+
await figma.loadFontAsync(currentFont);
|
|
1898
|
+
node.fontSize = parseInt(fontSize);
|
|
1899
|
+
return { id: node.id, name: node.name, fontSize: node.fontSize };
|
|
1900
|
+
} catch (error) {
|
|
1901
|
+
throw new Error(`Error setting font size: ${error.message}`);
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1905
|
+
async function setFontWeight(params) {
|
|
1906
|
+
const { nodeId, fontWeight } = params || {};
|
|
1907
|
+
|
|
1908
|
+
if (!nodeId) throw new Error("Missing nodeId parameter");
|
|
1909
|
+
if (fontWeight === undefined) throw new Error("Missing fontWeight parameter");
|
|
1910
|
+
|
|
1911
|
+
const node = await figma.getNodeByIdAsync(nodeId);
|
|
1912
|
+
if (!node) throw new Error(`Node not found with ID: ${nodeId}`);
|
|
1913
|
+
if (node.type !== "TEXT") throw new Error(`Node is not a text node: ${nodeId}`);
|
|
1914
|
+
|
|
1915
|
+
try {
|
|
1916
|
+
const currentFont = node.fontName === figma.mixed
|
|
1917
|
+
? node.getRangeFontName(0, 1)
|
|
1918
|
+
: node.fontName;
|
|
1919
|
+
const newStyle = mapFontWeight(fontWeight);
|
|
1920
|
+
const newFont = { family: currentFont.family, style: newStyle };
|
|
1921
|
+
await figma.loadFontAsync(newFont);
|
|
1922
|
+
node.fontName = newFont;
|
|
1923
|
+
return { id: node.id, name: node.name, fontName: node.fontName };
|
|
1924
|
+
} catch (error) {
|
|
1925
|
+
throw new Error(`Error setting font weight: ${error.message}`);
|
|
1926
|
+
}
|
|
1927
|
+
}
|
|
1928
|
+
|
|
1812
1929
|
// Initialize settings on load
|
|
1813
1930
|
(async function initializePlugin() {
|
|
1814
1931
|
try {
|
|
Binary file
|