From faa915c3aa397b7145e32a44aaabb33931b5d4e0 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Tue, 10 Dec 2024 15:10:46 +0800 Subject: [PATCH] feat: support arbitrary names for custom icons, fix #265 (#317) --- README.md | 25 ++++++++++++ playground/components/ShowcaseFixture.vue | 12 ++++++ playground/icons/custom1/Foo_Bar_Zag.svg | 8 ++++ playground/nuxt.config.ts | 3 ++ playground/test/nuxt/output/fixtures.html | 50 +++++++++++++++++++++++ src/collections.ts | 12 ++++-- src/types.ts | 13 ++++++ 7 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 playground/icons/custom1/Foo_Bar_Zag.svg diff --git a/README.md b/README.md index 7a1cce2a..3a52cb4c 100644 --- a/README.md +++ b/README.md @@ -187,6 +187,31 @@ export default defineNuxtConfig({ }) ``` +### Case Sensitive Custom Collections + +Before `v1.10`, due to the limitation of Iconify's previous convention, all custom icons were normalized to `kebab-case` with a warning. Thanks to the updates on Iconify side, starting from `v1.10`, you can opt-in to use case-sensitive custom collections and by pass the normalization. + +```ts +export default defineNuxtConfig({ + modules: [ + '@nuxt/icon' + ], + icon: { + customCollections: [ + { + prefix: 'my-icon', + dir: './assets/my-icons', + normalizeIconName: false, // <-- this + }, + ], + }, +}) +``` + +Which enable to use `assets/my-icons/FooBar.svg` as `my-icon:FooBar`, for example. + +`normalizeIconName` is default to `true` for backward compatibility, and will be flipped in the future major version. See [#265](https://github.com/nuxt/icon/issues/265) for more context. + ### Icon Customization To update the default size (`1em`) of the ``, create an `app.config.ts` with the `icon.size` property. diff --git a/playground/components/ShowcaseFixture.vue b/playground/components/ShowcaseFixture.vue index d19e5987..21630994 100644 --- a/playground/components/ShowcaseFixture.vue +++ b/playground/components/ShowcaseFixture.vue @@ -77,6 +77,18 @@ defineProps<{ :mode :customize /> + +

Custom icons with `prefix: ''` from local fs: diff --git a/playground/icons/custom1/Foo_Bar_Zag.svg b/playground/icons/custom1/Foo_Bar_Zag.svg new file mode 100644 index 00000000..ede640aa --- /dev/null +++ b/playground/icons/custom1/Foo_Bar_Zag.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/playground/nuxt.config.ts b/playground/nuxt.config.ts index d94153ab..0237f609 100644 --- a/playground/nuxt.config.ts +++ b/playground/nuxt.config.ts @@ -40,14 +40,17 @@ export default defineNuxtConfig({ { prefix: 'custom1', dir: './icons/custom1', + normalizeIconName: false, }, { prefix: 'custom-parts', dir: './icons/custom-parts', + normalizeIconName: false, }, { prefix: '', dir: './icons/no-prefix', + normalizeIconName: false, }, ], serverBundle: 'remote', diff --git a/playground/test/nuxt/output/fixtures.html b/playground/test/nuxt/output/fixtures.html index a6bc3fac..669feff3 100644 --- a/playground/test/nuxt/output/fixtures.html +++ b/playground/test/nuxt/output/fixtures.html @@ -195,6 +195,56 @@ d="M281.44 397.667H438.32C443.326 397.667 448.118 395.908 452.453 393.427C456.789 390.946 461.258 387.831 463.76 383.533C466.262 379.236 468.002 374.36 468 369.399C467.998 364.437 466.266 359.563 463.76 355.268L357.76 172.947C355.258 168.65 352.201 165.534 347.867 163.053C343.532 160.573 337.325 158.813 332.32 158.813C327.315 158.813 322.521 160.573 318.187 163.053C313.852 165.534 310.795 168.65 308.293 172.947L281.44 219.587L227.733 129.13C225.229 124.834 222.176 120.307 217.84 117.827C213.504 115.346 208.713 115 203.707 115C198.701 115 193.909 115.346 189.573 117.827C185.238 120.307 180.771 124.834 178.267 129.13L46.8267 355.268C44.3208 359.563 44.0022 364.437 44 369.399C43.9978 374.36 44.3246 379.235 46.8267 383.533C49.3288 387.83 53.7979 390.946 58.1333 393.427C62.4688 395.908 67.2603 397.667 72.2667 397.667H171.2C210.401 397.667 238.934 380.082 258.827 346.787L306.88 263.4L332.32 219.587L410.053 352.44H306.88L281.44 397.667ZM169.787 352.44H100.533L203.707 174.36L256 263.4L221.361 323.784C208.151 345.387 193.089 352.44 169.787 352.44Z" fill="#00DC82" > +

diff --git a/src/collections.ts b/src/collections.ts index 20b8d555..6f8635b9 100644 --- a/src/collections.ts +++ b/src/collections.ts @@ -31,7 +31,7 @@ export function getCollectionPath(collection: string) { } // https://github.com/iconify/iconify/blob/2274c033b49c01a50dc89b490b89d803d19d95dc/packages/utils/src/icon/name.ts#L15-L18 -export const validIconNameRE = /^[a-z0-9]+(-[a-z0-9]+)*$/ +const validIconNameRE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/ export async function loadCustomCollection(collection: CustomCollection, nuxt: Nuxt): Promise { const dir = isAbsolute(collection.dir) @@ -45,19 +45,25 @@ export async function loadCustomCollection(collection: CustomCollection, nuxt: N })) .sort() + const { + // TODO: next major flip this + normalizeIconName = true, + } = collection + const parsedIcons = await Promise.all(files.map(async (file) => { let name = basename(file, '.svg') // Currently Iconify only supports kebab-case icon names // https://github.com/nuxt/icon/issues/265#issuecomment-2441604639 // We normalize the icon name to kebab-case and warn user about it - if (!validIconNameRE.test(name)) { + if (normalizeIconName && !validIconNameRE.test(name)) { const normalized = name .replace(/([a-z])([A-Z])/g, '$1-$2') .toLowerCase() .replace(/[^a-z0-9-]/g, '-') .replace(/-+/g, '-') - logger.warn(`Custom icon \`${name}\` is normalized to \`${normalized}\`, we recommend to change the file name to match the icon name`) + if (normalized !== name) + logger.warn(`Custom icon \`${name}\` is normalized to \`${normalized}\`, we recommend to change the file name to match the icon name, or pass \`normalizeIconName: false\` to your custom collection options`) name = normalized } diff --git a/src/types.ts b/src/types.ts index bf2a9cf9..84dc654f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -54,6 +54,19 @@ export interface ModuleOptions extends Partial { dir: string + /** + * Normalize icon names to kebab-case + * + * Since v1.10.0, Iconify supports arbitrary icon names. + * You can disable this option to keep the original icon names. + * + * This options is true by default to ensure compatibility with older versions. + * In the next major version, this option will be disabled by default. + * + * @see https://github.com/nuxt/icon/issues/265#issuecomment-2524979176 + * @default true + */ + normalizeIconName?: boolean } export interface RemoteCollection {