Skip to content

将 Font Awesome Pro 转换为 Iconify JSON

使用 FontAwesome Pro git 仓库

本示例展示了如何将 FontAwesome Pro 的 SVG 文件转换为 Iconify JSON 格式。

本示例假设您有权访问 FontAwesome Pro 仓库。如果您拥有有效的许可证,您应该能够访问它。

创建文件 convert-fa-pro.ts 并填入以下内容:

convert-fa-pro.ts
tsimport { promises as fs } from 'fs';
import {
   downloadGitRepo,
   importDirectory,
   cleanupSVG,
   parseColors,
   isEmptyColor,
   runSVGO,
} from '@iconify/tools';
import type { IconifyInfo } from '@iconify/types';

// Clone repository?
// Set to false if repository is already unpacked to directory set in 'faRepoDir' variable.
const cloneFromGitHub = true;
const faRepoURL: string | null =
   'git@github.com:FortAwesome/Font-Awesome-Pro.git';
const faRepoBranch = 'master';

// Directory for FontAwesome Pro repository (automatically downloaded if information above is set)
const faRepoDir = 'fa-pro';

// Themes to parse
const themes = ['brands', 'duotone', 'light', 'regular', 'solid'];

// Directory to export icon sets to
const targetDirectory = 'json';

// Information
const baseInfo: IconifyInfo = {
   name: 'Font Awesome',
   author: {
       name: 'Font Awesome',
   },
   license: {
       title: 'Commercial License',
       url: 'https://fontawesome.com/license',
   },
   height: 32,
};

// Base prefix without theme
const basePrefix = 'fa-pro-';

// Do stuff
(async function () {
   // Download repository
   let sourceDir = faRepoDir;
   if (cloneFromGitHub) {
       const downloadResult = await downloadGitRepo({
           target: faRepoDir,
           remote: faRepoURL,
           branch: faRepoBranch,
           log: true,
       });
       sourceDir = downloadResult.contentsDir;
   }

   // Create directory for output if missing
   try {
       await fs.mkdir(targetDirectory, {
           recursive: true,
       });
   } catch (err) {
       //
   }

   // Parse all configured themes
   for (let i = 0; i < themes.length; i++) {
       const theme = themes[i];
       const source = sourceDir + '/svgs/' + theme;
       const prefix = basePrefix + theme;

       // Import icons
       const iconSet = await importDirectory(source, {
           prefix,
       });

       // Set info
       const info: IconifyInfo = JSON.parse(JSON.stringify(baseInfo));
       const themeName = theme.toUpperCase().slice(0, 1) + theme.slice(1);
       info.name += ' ' + themeName;
       iconSet.info = info;

       // Validate, clean up, fix palette and optimise
       iconSet.forEachSync((name, type) => {
           if (type !== 'icon') {
               return;
           }

           // Get SVG instance for parsing
           const svg = iconSet.toSVG(name);
           if (!svg) {
               // Invalid icon
               iconSet.remove(name);
               return;
           }

           // Clean up and optimise icons
           try {
               // Clean up icon code
               cleanupSVG(svg);

               // Replace color with currentColor, add if missing
               parseColors(svg, {
                   defaultColor: 'currentColor',
                   callback: (attr, colorStr, color) => {
                       return !color || isEmptyColor(color) ? colorStr : 'currentColor';
                   },
               });

               // Optimise
               runSVGO(svg);
           } catch (err) {
               // Invalid icon
               console.error(`Error parsing ${name}:`, err);
               iconSet.remove(name);
               return;
           }

           // Update icon from SVG instance
           iconSet.fromSVG(name, svg);
       });
       console.log(`Imported ${iconSet.count()} icons for ${info.name}`);

       // Export to IconifyJSON, convert to string
       const output = JSON.stringify(iconSet.export(), null, '\t');

       // Save to file
       const target = targetDirectory + '/' + prefix + '.json';
       await fs.writeFile(target, output, 'utf8');

       console.log(`Saved ${target} (${output.length} bytes)`);
   }
})().catch((err) => {
   console.error(err);
});

假设 TypeScript 已配置为编译到 lib 目录,将文件编译为 JavaScript 并运行:

node lib/convert-fa-pro

如果您不使用 TypeScript,请从代码中移除类型声明。 这应该不难,因为需要移除的行数并不多。

准备好的项目可在 Iconify Tools GitHub 仓库 中获取。

使用 FontAwesome Pro npm 库

生成 JSON 文件的另一种方法是使用 FontAwesome 提供的 NPM 库。

本示例假设您有权访问 FontAwesome Pro npm 库。如果您尚未获得库的访问权限,请参阅官方指南。

创建文件 convert-fa-pro-npm.ts 并填入以下内容:

convert-fa-pro-npm.ts
tsimport fs from 'fs';
import { blankIconSet } from '@iconify/tools';
import { dirname, join } from 'path';
// import the fonts you want to convert
import {
 far as faProRegularIcons,
 prefix as faProRegularPrefix,
} from '@fortawesome/pro-regular-svg-icons';
import {
 fas as faProSolidIcons,
 prefix as faProSolidPrefix,
} from '@fortawesome/pro-solid-svg-icons';

import {
 fat as faProThinIcons,
 prefix as faProThinPrefix,
} from '@fortawesome/pro-thin-svg-icons';
import {
 fal as faProLightIcons,
 prefix as faProLightPrefix,
} from '@fortawesome/pro-light-svg-icons';

import type { IconifyInfo } from '@iconify/types';

// put the icons and the prefix you want them to have together in one object.
const icons = [
 { icons: faProRegularIcons, prefix: /* faProRegularPrefix */ 'fa' },
 { icons: faProSolidIcons, prefix: faProSolidPrefix },
 { icons: faProThinIcons, prefix: faProThinPrefix },
 { icons: faProLightIcons, prefix: faProLightPrefix },
] as const;

// set the location where you want the generated json files to appear.
const collectionTargetDir = join(
 import.meta.dirname,
'font-awesome-iconify'
);

// set the base info
const baseInfo = {
 name: 'Font Awesome',
 author: {
   name: 'Font Awesome',
 },
 license: {
   title: 'Commercial License',
   url: 'https://fontawesome.com/license',
 },
 height: 512,
} as const satisfies IconifyInfo;

// iterate through the icons and generate the json files
for (const iconData of icons) {
 const iconSet = blankIconSet(iconData.prefix);
 iconSet.info = structuredClone(baseInfo);
 for (const { icon, iconName } of Object.values(iconData.icons)) {
   const [width, height, ligatures, unicode, svgPathData] = icon;

   // handle strings and array differently from each other
   const body =
     typeof svgPathData === 'string'
       ? `<path fill="currentColor" d="${svgPathData}" />`
       : `<g fill="currentColor">${svgPathData.map((x) => `<path d="${x}" />`).join('')}</g>`;

   iconSet.setIcon(iconName, {
     body,
     height,
     width,
   });

   ligatures.forEach((x) => {
     // ignore the aliases that are numbers.
     if (Number.isNaN(+x)) iconSet.setAlias(x, iconName);
   });
 }

 // generate the json
 const data = iconSet.export();
 const dataJson = JSON.stringify(data, null, 2);

 // set the path target for the json file
 const jsonTargetDir = join(collectionTargetDir, iconData.prefix);
 const fileName = join(jsonTargetDir, 'icons.json');

 // create the file
 fs.mkdirSync(jsonTargetDir, { recursive: true });
 fs.writeFileSync(fileName, dataJson, {
   encoding: 'utf-8',
 });
}

如果您使用的是 Node.js V22.6.0 或更高版本,您可以原生运行 TypeScript 文件。

node convert-fa-pro-npm.ts

如果您的 Node.js 版本低于 v22.6.0,则需要在命令中添加 --experimental-strip-types

node --experimental-strip-types convert-fa-pro-npm.ts

或者,您也可以手动从代码中移除类型声明,然后将其作为 JS 文件运行。