将 SVG 集合转换为 Iconify JSON
本示例展示了如何将包含大量 SVG 文件的目录转换为 Iconify JSON 格式。
作为数据源,本示例使用了来自 Templarian/MaterialDesign-SVG 仓库的 Material Design 图标,该仓库也可作为 @mdi/svg NPM 包获取。
安装依赖:
npm install @iconify/tools @mdi/svg --save然后创建文件 convert-mdi.ts 并填入以下内容:
convert-mdi.ts
ts
import { promises as fs } from 'fs';
import { dirname } from 'path';
// Installation: npm install --save-dev @iconify/tools @mdi/svg
import {
importDirectory,
cleanupSVG,
parseColors,
isEmptyColor,
runSVGO,
cleanupIconKeyword,
} from '@iconify/tools';
import type { IconifyInfo } from '@iconify/types';
// File to save icon set to
const target = 'json/mdi.json';
// SVG files location
const sourcePackageJSON = require.resolve('@mdi/svg/package.json');
const sourceSVGDir = dirname(sourcePackageJSON) + '/svg';
// Metadata (specific to MDI example, remove this for your code)
const metadataSource: string | null = require.resolve('@mdi/svg/meta.json');
// Prefix to use for icon set
const prefix = 'mdi';
// Expected icon size. Used in validating icons, remove if you do not need to validate icons
const expectedSize = 24;
// Icon set information
const info: IconifyInfo = {
name: 'Material Design Icons',
author: {
name: 'Austin Andrews',
url: 'https://github.com/Templarian/MaterialDesign',
},
license: {
title: 'Open Font License',
url: 'https://raw.githubusercontent.com/Templarian/MaterialDesign/master/LICENSE',
spdx: 'OFL-1.1',
},
height: 24,
samples: ['account-check', 'bell-alert-outline', 'calendar-edit'],
};
// Import icons
(async function () {
// Import icons
const iconSet = await importDirectory(sourceSVGDir, {
prefix,
});
// Set info
iconSet.info = info;
// Validate, clean up, fix palette and optimise
await iconSet.forEach((name, type) => {
if (type !== 'icon') {
return;
}
// Get SVG instance for parsing
const svg = iconSet.toSVG(name);
if (!svg) {
// Invalid icon
iconSet.remove(name);
return;
}
// Check icon size
const viewBox = svg.viewBox;
if (viewBox.width !== expectedSize || viewBox.height !== expectedSize) {
console.error(
`Icon ${name} has invalid dimensions: ${viewBox.width} x ${viewBox.height}`
);
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`);
// Add metadata from meta.json
if (metadataSource) {
interface MDIMetaDataItem {
id: string;
name: string;
codepoint: string;
aliases: string[];
tags: string[];
author: string;
version: string;
}
const metaContent = JSON.parse(
await fs.readFile(metadataSource, 'utf8')
) as MDIMetaDataItem[];
metaContent.forEach((entry) => {
const { name, aliases, tags } = entry;
const cleanName = cleanupIconKeyword(name);
if (iconSet.entries[cleanName] === void 0) {
console.error(`Missing icon: ${cleanName}`);
return;
}
// Add categories
tags.forEach((category) => {
iconSet.toggleCategory(cleanName, category, true);
});
// Add aliases
aliases.forEach((alias) => {
const cleanAlias = cleanupIconKeyword(alias);
if (iconSet.entries[cleanAlias] === void 0) {
iconSet.setAlias(cleanAlias, cleanName);
}
});
});
}
// Export to IconifyJSON, convert to string
const output = JSON.stringify(iconSet.export(), null, '\t');
// Create directory for output if missing
const dir = dirname(target);
try {
await fs.mkdir(dir, {
recursive: true,
});
} catch (err) {
//
}
// Save to file
await fs.writeFile(target, output, 'utf8');
console.log(`Saved ${target} (${output.length} bytes)`);
})().catch((err) => {
console.error(err);
});假设 TypeScript 已配置为编译到 lib 目录,将文件编译为 JavaScript 并运行:
node lib/convert-mdi如果您不使用 TypeScript,请从代码中移除类型注解。这应该不难,因为需要删除的行数并不多。
准备好的项目可在 Iconify Tools GitHub 仓库 中获取。
它是如何工作的?
上述代码中的注释解释了具体过程。
流程很简单:
- importDirectory() 从 @mdi/svg 包的 "svg" 目录导入所有图标。
- 使用 iconSet.forEach() 遍历所有图标以执行以下操作:
- 使用 toSVG() 获取可通过各种函数进行操作的 SVG 实例。
- 使用 cleanupSVG() 清理代码(MDI 的代码已经很干净,因此无需清理,但对于其他图标集则是必要的)。
- 使用 parseColors() 将默认颜色更改为 "currentColor"。
- 使用 runSVGO() 优化图标代码。
- 使用 iconSet.fromSVG() 更新图标集中的图标数据。
- 然后脚本处理元数据:为所有图标添加分类和别名。
- 使用 iconSet.export() 将图标集导出为 JSON 文件。