Skip to content

Instantly share code, notes, and snippets.

@ngbrown
Created December 21, 2023 02:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ngbrown/c6f46ea7d9c75511faf0911c30ddac67 to your computer and use it in GitHub Desktop.
Save ngbrown/c6f46ea7d9c75511faf0911c30ddac67 to your computer and use it in GitHub Desktop.
Generate TypeScript files containing Font Awsome Icons from kit metadata
#!/usr/bin/env node
/* eslint-env node */
import fs from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
async function main() {
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const icons_json_path = path.resolve(
__dirname,
"../app/assets/fontawesome/icons.json"
);
const icons_json = await fs.readFile(icons_json_path, {
encoding: "utf8",
flag: "r",
});
const icons = JSON.parse(icons_json);
const sets = [
["custom", "fak", "custom-svg-icons"],
["regular", "far", "pro-regular-svg-icons"],
["solid", "fas", "pro-solid-svg-icons"],
];
for (const [style, prefix, output_path] of sets) {
const output_filename = path.resolve(
__dirname,
"../app/assets/fontawesome",
`${output_path}/index.ts`
);
await generate_output(icons, style, prefix, output_filename);
}
console.log("Icon generation completed");
}
/**
* @param {{[p: string]: T}} icons
* @param {string} prefix
* @param {string} style
* @param {string} output_filename
*/
async function generate_output(icons, style, prefix, output_filename) {
let file_out;
try {
file_out = await fs.open(output_filename, "w");
await generate_output_file(icons, prefix, style, file_out);
} finally {
await file_out?.close();
}
}
/**
* @param {{[p: string]: T}} icons
* @param {string} prefix
* @param {string} style
* @param {FileHandle} file_out
*/
async function generate_output_file(icons, prefix, style, file_out) {
console.log(`## Generating "${style}" pack (prefix "${prefix}")`);
await file_out.write(`import type { IconDefinition, IconPrefix, IconPack } from "@fortawesome/fontawesome-common-types";
export type { IconDefinition, IconLookup, IconName, IconPrefix, IconPack } from "@fortawesome/fontawesome-common-types";
export const prefix: IconPrefix = "${prefix}";
`);
const exportedIconNames = [];
const icon_entries = Object.entries(icons).sort((a, b) =>
a[0].localeCompare(b[0])
);
for (const [icon_name, details] of icon_entries) {
if (details.styles.indexOf(style) === -1) {
continue;
}
console.log(icon_name);
const svg = details.svg[style];
if (svg == null) {
throw new Error(`No svg found for "${icon_name}", style ${style}`);
}
const exportedIconName = `fa${kebobToUpperCamel(icon_name)}`;
exportedIconNames.push(exportedIconName);
const aliases = [];
if (details.aliases?.unicodes?.composite != null) {
for (const unicode_hex of details.aliases.unicodes.composite) {
aliases.push(parseInt(unicode_hex, 16).toString());
}
}
if (details.aliases?.names != null) {
for (const alias of details.aliases.names) {
aliases.push(alias);
}
}
const alias_text = aliases.length > 0 ? `"${aliases.join('", "')}"` : "";
await file_out.write(`export const ${exportedIconName}: IconDefinition = {
prefix: "${prefix}",
`);
if (prefix === "fak") {
await file_out.write(`// @ts-ignore
`);
}
await file_out.write(` iconName: "${icon_name}",
icon: [${svg.width}, ${svg.height}, [${alias_text}], "${details.unicode}", "${svg.path}"]
};
`);
if (details.aliases?.names != null) {
for (const alias of details.aliases.names) {
const aliasIconName = `fa${kebobToUpperCamel(alias)}`;
exportedIconNames.push(aliasIconName);
await file_out.write(`export const ${aliasIconName} = ${exportedIconName};
`);
}
}
}
await file_out.write(`const icons: IconPack = {
`);
for (const exportedIconName of exportedIconNames) {
await file_out.write(` ${exportedIconName},
`);
}
await file_out.write(`};
export { icons as ${prefix} };
`);
console.log();
}
/**
* @param {string} string
* @return {string}
*/
function capitalize(string) {
if (string.length === 0) return "";
return string[0].toUpperCase() + string.slice(1);
}
/**
* @param {string} string
* @return {string}
*/
function kebobToUpperCamel(string) {
return string.split("-").map(capitalize).join("");
}
await main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment