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

如何用Node.js/Grunt拆分woff2字体为多字符集文件并识别Unicode范围

我太懂你这种糟心的情况了——之前那些工具要么只会粗暴按大小拆分,要么字符集识别得稀里糊涂,完全没法精准拆分出拉丁、西里尔和中文字符对应的独立字体文件。下面给你一套基于Node.js的可行方案,还能无缝整合到Grunt工作流里:

核心思路:精准匹配字符集的Unicode范围

要实现精准拆分,核心是先明确目标字符集的Unicode范围(或自动识别字符所属脚本),再过滤字体中对应字符的字形,最后生成新的字体文件。两种思路都可行,下面分别说明:

方案1:硬编码Unicode范围(稳定可靠)

如果你清楚目标字符集的标准Unicode范围,可以直接硬编码过滤,这种方式最稳定,不会出现识别错误。我们用Node.js的opentype.js库来解析和生成字体:

步骤1:安装依赖

npm install opentype.js woff2 --save-dev

(woff2用于把生成的TTF转成WOFF2,避免opentype.js直接输出WOFF2可能出现的兼容问题)

步骤2:编写拆分脚本(split-font.js)

const opentype = require('opentype.js');
const fs = require('fs');
const woff2 = require('woff2');

// 预定义各字符集的Unicode范围(可根据需求调整)
const characterSets = {
  latin: [
    [0x0020, 0x007E], // 基本拉丁(含标点、数字)
    [0x00A0, 0x00FF], // 拉丁补充-1(带重音的拉丁字符)
    [0x0100, 0x017F], // 拉丁扩展-A
    [0x0180, 0x024F], // 拉丁扩展-B
  ],
  cyrillic: [
    [0x0400, 0x04FF], // 西里尔基本字符
    [0x0500, 0x052F], // 西里尔补充
    [0x2DE0, 0x2DFF], // 西里尔扩展-A
    [0xA640, 0xA69F], // 西里尔扩展-B
  ],
  chinese: [
    [0x4E00, 0x9FFF], // 中日韩统一表意文字(基本区,覆盖绝大多数常用中文)
    [0x3400, 0x4DBF], // 扩展A区(生僻字)
  ]
};

// 判断字符码点是否在目标范围内
function isInRange(codePoint, ranges) {
  return ranges.some(([start, end]) => codePoint >= start && codePoint <= end);
}

// 核心拆分函数
async function splitFont(inputPath) {
  try {
    // 加载源字体文件
    const font = await opentype.load(inputPath);
    
    // 遍历每个字符集,生成对应子集字体
    for (const [setName, ranges] of Object.entries(characterSets)) {
      // 过滤出属于当前字符集的字形(跳过无Unicode码点的字形,比如空格以外的控制字符)
      const filteredGlyphs = font.glyphs.filter(glyph => {
        if (glyph.unicode === undefined) return false;
        return isInRange(glyph.unicode, ranges);
      });

      // 保留源字体的元数据,替换为过滤后的字形
      const newFont = new opentype.Font({
        familyName: font.familyName,
        styleName: font.styleName,
        unitsPerEm: font.unitsPerEm,
        ascender: font.ascender,
        descender: font.descender,
        glyphs: filteredGlyphs
      });

      // 先生成TTF,再转成WOFF2
      const ttfBuffer = newFont.toBuffer();
      const woff2Buffer = woff2.compress(ttfBuffer);
      
      // 保存文件
      const outputPath = `${inputPath.replace('.woff2', '')}-${setName}.woff2`;
      fs.writeFileSync(outputPath, woff2Buffer);
      console.log(`✅ 已生成子集字体:${outputPath}`);
    }
  } catch (err) {
    console.error('❌ 拆分失败:', err);
    throw err;
  }
}

// 执行拆分(替换成你的源字体路径)
splitFont('./your-source-font.woff2');

步骤3:整合到Grunt工作流

如果要把这个脚本加入Grunt构建流程,在Gruntfile.js里添加自定义任务:

module.exports = function(grunt) {
  grunt.initConfig({
    // 你的其他Grunt任务配置(比如sass、uglify等)
  });

  // 注册自定义字体拆分任务
  grunt.registerTask('split-font', 'Split font into latin, cyrillic, chinese subsets', function() {
    const done = this.async();
    const splitFont = require('./split-font.js');
    splitFont('./path/to/your-source-font.woff2')
      .then(() => done())
      .catch(err => {
        grunt.log.error(err);
        done(false);
      });
  });

  // 把拆分任务加入构建流程
  grunt.registerTask('build', ['clean', 'sass', 'split-font']);
};

方案2:自动识别字符所属脚本(灵活智能)

如果不想手动维护Unicode范围,可以用unicode-properties库自动判断字符所属的脚本(比如Latin、Cyrillic、Han),实现更灵活的拆分:

步骤1:安装额外依赖

npm install unicode-properties --save-dev

步骤2:修改拆分脚本的过滤逻辑

把之前的isInRange函数替换成以下代码:

const unicode = require('unicode-properties');

// 获取字符所属的脚本
function getCharacterScript(codePoint) {
  return unicode.getScript(codePoint);
}

// 修改过滤逻辑
const filteredGlyphs = font.glyphs.filter(glyph => {
  if (glyph.unicode === undefined) return false;
  const script = getCharacterScript(glyph.unicode);
  // 匹配对应脚本:Latin(拉丁)、Cyrillic(西里尔)、Han(中文)
  return (setName === 'latin' && script === 'Latin') ||
         (setName === 'cyrillic' && script === 'Cyrillic') ||
         (setName === 'chinese' && script === 'Han');
});
注意事项
  • 测试生成的子集字体:一定要验证目标字符是否能正常显示,避免遗漏复合字形(比如带重音的拉丁字符)。
  • 处理生僻字:如果需要包含中文生僻字,可以扩展chinese的Unicode范围,加入扩展B/C/D区。
  • 二进制依赖问题:woff2和unicode-properties需要编译二进制文件,如果安装失败,确保你的环境有Python 3.x和C++编译工具(比如Windows上的Visual Studio Build Tools,Mac上的Xcode Command Line Tools)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:19:51