From dbfce919fcceb2c7e40a76b92758c5b2f5022c97 Mon Sep 17 00:00:00 2001 From: Eric Fennis Date: Tue, 17 Oct 2023 21:27:46 +0200 Subject: [PATCH] Alias support for lucide package (#1592) * Setup aliases for lucide * Make aliases work for lucide package --- packages/lucide/package.json | 2 +- packages/lucide/rollup.config.mjs | 2 +- packages/lucide/src/iconsAndAliases.ts | 2 + packages/lucide/src/lucide.ts | 4 +- packages/lucide/src/replaceElement.ts | 2 +- .../tests/__snapshots__/lucide.spec.js.snap | 2 + packages/lucide/tests/lucide.spec.js | 20 ++++++-- .../building/generateAliasesFile.mjs | 48 ++++++++++++------- tools/build-icons/main.mjs | 2 + 9 files changed, 58 insertions(+), 26 deletions(-) create mode 100644 packages/lucide/src/iconsAndAliases.ts diff --git a/packages/lucide/package.json b/packages/lucide/package.json index a1a6687ee..d64cf1b44 100644 --- a/packages/lucide/package.json +++ b/packages/lucide/package.json @@ -25,7 +25,7 @@ "build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:bundles", "copy:license": "cp ../../LICENSE ./LICENSE", "clean": "rm -rf dist && rm -rf stats && rm -rf ./src/icons/*.ts", - "build:icons": "build-icons --output=./src --templateSrc=./scripts/exportTemplate.mjs --iconFileExtension=.ts", + "build:icons": "build-icons --output=./src --templateSrc=./scripts/exportTemplate.mjs --iconFileExtension=.ts --withAliases --aliasNamesOnly --aliasesFileExtension=.ts --exportFileName=index.ts", "build:types": "node ./scripts/buildTypes.mjs", "build:bundles": "rollup -c rollup.config.mjs", "test": "vitest run", diff --git a/packages/lucide/rollup.config.mjs b/packages/lucide/rollup.config.mjs index 9ee1de620..de4df672d 100644 --- a/packages/lucide/rollup.config.mjs +++ b/packages/lucide/rollup.config.mjs @@ -40,7 +40,7 @@ const configs = bundles ...( format === 'umd' ? [ replace({ - 'icons = {}': 'icons = allIcons', + 'icons = {}': 'icons = iconAndAliases', delimiters: ['', ''], preventAssignment: false, }), diff --git a/packages/lucide/src/iconsAndAliases.ts b/packages/lucide/src/iconsAndAliases.ts new file mode 100644 index 000000000..9ace9e4ce --- /dev/null +++ b/packages/lucide/src/iconsAndAliases.ts @@ -0,0 +1,2 @@ +export * from './icons' +export * from './aliases' diff --git a/packages/lucide/src/lucide.ts b/packages/lucide/src/lucide.ts index 6bf0e8e05..43e4ec4af 100644 --- a/packages/lucide/src/lucide.ts +++ b/packages/lucide/src/lucide.ts @@ -1,5 +1,5 @@ import replaceElement from './replaceElement'; -import * as allIcons from './icons'; +import * as iconAndAliases from './iconsAndAliases'; /** * Replaces all elements with matching nameAttr with the defined icons @@ -43,5 +43,5 @@ export { default as createElement } from './createElement'; /* Icons exports. */ -export { allIcons as icons }; +export { iconAndAliases as icons }; export * from './icons'; diff --git a/packages/lucide/src/replaceElement.ts b/packages/lucide/src/replaceElement.ts index 33fad25af..6b585bf5a 100644 --- a/packages/lucide/src/replaceElement.ts +++ b/packages/lucide/src/replaceElement.ts @@ -66,7 +66,7 @@ interface ReplaceElementOptions { const replaceElement = (element: Element, { nameAttr, icons, attrs }: ReplaceElementOptions) => { const iconName = element.getAttribute(nameAttr); - if(iconName == null) return + if (iconName == null) return const ComponentName = toPascalCase(iconName); diff --git a/packages/lucide/tests/__snapshots__/lucide.spec.js.snap b/packages/lucide/tests/__snapshots__/lucide.spec.js.snap index b39c78d90..2cb27d149 100644 --- a/packages/lucide/tests/__snapshots__/lucide.spec.js.snap +++ b/packages/lucide/tests/__snapshots__/lucide.spec.js.snap @@ -2,4 +2,6 @@ exports[`createIcons > should add custom attributes 1`] = `""`; +exports[`createIcons > should read elements from DOM and replace icon with alias name 1`] = `""`; + exports[`createIcons > should read elements from DOM and replace it with icons 1`] = `""`; diff --git a/packages/lucide/tests/lucide.spec.js b/packages/lucide/tests/lucide.spec.js index eb9c92933..b9bc24108 100644 --- a/packages/lucide/tests/lucide.spec.js +++ b/packages/lucide/tests/lucide.spec.js @@ -1,18 +1,17 @@ import { describe, it, expect } from 'vitest'; -import * as icons from '../src/icons'; -import { createIcons } from '../src/lucide'; +import { createIcons, icons } from '../src/lucide'; import fs from 'fs'; import path from 'path'; import { parseSync, stringify } from 'svgson'; const ICONS_DIR = path.resolve(__dirname, '../../../icons'); -const getOriginalSvg = (iconName) => { +const getOriginalSvg = (iconName, aliasName) => { const svgContent = fs.readFileSync(path.join(ICONS_DIR, `${iconName}.svg`), 'utf8'); const svgParsed = parseSync(svgContent); - svgParsed.attributes['data-lucide'] = iconName; - svgParsed.attributes['class'] = `lucide lucide-${iconName}`; + svgParsed.attributes['data-lucide'] = aliasName ?? iconName; + svgParsed.attributes['class'] = `lucide lucide-${aliasName ?? iconName}`; return stringify(svgParsed, { selfClose: false }); }; @@ -86,4 +85,15 @@ describe('createIcons', () => { expect(attributesAndValues).toEqual(expect.objectContaining(attrs)); }); + + it('should read elements from DOM and replace icon with alias name', () => { + document.body.innerHTML = ``; + + createIcons({ icons }); + + const svg = getOriginalSvg('grid-3x3', 'grid'); + + expect(document.body.innerHTML).toBe(svg) + expect(document.body.innerHTML).toMatchSnapshot() + }); }); diff --git a/tools/build-icons/building/generateAliasesFile.mjs b/tools/build-icons/building/generateAliasesFile.mjs index 53957da41..47e7a3181 100644 --- a/tools/build-icons/building/generateAliasesFile.mjs +++ b/tools/build-icons/building/generateAliasesFile.mjs @@ -12,6 +12,7 @@ export default async function generateAliasesFile({ iconFileExtension = '.js', aliases, aliasImportFileExtension, + aliasNamesOnly = false, separateAliasesFile = false, showLog = true, }) { @@ -24,14 +25,28 @@ export default async function generateAliasesFile({ // Generate Import for Icon VNodes await Promise.all( - icons.map(async (iconName) => { + icons.map(async (iconName, index) => { const componentName = toPascalCase(iconName); const iconAliases = aliases[iconName]?.aliases; - let importString = `// ${componentName} aliases\n`; + let importString = ''; - importString += getImportString(`${componentName}Icon`, iconName, aliasImportFileExtension); - importString += getImportString(`Lucide${componentName}`, iconName, aliasImportFileExtension); + if ((iconAliases != null && Array.isArray(iconAliases)) || !aliasNamesOnly) { + if (index > 0) { + importString += '\n'; + } + + importString += `// ${componentName} aliases\n`; + } + + if (!aliasNamesOnly) { + importString += getImportString(`${componentName}Icon`, iconName, aliasImportFileExtension); + importString += getImportString( + `Lucide${componentName}`, + iconName, + aliasImportFileExtension, + ); + } if (iconAliases != null && Array.isArray(iconAliases)) { await Promise.all( @@ -57,23 +72,24 @@ export default async function generateAliasesFile({ exportFileIcon, aliasImportFileExtension, ); - importString += getImportString( - `${componentNameAlias}Icon`, - exportFileIcon, - aliasImportFileExtension, - ); - importString += getImportString( - `Lucide${componentNameAlias}`, - exportFileIcon, - aliasImportFileExtension, - ); + if (!aliasNamesOnly) { + importString += getImportString( + `${componentNameAlias}Icon`, + exportFileIcon, + aliasImportFileExtension, + ); + + importString += getImportString( + `Lucide${componentNameAlias}`, + exportFileIcon, + aliasImportFileExtension, + ); + } }), ); } - importString += '\n'; - appendFile(importString, fileName, outputDirectory); }), ); diff --git a/tools/build-icons/main.mjs b/tools/build-icons/main.mjs index 1207a5d5a..ff0e34b46 100755 --- a/tools/build-icons/main.mjs +++ b/tools/build-icons/main.mjs @@ -31,6 +31,7 @@ const { importImportFileExtension = '', exportFileName = 'index.js', withAliases = false, + aliasNamesOnly = false, withDynamicImports = false, separateAliasesFile = false, aliasesFileExtension = '.js', @@ -66,6 +67,7 @@ async function buildIcons() { await generateAliasesFile({ iconNodes: icons, aliases, + aliasNamesOnly, iconFileExtension, outputDirectory: OUTPUT_DIR, fileExtension: aliasesFileExtension,