Skip to content

Commit

Permalink
feat: support arbitrary names for custom icons, fix #265 (#317)
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu authored Dec 10, 2024
1 parent 65e4c85 commit faa915c
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 3 deletions.
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 `<Icon />`, create an `app.config.ts` with the `icon.size` property.
Expand Down
12 changes: 12 additions & 0 deletions playground/components/ShowcaseFixture.vue
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,18 @@ defineProps<{
:mode
:customize
/>
<Icon
name="custom1:Foo_Bar_Zag"
size="64"
:mode
:customize
/>
<Icon
name="custom1:Foo.BarZag"
size="64"
:mode
:customize
/>
</p>
<p>
Custom icons with `prefix: ''` from local fs:
Expand Down
8 changes: 8 additions & 0 deletions playground/icons/custom1/Foo_Bar_Zag.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
50 changes: 50 additions & 0 deletions playground/test/nuxt/output/fixtures.html
Original file line number Diff line number Diff line change
Expand Up @@ -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"
></path>
</g></svg
><svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
aria-hidden="true"
role="img"
class="iconify iconify--custom1"
style="font-size: 64px"
width="1.36em"
height="1em"
viewBox="0 0 256 189"
>
<g>
<polygon
fill="#48B884"
points="109.7766 0.0009 -0.0004 188.2259 219.5526 188.2259"
></polygon>
<polygon
fill="#3F7F70"
points="72.8361 188.226 255.9991 188.226 164.4181 31.198"
></polygon>
<polygon
fill="#36495D"
points="72.8361 188.226 219.5521 188.226 146.1941 62.444"
></polygon>
</g></svg
><svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
aria-hidden="true"
role="img"
class="iconify iconify--custom1"
style="font-size: 64px"
width="1.36em"
height="1em"
viewBox="0 0 256 189"
>
<g>
<polygon
fill="#48B884"
points="109.7766 0.0009 -0.0004 188.2259 219.5526 188.2259"
></polygon>
<polygon
fill="#3F7F70"
points="72.8361 188.226 255.9991 188.226 164.4181 31.198"
></polygon>
<polygon
fill="#36495D"
points="72.8361 188.226 219.5521 188.226 146.1941 62.444"
></polygon>
</g>
</svg>
</p>
Expand Down
12 changes: 9 additions & 3 deletions src/collections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<IconifyJSON> {
const dir = isAbsolute(collection.dir)
Expand All @@ -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
}

Expand Down
13 changes: 13 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,19 @@ export interface ModuleOptions extends Partial<Omit<NuxtIconRuntimeOptions, 'cus

export interface CustomCollection extends Pick<IconifyJSON, 'prefix' | 'width' | 'height'> {
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 {
Expand Down

0 comments on commit faa915c

Please sign in to comment.