From a26771fc6b5f7786b717686d424390c2ca03bd25 Mon Sep 17 00:00:00 2001 From: Lukas Maurer Date: Mon, 9 Dec 2024 13:54:24 +0100 Subject: [PATCH 1/3] feat: allow preloading of icons --- src/components/icon/resolveIcon.ts | 15 ++++++++- src/components/icon/test/ix-icon.spec.tsx | 2 +- src/components/icon/test/resolveIcon.spec.ts | 31 ++++++++++++++++--- .../{rocker-example.ts => rocket-example.ts} | 0 4 files changed, 41 insertions(+), 7 deletions(-) rename src/components/icon/test/{rocker-example.ts => rocket-example.ts} (100%) diff --git a/src/components/icon/resolveIcon.ts b/src/components/icon/resolveIcon.ts index ba4ece7..9706201 100644 --- a/src/components/icon/resolveIcon.ts +++ b/src/components/icon/resolveIcon.ts @@ -85,12 +85,15 @@ async function fetchSVG(url: string) { const svgContent = parseSVGDataContent(responseText); cache.set(url, svgContent); + requests.delete(url); + return svgContent; }); requests.set(url, fetching); return fetching; } + const urlRegex = /^(?:(?:https?|ftp):\/\/)?(?:\S+(?::\S*)?@)?(?:www\.)?(?:\S+\.\S+)(?:\S*)$/i; function isValidUrl(url: string) { @@ -99,11 +102,13 @@ function isValidUrl(url: string) { export function getIconUrl(name: string) { const customAssetUrl = getCustomAssetUrl(); + if (customAssetUrl) { return `${customAssetUrl}/${name}.svg`; } let url: string = `svg/${name}.svg`; + try { url = getAssetPath(url); } catch (error) { @@ -124,6 +129,10 @@ export async function resolveIcon(iconName: string) { return parseSVGDataContent(iconName); } + return await loadIcon(iconName); +} + +async function loadIcon(iconName: string) { if (isValidUrl(iconName)) { try { return fetchSVG(iconName); @@ -135,6 +144,10 @@ export async function resolveIcon(iconName: string) { try { return fetchSVG(getIconUrl(iconName)); } catch (error) { - throw Error('Cannot resolve any icon'); + throw Error(`Could not resolve ${iconName}`); } } + +export function loadIcons(icons: string[]) { + icons.map(icon => loadIcon(icon)); +} diff --git a/src/components/icon/test/ix-icon.spec.tsx b/src/components/icon/test/ix-icon.spec.tsx index f32bbe3..4030343 100644 --- a/src/components/icon/test/ix-icon.spec.tsx +++ b/src/components/icon/test/ix-icon.spec.tsx @@ -3,7 +3,7 @@ */ import { newSpecPage } from '@stencil/core/testing'; import { Icon } from '../icon'; -import { rocket } from './rocker-example'; +import { rocket } from './rocket-example'; //@ts-ignore global.fetch = jest.fn(() => diff --git a/src/components/icon/test/resolveIcon.spec.ts b/src/components/icon/test/resolveIcon.spec.ts index 9d22b29..aab4f60 100644 --- a/src/components/icon/test/resolveIcon.spec.ts +++ b/src/components/icon/test/resolveIcon.spec.ts @@ -2,7 +2,8 @@ * COPYRIGHT (c) Siemens AG 2018-2023 ALL RIGHTS RESERVED. */ import { iconStar } from '../icons'; -import { resolveIcon, getIconCacheMap, getIconUrl, parseSVGDataContent } from '../resolveIcon'; +import { resolveIcon, getIconCacheMap, getIconUrl, parseSVGDataContent, loadIcons } from '../resolveIcon'; + const exampleSvg = ` @@ -22,6 +23,9 @@ const invalidexampleSvg = ` `; +const urlInvalid = 'http://localhost/invalid.svg'; +const urlTest = 'http://localhost/test.svg'; + jest.mock('../meta-tag'); jest.mock('../icons', () => ({ iconStar: exampleSvg, @@ -43,14 +47,14 @@ let fetch = (global.fetch = jest.fn((url: string) => { }); } - if (url === 'http://localhost/test.svg') { + if (url === urlTest) { return Promise.resolve({ text: () => Promise.resolve(exampleSvg), ok: true, }); } - if (url === 'http://localhost/invalid.svg') { + if (url === urlInvalid) { return Promise.resolve({ text: () => Promise.resolve(invalidexampleSvg), ok: true, @@ -72,7 +76,7 @@ describe('resolve icon', () => { }); it('should resolve svg from src', async () => { - const expectedName = await resolveIcon('http://localhost/test.svg'); + const expectedName = await resolveIcon(urlTest); expect(expectedName).toEqual( ` add `, @@ -80,7 +84,7 @@ describe('resolve icon', () => { }); it('should not resolve invalid svg from src', async () => { - const icon = 'http://localhost/invalid.svg'; + const icon = urlInvalid; await expect(resolveIcon(icon)).rejects.toThrow('No valid svg data provided'); }); @@ -111,3 +115,20 @@ test('preload custom icon', async () => { const data = await resolveIcon('star'); expect(data).toBe('Test'); }); + +test('load icons', async () => { + fetch.mockClear(); + + const cacheMap = getIconCacheMap(); + cacheMap.clear(); + + expect(cacheMap.size).toBe(0); + + const icons = ['star', urlTest]; + + loadIcons(icons); + + const urlStar = getIconUrl('star'); + + expect(fetch.mock.calls).toEqual([[urlStar], [urlTest]]); +}); diff --git a/src/components/icon/test/rocker-example.ts b/src/components/icon/test/rocket-example.ts similarity index 100% rename from src/components/icon/test/rocker-example.ts rename to src/components/icon/test/rocket-example.ts From c2b21822aecc7c4fdbbe188ae62c2d6ec60ac292 Mon Sep 17 00:00:00 2001 From: Lukas Maurer Date: Wed, 18 Dec 2024 10:56:43 +0100 Subject: [PATCH 2/3] test: don't test basic functionality of map --- src/components/icon/test/resolveIcon.spec.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/components/icon/test/resolveIcon.spec.ts b/src/components/icon/test/resolveIcon.spec.ts index aab4f60..8c02dc1 100644 --- a/src/components/icon/test/resolveIcon.spec.ts +++ b/src/components/icon/test/resolveIcon.spec.ts @@ -96,8 +96,6 @@ test('fill cache map if not loaded', async () => { const cacheMap = getIconCacheMap(); cacheMap.clear(); - expect(cacheMap.size).toBe(0); - const data = await resolveIcon('star'); expect(data).toBe(parseSVGDataContent(iconStar)); @@ -122,8 +120,6 @@ test('load icons', async () => { const cacheMap = getIconCacheMap(); cacheMap.clear(); - expect(cacheMap.size).toBe(0); - const icons = ['star', urlTest]; loadIcons(icons); From d11ff00b5407ab4cd9652a80cd1b2736835f25ca Mon Sep 17 00:00:00 2001 From: Lukas Maurer Date: Wed, 18 Dec 2024 10:58:04 +0100 Subject: [PATCH 3/3] Create fuzzy-carrots-drive.md --- .changeset/fuzzy-carrots-drive.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fuzzy-carrots-drive.md diff --git a/.changeset/fuzzy-carrots-drive.md b/.changeset/fuzzy-carrots-drive.md new file mode 100644 index 0000000..1838644 --- /dev/null +++ b/.changeset/fuzzy-carrots-drive.md @@ -0,0 +1,5 @@ +--- +"@siemens/ix-icons": patch +--- + +Allow preloading of specific icons.