You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Figma插件获取混合字体样式报错:Cannot unwrap symbol 解决方法

解决Figma插件选中混合字体元素时postMessage报错“Cannot unwrap symbol”的问题

当Figma插件尝试提取选中元素的字体信息,且选中包含混合字体样式的文本节点时,会触发以下错误:

figma_app.min.js.br:5 Error: in postMessage: Cannot unwrap symbol
at (PLUGIN_477_SOURCE:26)

错误原因

混合字体的文本节点(同一TEXT节点内存在多种字体样式)中,node.fontName不会返回常规的FontName对象,而是返回一个Symbol类型的值。postMessage仅支持传递可JSON序列化的数据,Symbol无法被序列化,因此触发报错。

解决方案

需要针对混合字体节点做特殊处理:通过getRangeFontName遍历文本的每个字符范围,逐个获取对应位置的字体信息,而非直接读取node.fontName。同时,字重信息也需要用getRangeFontWeight逐个范围获取,避免混合字体时node.fontWeight失效。

修改后的完整代码

选择监听逻辑(无需修改)

figma.on("selectionchange", () => {
  const selectedNodes = figma.currentPage.selection;

  if (selectedNodes && selectedNodes.length > 0) {
    const fontsInSelection = getFontsFromSelection(selectedNodes);
    figma.ui.postMessage({ type: "fontList", fonts: fontsInSelection });
  } else {
    figma.ui.postMessage({ type: "noElementSelected" });
  }
});

字体提取函数(核心修改)

function getFontsFromSelection(selection: ReadonlyArray<SceneNode>) {
  const fontsMap = new Map();

  function processNode(node: SceneNode) {
    if (node.type === "TEXT") {
      const textLength = node.characters.length;
      // 遍历每个字符范围获取字体,处理混合字体场景
      for (let i = 0; i < textLength; i++) {
        try {
          const font = node.getRangeFontName(i, i + 1) as FontName;
          if (!font) continue;
          
          const fontFamily = font.family;
          const fontStyle = font.style;
          const fontWeight = node.getRangeFontWeight(i, i + 1) || "";

          if (!fontsMap.has(fontFamily)) {
            fontsMap.set(fontFamily, new Set());
          }

          const stylesSet = fontsMap.get(fontFamily);
          // 生成唯一key解决对象无法去重的问题
          const styleKey = `${fontStyle}_${fontWeight}`;
          stylesSet.add({ style: fontStyle, weight: fontWeight, key: styleKey });
        } catch (e) {
          // 跳过异常范围,避免函数中断
          continue;
        }
      }
    } else if (node.type === "GROUP" || node.type === "FRAME") {
      for (const childNode of (node as GroupNode | FrameNode).children) {
        processNode(childNode);
      }
    }
  }

  for (const node of selection) {
    processNode(node);
  }

  const fonts = [];
  // 对字体样式去重
  for (const [fontFamily, fontStyles] of fontsMap) {
    const uniqueStyles = Array.from(fontStyles).reduce((acc, curr) => {
      if (!acc.some(item => item.key === curr.key)) {
        acc.push({ style: curr.style, weight: curr.weight });
      }
      return acc;
    }, [] as {style: string, weight: string | number}[]);
    
    fonts.push({ family: fontFamily, styles: uniqueStyles });
  }

  return fonts;
}

关键修改点说明

  1. 替换字体获取方式:用getRangeFontName(i, i+1)逐个字符范围获取字体,避免混合字体时node.fontName返回Symbol的问题。
  2. 可靠获取字重:用getRangeFontWeight获取对应范围的字重,替代直接读取node.fontWeight(混合字体场景下该属性无效)。
  3. 样式去重处理:通过生成唯一key解决Set中对象因引用不同无法去重的问题,确保最终返回的字体样式不重复。
  4. 异常容错:增加try-catch块跳过极少数无法获取字体的字符范围,避免整个函数执行中断。

内容的提问来源于stack exchange,提问作者pinata

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 14:17:05