diff --git a/README.md b/README.md index 7a1cce2..3a52cb4 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 d19e598..2163099 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 0000000..ede640a --- /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 d94153a..0237f60 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 a6bc3fa..669feff 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 20b8d55..6f8635b 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 bf2a9cf..84dc654 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 {