From f59c1f8f9a12d2da5b4e83589cb986c17e3f6ee0 Mon Sep 17 00:00:00 2001 From: Kacper Wojciechowski <39823706+jog1t@users.noreply.github.com> Date: Tue, 26 Nov 2024 01:24:58 +0100 Subject: [PATCH] feat: add custom icons kit to rivet-gg/icons --- .../project-generate-cloud-token-dialog.tsx | 4 +- biome.json | 2 +- packages/icons/README.md | 14 ++++- packages/icons/manifest.json | 22 +++++++ packages/icons/scripts/generateManifest.js | 61 ++++++++++++++++--- packages/icons/scripts/postinstall.js | 28 +++++++++ packages/icons/src/package.json | 5 +- 7 files changed, 123 insertions(+), 13 deletions(-) mode change 100644 => 100755 packages/icons/scripts/generateManifest.js diff --git a/apps/hub/src/domains/project/components/dialogs/project-generate-cloud-token-dialog.tsx b/apps/hub/src/domains/project/components/dialogs/project-generate-cloud-token-dialog.tsx index bbc9a5d5..e8d51ca3 100644 --- a/apps/hub/src/domains/project/components/dialogs/project-generate-cloud-token-dialog.tsx +++ b/apps/hub/src/domains/project/components/dialogs/project-generate-cloud-token-dialog.tsx @@ -19,7 +19,9 @@ export default function ProjectGenerateCloudTokenDialogContent({ projectId, onClose, }: ContentProps) { - const { data } = useSuspenseQuery(projectTokenCloudQueryOptions({ projectId })); + const { data } = useSuspenseQuery( + projectTokenCloudQueryOptions({ projectId }), + ); return ( <> diff --git a/biome.json b/biome.json index 03a28c03..a2710c82 100644 --- a/biome.json +++ b/biome.json @@ -8,7 +8,7 @@ "**/coverage/**", "**/tmp", "**/.turbo/**", - "*gen*" + "*.gen.*" ] }, "formatter": { diff --git a/packages/icons/README.md b/packages/icons/README.md index 8c378a61..18678c1d 100644 --- a/packages/icons/README.md +++ b/packages/icons/README.md @@ -16,10 +16,17 @@ Rivet Icons are a set of SVG icons that are used in Rivet products. This package ## Contributing -### Adding new icons +### Prerequisites + +Obtain a Font Awesome Pro license and set the `FONTAWESOME_PACKAGE_TOKEN` environment variable to your Font Awesome Pro token. This is required to download the premium icons. -Modify `generateManifest.js` to include new icons. The script will generate a new icon set with the new icons. Commit the changes to the `manifest.json` file. +### Adding new icons +1. Modify `generateManifest.js` to include new icons. +2. Run `./scripts/generateManifest.js` to generate a new `manifest.json` file. + - If you're getting an error: `Could not find package @fortawesome/pro-solid-svg-icons`, +3. Commit the changes to the `manifest.json` file. +4. Run `yarn rebuild @rivet-gg/icons` to generate a new icon set with the new icons. ## Troubleshooting @@ -30,3 +37,6 @@ Some icons used in the open-source Rivet products are part of the premium Font A ### Can't start/build project The description of these kinds of errors may vary. This package heavily depends on [postinstall scripts](https://yarnpkg.com/advanced/lifecycle-scripts#postinstall) from Yarn/npm. Make sure you didn't disable them accidentally. Turn on post-installation script support and run `yarn install` or `yarn rebuild @rivet-gg/cions` again. If there is still a problem, please contact us on [Discord](https://rivet.gg/discord"). + +### `Could not find package @fortawesome/pro-solid-svg-icons` when generating manifest +Make sure you have installed pro icons. If you're getting an error, you can try to install them manually by running `yarn add @fortawesome/pro-solid-svg-icons`, or run `yarn install` in `src` folder. Finally run `./scripts/generateManifest.js` again. diff --git a/packages/icons/manifest.json b/packages/icons/manifest.json index d8b42345..a628753e 100644 --- a/packages/icons/manifest.json +++ b/packages/icons/manifest.json @@ -2000,6 +2000,7 @@ { "icon": "faTableCellsColumnLock", "aliases": [] }, { "icon": "faTableCellsLarge", "aliases": ["faThLarge"] }, { "icon": "faTableCellsRowLock", "aliases": [] }, + { "icon": "faTableCellsRowUnlock", "aliases": [] }, { "icon": "faTableColumns", "aliases": ["faColumns"] }, { "icon": "faTableList", "aliases": ["faThList"] }, { @@ -2176,6 +2177,7 @@ { "icon": "faThumbsDown", "aliases": [] }, { "icon": "faThumbsUp", "aliases": [] }, { "icon": "faThumbtack", "aliases": ["faThumbTack"] }, + { "icon": "faThumbtackSlash", "aliases": ["faThumbTackSlash"] }, { "icon": "faThunderstorm", "aliases": ["faThunderstorm"] }, { "icon": "faTicket", "aliases": [] }, { "icon": "faTicketAlt", "aliases": ["faTicketAlt"] }, @@ -2403,6 +2405,7 @@ "aliases": ["faLadderWater", "faSwimmingPool"] }, { "icon": "faWaveSquare", "aliases": [] }, + { "icon": "faWebAwesome", "aliases": [] }, { "icon": "faWeight", "aliases": ["faWeight"] }, { "icon": "faWeightHanging", "aliases": [] }, { "icon": "faWeightScale", "aliases": ["faWeight"] }, @@ -2561,6 +2564,7 @@ { "icon": "faDAndD", "aliases": [] }, { "icon": "faDAndDBeyond", "aliases": [] }, { "icon": "faDailymotion", "aliases": [] }, + { "icon": "faDartLang", "aliases": [] }, { "icon": "faDashcube", "aliases": [] }, { "icon": "faDebian", "aliases": [] }, { "icon": "faDeezer", "aliases": [] }, @@ -2612,6 +2616,7 @@ { "icon": "faFirstdraft", "aliases": [] }, { "icon": "faFlickr", "aliases": [] }, { "icon": "faFlipboard", "aliases": [] }, + { "icon": "faFlutter", "aliases": [] }, { "icon": "faFly", "aliases": [] }, { "icon": "faFontAwesome", @@ -4431,6 +4436,7 @@ { "icon": "faDiamondHalf", "aliases": [] }, { "icon": "faDiamondHalfStroke", "aliases": [] }, { "icon": "faDiamondTurnRight", "aliases": ["faDirections"] }, + { "icon": "faDiamonds4", "aliases": [] }, { "icon": "faDice", "aliases": [] }, { "icon": "faDiceD10", "aliases": [] }, { "icon": "faDiceD12", "aliases": [] }, @@ -5092,6 +5098,7 @@ { "icon": "faGlobePointer", "aliases": [] }, { "icon": "faGlobeSnow", "aliases": [] }, { "icon": "faGlobeStand", "aliases": [] }, + { "icon": "faGlobeWifi", "aliases": [] }, { "icon": "faGloveBoxing", "aliases": ["faGloveBoxing"] }, { "icon": "faGoalNet", "aliases": [] }, { "icon": "faGolfBall", "aliases": ["faGolfBall"] }, @@ -5449,6 +5456,7 @@ { "icon": "faHumidity", "aliases": ["faHumidity"] }, { "icon": "faHundredPoints", "aliases": ["fa100"] }, { "icon": "faHurricane", "aliases": [] }, + { "icon": "faHydra", "aliases": [] }, { "icon": "faHyphen", "aliases": [] }, { "icon": "faI", "aliases": [] }, { "icon": "faICursor", "aliases": [] }, @@ -5625,6 +5633,7 @@ { "icon": "faLightbulbExclamation", "aliases": [] }, { "icon": "faLightbulbExclamationOn", "aliases": [] }, { "icon": "faLightbulbGear", "aliases": [] }, + { "icon": "faLightbulbMessage", "aliases": [] }, { "icon": "faLightbulbOn", "aliases": [] }, { "icon": "faLightbulbSlash", "aliases": [] }, { "icon": "faLighthouse", "aliases": [] }, @@ -6033,6 +6042,7 @@ "icon": "faOctagonXmark", "aliases": ["faTimesOctagon", "faXmarkOctagon"] }, + { "icon": "faOctopus", "aliases": [] }, { "icon": "faOilCan", "aliases": [] }, { "icon": "faOilCanDrip", "aliases": [] }, { "icon": "faOilTemp", "aliases": ["faOilTemp"] }, @@ -7201,9 +7211,12 @@ { "icon": "faTable", "aliases": [] }, { "icon": "faTableCells", "aliases": ["faTh"] }, { "icon": "faTableCellsColumnLock", "aliases": [] }, + { "icon": "faTableCellsColumnUnlock", "aliases": [] }, { "icon": "faTableCellsLarge", "aliases": ["faThLarge"] }, { "icon": "faTableCellsLock", "aliases": [] }, { "icon": "faTableCellsRowLock", "aliases": [] }, + { "icon": "faTableCellsRowUnlock", "aliases": [] }, + { "icon": "faTableCellsUnlock", "aliases": [] }, { "icon": "faTableColumns", "aliases": ["faColumns"] }, { "icon": "faTableLayout", "aliases": [] }, { "icon": "faTableList", "aliases": ["faThList"] }, @@ -7424,6 +7437,7 @@ { "icon": "faThumbsDown", "aliases": [] }, { "icon": "faThumbsUp", "aliases": [] }, { "icon": "faThumbtack", "aliases": ["faThumbTack"] }, + { "icon": "faThumbtackSlash", "aliases": ["faThumbTackSlash"] }, { "icon": "faThunderstorm", "aliases": ["faThunderstorm"] }, { "icon": "faThunderstormMoon", "aliases": ["faThunderstormMoon"] }, { "icon": "faThunderstormSun", "aliases": ["faThunderstormSun"] }, @@ -7748,6 +7762,7 @@ { "icon": "faUserAlt", "aliases": ["faUserAlt"] }, { "icon": "faUserAltSlash", "aliases": ["faUserAltSlash"] }, { "icon": "faUserAstronaut", "aliases": [] }, + { "icon": "faUserBeardBolt", "aliases": [] }, { "icon": "faUserBountyHunter", "aliases": [] }, { "icon": "faUserChart", "aliases": ["faUserChart"] }, { "icon": "faUserCheck", "aliases": [] }, @@ -7788,6 +7803,7 @@ "icon": "faUserHelmetSafety", "aliases": ["faUserConstruction", "faUserHardHat"] }, + { "icon": "faUserHoodie", "aliases": [] }, { "icon": "faUserInjured", "aliases": [] }, { "icon": "faUserLarge", "aliases": ["faUserAlt"] }, { "icon": "faUserLargeSlash", "aliases": ["faUserAltSlash"] }, @@ -8040,5 +8056,11 @@ { "icon": "faZzz", "aliases": ["faZzz"] } ], "prefix": "fas" + }, + "@awesome.me/kit-63db24046b/icons/kit/custom": { + "icons": [ + { "icon": "faActors", "aliases": [] }, + { "icon": "faSelect", "aliases": [] } + ] } } diff --git a/packages/icons/scripts/generateManifest.js b/packages/icons/scripts/generateManifest.js old mode 100644 new mode 100755 index d6c8fd17..4b0bd4be --- a/packages/icons/scripts/generateManifest.js +++ b/packages/icons/scripts/generateManifest.js @@ -1,9 +1,15 @@ // @ts-check const fs = require("node:fs"); -const { getPackageInfo } = require("local-pkg"); +const { getPackageInfo, importModule, resolveModule } = require("local-pkg"); +const { join } = require("node:path"); const icons = new Set(); +const searchPaths = [ + join(__dirname, "..", "src", "node_modules"), + join(__dirname, "..", "..", "..", "node_modules"), +]; + function faCamelCase(str) { const [firstLetter, ...restLetters] = str.replace(/-./g, (g) => g[1].toUpperCase(), @@ -12,22 +18,27 @@ function faCamelCase(str) { } async function registerIcons(iconModuleName) { - const info = await getPackageInfo(iconModuleName); + const info = await getPackageInfo(iconModuleName, { + paths: searchPaths, + }); if (!info) { - console.error("Could not find package", iconModuleName); - return; + throw new Error(`Could not find package ${iconModuleName}`); } const { rootPath } = info; + const module = resolveModule(iconModuleName, { paths: [rootPath] }); + if (!module) { + throw new Error(`Could not resolve module ${iconModuleName}`); + } const files = await fs.promises.readdir(rootPath); const iconFiles = files.filter( (file) => file.startsWith("fa") && file.endsWith(".js"), ); - const iconsModule = require(iconModuleName); + const iconsModule = await importModule(module); const foundIcons = []; @@ -54,14 +65,50 @@ async function registerIcons(iconModuleName) { }; } +function registerCustomIcons(iconKit) { + const module = require.resolve(iconKit, { paths: searchPaths }); + + if (!module) { + throw new Error(`Could not resolve module ${iconKit}`); + } + + const customIcons = require(module); + + const foundIcons = []; + + for (const [iconName, iconDefinition] of Object.entries(customIcons)) { + const aliases = iconDefinition.icon?.[2].filter( + (alias) => typeof alias === "string", + ); + + if ( + icons.has(iconDefinition.iconName) || + aliases.some((alias) => icons.has(alias)) + ) { + continue; + } + + foundIcons.push({ icon: iconName, aliases: aliases.map(faCamelCase) }); + } + + return { [iconKit]: { icons: foundIcons } }; +} + async function generateManifest() { const manifest = { ...(await registerIcons("@fortawesome/free-solid-svg-icons")), ...(await registerIcons("@fortawesome/free-brands-svg-icons")), ...(await registerIcons("@fortawesome/pro-solid-svg-icons")), + ...registerCustomIcons("@awesome.me/kit-63db24046b/icons/kit/custom"), }; - fs.writeFileSync("./manifest.json", JSON.stringify(manifest)); + fs.writeFileSync( + join(__dirname, "../manifest.json"), + JSON.stringify(manifest), + ); } -generateManifest().catch(() => process.exit(1)); +generateManifest().catch((e) => { + console.error(e); + process.exit(1); +}); diff --git a/packages/icons/scripts/postinstall.js b/packages/icons/scripts/postinstall.js index 7540134d..fe861748 100644 --- a/packages/icons/scripts/postinstall.js +++ b/packages/icons/scripts/postinstall.js @@ -26,6 +26,10 @@ if (process.env.FONTAWESOME_PACKAGE_TOKEN) { npmAlwaysAuth: true npmRegistryServer: 'https://npm.fontawesome.com/' npmAuthToken: \${FONTAWESOME_PACKAGE_TOKEN} + awesome.me: + npmAlwaysAuth: true + npmRegistryServer: "https://npm.fontawesome.com/" + npmAuthToken: \${FONTAWESOME_PACKAGE_TOKEN} `, ); @@ -74,6 +78,18 @@ let indexTsSource = dedent` for (const [pkg, { icons }] of Object.entries(manifest)) { const pkgExists = pkg.includes("pro") ? isPro : true; + const isCustom = pkg.startsWith("@awesome.me/kit-"); + + if (isCustom) { + if (!pkgExists) { + const iconNames = icons.map(({ icon }) => icon); + const exp = iconNames.map((icon) => `definition as ${icon}`).join(", "); + indexTsSource += `export { ${exp} } from "@fortawesome/free-solid-svg-icons/faSquare";\n`; + } else { + indexTsSource += `export * from "${pkg}";\n`; + } + continue; + } for (const { icon, aliases } of icons) { if (!indexTsSource.includes(`export { definition as ${icon} }`)) { @@ -101,6 +117,18 @@ import {type IconPack} from "@fortawesome/fontawesome-common-types";\n`; for (const [pkg, { icons }] of Object.entries(manifest)) { const pkgExists = pkg.includes("pro") ? isPro : true; + const isCustom = pkg.startsWith("@awesome.me/kit-"); + + if (isCustom) { + const iconNames = icons.map(({ icon }) => icon); + if (!pkgExists) { + const exp = iconNames.map((icon) => `definition as ${icon}`).join(", "); + iconsPackTsSource += `import {${exp}} from "@fortawesome/free-solid-svg-icons/faSquare";\n`; + } else { + iconsPackTsSource += `import {${iconNames.join(",")}} from "${pkg}";\n`; + } + continue; + } for (const { icon } of icons) { if (iconsPackTsSource.includes(`import {definition as ${icon}}`)) { diff --git a/packages/icons/src/package.json b/packages/icons/src/package.json index 38abd360..26929b94 100644 --- a/packages/icons/src/package.json +++ b/packages/icons/src/package.json @@ -2,7 +2,8 @@ "name": "@rivet-gg/internal-icons", "private": true, "dependencies": { - "@fortawesome/pro-regular-svg-icons": "^6.6.0", - "@fortawesome/pro-solid-svg-icons": "^6.6.0" + "@awesome.me/kit-63db24046b": "^1.0.11", + "@fortawesome/pro-regular-svg-icons": "6.6.0", + "@fortawesome/pro-solid-svg-icons": "6.6.0" } }