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
/>
+
+
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 {