diff --git a/packages/utils/src/loader/modern.ts b/packages/utils/src/loader/modern.ts index cfe9a61..fc5397a 100644 --- a/packages/utils/src/loader/modern.ts +++ b/packages/utils/src/loader/modern.ts @@ -22,8 +22,16 @@ export async function searchForIcon( if (iconData) { debug(`${collection}:${id}`); let defaultCustomizations = { ...defaultIconCustomisations }; - if (typeof customize === 'function') - defaultCustomizations = customize(defaultCustomizations); + if (typeof customize === 'function') { + // Clone icon data to make it mutable + iconData = Object.assign({}, iconData); + defaultCustomizations = + customize( + defaultCustomizations, + iconData, + `${collection}:${id}` + ) ?? defaultCustomizations; + } const { attributes: { width, height, ...restAttributes }, diff --git a/packages/utils/src/loader/types.ts b/packages/utils/src/loader/types.ts index 37e45ec..e58ef91 100644 --- a/packages/utils/src/loader/types.ts +++ b/packages/utils/src/loader/types.ts @@ -1,6 +1,6 @@ import type { Awaitable } from '@antfu/utils'; import type { FullIconCustomisations } from '../customisations/defaults'; -import type { IconifyJSON } from '@iconify/types'; +import type { IconifyIcon, IconifyJSON } from '@iconify/types'; /** * External package name. @@ -69,11 +69,15 @@ export type IconCustomizations = { * Change default icon customizations values. * * @param defaultCustomizations Default icon's customizations values. + * @param data The icon data. Mutable, you can change the icon data. + * @param name The icon name, can be used to check if icon needs to be customised. * @return The modified icon's customizations values. */ customize?: ( - defaultCustomizations: FullIconCustomisations - ) => FullIconCustomisations; + defaultCustomizations: FullIconCustomisations, + data: IconifyIcon, + name: string + ) => FullIconCustomisations | undefined; /** * Custom icon customizer. */ diff --git a/packages/utils/tests/get-custom-icon-test.ts b/packages/utils/tests/get-custom-icon-test.ts index 8c51377..fd599d3 100644 --- a/packages/utils/tests/get-custom-icon-test.ts +++ b/packages/utils/tests/get-custom-icon-test.ts @@ -143,4 +143,15 @@ describe('Testing getCustomIcon', () => { expect(result && result.indexOf(' width="') === -1).toBeTruthy(); expect(result && result.indexOf(' height="') === -1).toBeTruthy(); }); + + test('CustomIconLoader with non-square icon', async () => { + const svg = + ''; + const result = await getCustomIcon(() => svg, 'a', 'b', { + addXmlNs: true, + }); + expect(result).toEqual( + '' + ); + }); }); diff --git a/packages/utils/tests/iconify-icon-test.ts b/packages/utils/tests/iconify-icon-test.ts index 24d300e..286911a 100644 --- a/packages/utils/tests/iconify-icon-test.ts +++ b/packages/utils/tests/iconify-icon-test.ts @@ -11,7 +11,7 @@ describe('Testing loadIcon with @iconify-json/flat-color-icons>', () => { addXmlNs: true, }); expect(result).toBeTruthy(); - expect(result && result.indexOf('xmlns:xlink=') === -1).toBeTruthy(); + expect(result && !result.includes('xmlns:xlink=')).toBeTruthy(); }); test('loadIcon with customize with default style and class', async () => { @@ -19,7 +19,14 @@ describe('Testing loadIcon with @iconify-json/flat-color-icons>', () => { defaultStyle: 'margin-top: 1rem;', defaultClass: 'clazz', customizations: { - customize(props) { + customize(props, data, name) { + // Check props + expect(props.width).toBeNull(); + expect(data.width).toBe(48); + expect(data.height).toBe(48); + expect(name).toBe('flat-color-icons:up-right'); + + // Change props props.width = '2em'; props.height = '2em'; return props; @@ -27,10 +34,10 @@ describe('Testing loadIcon with @iconify-json/flat-color-icons>', () => { }, }); expect(result).toBeTruthy(); - expect(result && result.indexOf('margin-top: 1rem;') > -1).toBeTruthy(); - expect(result && result.indexOf('class="clazz"') > -1).toBeTruthy(); - expect(result && result.indexOf('width="2em"') > -1).toBeTruthy(); - expect(result && result.indexOf('height="2em"') > -1).toBeTruthy(); + expect(result && result.includes('margin-top: 1rem;')).toBeTruthy(); + expect(result && result.includes('class="clazz"')).toBeTruthy(); + expect(result && result.includes('width="2em"')).toBeTruthy(); + expect(result && result.includes('height="2em"')).toBeTruthy(); }); test('loadIcon preserves customizations order', async () => { @@ -100,7 +107,7 @@ describe('Testing loadIcon with @iconify-json/flat-color-icons>', () => { expect(result && result.includes('height="1em"')).toBeTruthy(); }); - test.only('loadIcon with custom width/height', async () => { + test('loadIcon with custom width/height', async () => { const result = await loadNodeIcon('flat-color-icons', 'up-right', { customizations: { customize(props) {