Created
December 21, 2023 02:42
-
-
Save ngbrown/c6f46ea7d9c75511faf0911c30ddac67 to your computer and use it in GitHub Desktop.
Generate TypeScript files containing Font Awsome Icons from kit metadata
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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