From 355a5ecacdd46336c4dfc597d02057e0a664cd7e Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Thu, 17 Aug 2023 16:21:31 -0400 Subject: [PATCH 1/6] icon-map-kebab --- src/components/icon/test/utils.spec.ts | 26 +++++++++++++++++++++++++- src/components/icon/utils.ts | 19 ++++++++++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/components/icon/test/utils.spec.ts b/src/components/icon/test/utils.spec.ts index 45ee5d0cc..9384d2c25 100644 --- a/src/components/icon/test/utils.spec.ts +++ b/src/components/icon/test/utils.spec.ts @@ -1,5 +1,5 @@ import { Icon } from '../icon'; -import { getName, getSrc, getUrl } from '../utils'; +import { addIcons, getIconMap, getName, getSrc, getUrl } from '../utils'; describe('getUrl', () => { @@ -82,3 +82,27 @@ describe('getName', () => { }); }); + +describe('addIcons', () => { + it('should add an svg to the icon cache', () => { + const testData = 'stubbed data'; + + expect(getIconMap().get('logo-ionic')).toEqual(undefined); + + addIcons({ 'logo-ionic': 'stubbed data' }); + + expect(getIconMap().get('logo-ionic')).toEqual(testData); + }); + + it('should add kebab and camel case names to the icon cache', () => { + const logoIonitron = 'stubbed data'; + + expect(getIconMap().get('logo-ionitron')).toEqual(undefined); + expect(getIconMap().get('logoIonitron')).toEqual(undefined); + + addIcons({ logoIonitron }); + + expect(getIconMap().get('logo-ionitron')).toEqual(logoIonitron); + expect(getIconMap().get('logoIonitron')).toEqual(logoIonitron); + }); +}); diff --git a/src/components/icon/utils.ts b/src/components/icon/utils.ts index 3ffc9dad5..ca12ae2f6 100644 --- a/src/components/icon/utils.ts +++ b/src/components/icon/utils.ts @@ -19,7 +19,24 @@ export const getIconMap = (): Map => { export const addIcons = (icons: { [name: string]: string; }) => { const map = getIconMap(); - Object.keys(icons).forEach(name => map.set(name, icons[name])); + Object.keys(icons).forEach(name => { + const toKebabCase = name.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2").toLowerCase(); + map.set(name, icons[name]); + + /** + * Developers can also pass in the SVG object directly + * and Ionicons can map the object to a kebab case name. + * Example: addIcons({ addCircleOutline }); + * This will create an "addCircleOutline" entry and + * an "add-circle-outline" entry. + * Usage: + * Using name="addCircleOutline" is valid too, but the + * the kebab case naming is preferred. + */ + if (name !== toKebabCase) { + map.set(toKebabCase, icons[name]); + } + }); }; From 370a988957805635b82a120862526be6fca205e4 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Thu, 17 Aug 2023 16:26:06 -0400 Subject: [PATCH 2/6] add another test --- src/components/icon/test/utils.spec.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/components/icon/test/utils.spec.ts b/src/components/icon/test/utils.spec.ts index 9384d2c25..90eab3b9e 100644 --- a/src/components/icon/test/utils.spec.ts +++ b/src/components/icon/test/utils.spec.ts @@ -105,4 +105,14 @@ describe('addIcons', () => { expect(getIconMap().get('logo-ionitron')).toEqual(logoIonitron); expect(getIconMap().get('logoIonitron')).toEqual(logoIonitron); }); + + it('should map to a name that does not match the svg', () => { + const logoIonitron = 'stubbed data'; + + expect(getIconMap().get('my-fun-icon')).toEqual(undefined); + + addIcons({ 'my-fun-icon': logoIonitron }); + + expect(getIconMap().get('my-fun-icon')).toEqual(logoIonitron); + }); }); From a15c0bfce05833ec641920157e6498a63c7036d2 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Mon, 21 Aug 2023 10:39:14 -0400 Subject: [PATCH 3/6] add another test --- src/components/icon/test/utils.spec.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/components/icon/test/utils.spec.ts b/src/components/icon/test/utils.spec.ts index 90eab3b9e..12bdd4ce4 100644 --- a/src/components/icon/test/utils.spec.ts +++ b/src/components/icon/test/utils.spec.ts @@ -115,4 +115,14 @@ describe('addIcons', () => { expect(getIconMap().get('my-fun-icon')).toEqual(logoIonitron); }); + + it('should map to an explicit camel case name', () => { + const logoIonitron = 'stubbed data'; + + expect(getIconMap().get('myCoolIcon')).toEqual(undefined); + + addIcons({ 'myCoolIcon': logoIonitron }); + + expect(getIconMap().get('myCoolIcon')).toEqual(logoIonitron); + }); }); From bf02c7a2a3707b40fcf6c4b280826d167804bf5a Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Mon, 21 Aug 2023 10:46:57 -0400 Subject: [PATCH 4/6] account for duplicates --- src/components/icon/test/utils.spec.ts | 12 ++++++++++++ src/components/icon/utils.ts | 19 ++++++++++++++----- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/components/icon/test/utils.spec.ts b/src/components/icon/test/utils.spec.ts index 12bdd4ce4..42887bcc8 100644 --- a/src/components/icon/test/utils.spec.ts +++ b/src/components/icon/test/utils.spec.ts @@ -125,4 +125,16 @@ describe('addIcons', () => { expect(getIconMap().get('myCoolIcon')).toEqual(logoIonitron); }); + + it('should not overwrite icons', () => { + const logoA = 'logo a'; + const logoB = 'logo b'; + + expect(getIconMap().get('logo-a')).toEqual(undefined); + + addIcons({ 'logo-a': logoB, logoA }); + + expect(getIconMap().get('logo-a')).toEqual(logoB); + expect(getIconMap().get('logoA')).toEqual(logoA); + }); }); diff --git a/src/components/icon/utils.ts b/src/components/icon/utils.ts index ca12ae2f6..cd11be516 100644 --- a/src/components/icon/utils.ts +++ b/src/components/icon/utils.ts @@ -18,10 +18,8 @@ export const getIconMap = (): Map => { }; export const addIcons = (icons: { [name: string]: string; }) => { - const map = getIconMap(); - Object.keys(icons).forEach(name => { - const toKebabCase = name.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2").toLowerCase(); - map.set(name, icons[name]); + Object.keys(icons).forEach(name => { + addToIconMap(name, icons[name]); /** * Developers can also pass in the SVG object directly @@ -33,12 +31,23 @@ export const addIcons = (icons: { [name: string]: string; }) => { * Using name="addCircleOutline" is valid too, but the * the kebab case naming is preferred. */ + const toKebabCase = name.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2").toLowerCase(); if (name !== toKebabCase) { - map.set(toKebabCase, icons[name]); + addToIconMap(toKebabCase, icons[name]); } }); }; +const addToIconMap = (name: string, data: any) => { + const map = getIconMap(); + + if (map.get(name) === undefined) { + map.set(name, data); + } else { + console.warn(`[Ionicons Warning]: Multiple icons were mapped to name "${name}". Ensure that multiple icons are not mapped to the same icon name.`) + } +} + export const getUrl = (i: Icon) => { let url = getSrc(i.src); From f5f09ee3c762e34d184750b5a69b8635d3639728 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Mon, 21 Aug 2023 10:51:13 -0400 Subject: [PATCH 5/6] add another test --- src/components/icon/test/utils.spec.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/components/icon/test/utils.spec.ts b/src/components/icon/test/utils.spec.ts index 42887bcc8..4844e942b 100644 --- a/src/components/icon/test/utils.spec.ts +++ b/src/components/icon/test/utils.spec.ts @@ -137,4 +137,16 @@ describe('addIcons', () => { expect(getIconMap().get('logo-a')).toEqual(logoB); expect(getIconMap().get('logoA')).toEqual(logoA); }); + + it('passing kebab case key should not generate a camel case key', () => { + const logoIonitron = 'stubbed data'; + + expect(getIconMap().get('kebab-key')).toEqual(undefined); + expect(getIconMap().get('kebabKey')).toEqual(undefined); + + addIcons({ 'kebab-key': logoIonitron }); + + expect(getIconMap().get('kebab-key')).toEqual(logoIonitron); + expect(getIconMap().get('kebabKey')).toEqual(undefined); + }); }); From dfab40442305e7b44ff88d57a68032bcc8afc565 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Mon, 21 Aug 2023 14:25:24 -0400 Subject: [PATCH 6/6] Update src/components/icon/utils.ts Co-authored-by: Brandy Carney --- src/components/icon/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/icon/utils.ts b/src/components/icon/utils.ts index cd11be516..ff8deefc3 100644 --- a/src/components/icon/utils.ts +++ b/src/components/icon/utils.ts @@ -29,7 +29,7 @@ export const addIcons = (icons: { [name: string]: string; }) => { * an "add-circle-outline" entry. * Usage: * Using name="addCircleOutline" is valid too, but the - * the kebab case naming is preferred. + * kebab case naming is preferred. */ const toKebabCase = name.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2").toLowerCase(); if (name !== toKebabCase) {