mirror of
https://github.com/iconify/iconify.git
synced 2024-12-13 14:13:06 +00:00
Add loadIcon function
This commit is contained in:
parent
035d2fe305
commit
bf8d17f97a
@ -14,6 +14,7 @@ import type {
|
|||||||
IconifyAPICustomQueryParams,
|
IconifyAPICustomQueryParams,
|
||||||
} from './modules';
|
} from './modules';
|
||||||
import type { MergeParams, IconifyAPIMergeQueryParams } from './params';
|
import type { MergeParams, IconifyAPIMergeQueryParams } from './params';
|
||||||
|
import type { IconifyIcon } from '@iconify/types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iconify API functions
|
* Iconify API functions
|
||||||
@ -27,6 +28,13 @@ export interface IconifyAPIFunctions {
|
|||||||
callback?: IconifyIconLoaderCallback
|
callback?: IconifyIconLoaderCallback
|
||||||
) => IconifyIconLoaderAbort;
|
) => IconifyIconLoaderAbort;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load one icon, using Promise syntax
|
||||||
|
*/
|
||||||
|
loadIcon: (
|
||||||
|
icon: IconifyIconName | string
|
||||||
|
) => Promise<Required<IconifyIcon>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add API provider
|
* Add API provider
|
||||||
*/
|
*/
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import type { IconifyJSON } from '@iconify/types';
|
import type { IconifyIcon, IconifyJSON } from '@iconify/types';
|
||||||
import type {
|
import {
|
||||||
IconifyIconName,
|
IconifyIconName,
|
||||||
IconifyIconSource,
|
IconifyIconSource,
|
||||||
|
stringToIcon,
|
||||||
} from '@iconify/utils/lib/icon/name';
|
} from '@iconify/utils/lib/icon/name';
|
||||||
import type { SortedIcons } from '../icon/sort';
|
import type { SortedIcons } from '../icon/sort';
|
||||||
import { sortIcons } from '../icon/sort';
|
import { sortIcons } from '../icon/sort';
|
||||||
import { storeCallback, updateCallbacks } from './callbacks';
|
import { storeCallback, updateCallbacks } from './callbacks';
|
||||||
import { getAPIModule } from './modules';
|
import { getAPIModule } from './modules';
|
||||||
import { getStorage, addIconSet } from '../storage/storage';
|
import { getStorage, addIconSet, getIconFromStorage } from '../storage/storage';
|
||||||
import { listToIcons } from '../icon/list';
|
import { listToIcons } from '../icon/list';
|
||||||
import { allowSimpleNames } from '../storage/functions';
|
import { allowSimpleNames } from '../storage/functions';
|
||||||
import { sendAPIQuery } from './query';
|
import { sendAPIQuery } from './query';
|
||||||
@ -338,3 +339,36 @@ export const loadIcons: IconifyLoadIcons = (
|
|||||||
? storeCallback(callback, sortedIcons, sources)
|
? storeCallback(callback, sortedIcons, sources)
|
||||||
: emptyCallback;
|
: emptyCallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache for loadIcon promises
|
||||||
|
*/
|
||||||
|
type LoadIconResult = Promise<Required<IconifyIcon>>;
|
||||||
|
const iconsQueue: Record<string, LoadIconResult> = Object.create(null);
|
||||||
|
|
||||||
|
export const loadIcon = (icon: IconifyIconName | string): LoadIconResult => {
|
||||||
|
if (typeof icon === 'string' && iconsQueue[icon]) {
|
||||||
|
return iconsQueue[icon];
|
||||||
|
}
|
||||||
|
|
||||||
|
const result: LoadIconResult = new Promise((fulfill, reject) => {
|
||||||
|
const iconObj = typeof icon === 'string' ? stringToIcon(icon) : icon;
|
||||||
|
loadIcons([iconObj || icon], (loaded) => {
|
||||||
|
if (loaded.length && iconObj) {
|
||||||
|
const storage = getStorage(iconObj.provider, iconObj.prefix);
|
||||||
|
const data = getIconFromStorage(storage, iconObj.name);
|
||||||
|
if (data) {
|
||||||
|
fulfill(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reject(icon);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof icon === 'string') {
|
||||||
|
iconsQueue[icon] = result;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
@ -5,7 +5,7 @@ import type {
|
|||||||
IconifyAPIQueryParams,
|
IconifyAPIQueryParams,
|
||||||
} from '../../lib/api/modules';
|
} from '../../lib/api/modules';
|
||||||
import { setAPIModule } from '../../lib/api/modules';
|
import { setAPIModule } from '../../lib/api/modules';
|
||||||
import { loadIcons, isPending } from '../../lib/api/icons';
|
import { loadIcons, loadIcon, isPending } from '../../lib/api/icons';
|
||||||
|
|
||||||
describe('Testing API loadIcons', () => {
|
describe('Testing API loadIcons', () => {
|
||||||
let prefixCounter = 0;
|
let prefixCounter = 0;
|
||||||
@ -154,6 +154,167 @@ describe('Testing API loadIcons', () => {
|
|||||||
asyncCounter++;
|
asyncCounter++;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Loading one icon with Promise', async () => {
|
||||||
|
const provider = nextPrefix();
|
||||||
|
const prefix = nextPrefix();
|
||||||
|
|
||||||
|
// Set config
|
||||||
|
addAPIProvider(provider, {
|
||||||
|
resources: ['https://api1.local', 'https://api2.local'],
|
||||||
|
});
|
||||||
|
|
||||||
|
// Icon loader
|
||||||
|
const prepareQuery = (
|
||||||
|
provider: string,
|
||||||
|
prefix: string,
|
||||||
|
icons: string[]
|
||||||
|
): IconifyAPIIconsQueryParams[] => {
|
||||||
|
const item: IconifyAPIIconsQueryParams = {
|
||||||
|
type: 'icons',
|
||||||
|
provider,
|
||||||
|
prefix,
|
||||||
|
icons,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test input and return as one item
|
||||||
|
const expected: IconifyAPIIconsQueryParams = {
|
||||||
|
type: 'icons',
|
||||||
|
provider,
|
||||||
|
prefix,
|
||||||
|
icons: ['icon1'],
|
||||||
|
};
|
||||||
|
expect(item).toEqual(expected);
|
||||||
|
|
||||||
|
return [item];
|
||||||
|
};
|
||||||
|
|
||||||
|
const sendQuery = (
|
||||||
|
host: string,
|
||||||
|
params: IconifyAPIQueryParams,
|
||||||
|
item: PendingQueryItem
|
||||||
|
): void => {
|
||||||
|
expect(params.type).toBe('icons');
|
||||||
|
|
||||||
|
// Test input
|
||||||
|
expect(host).toBe('https://api1.local');
|
||||||
|
const expected: IconifyAPIQueryParams = {
|
||||||
|
type: 'icons',
|
||||||
|
provider,
|
||||||
|
prefix,
|
||||||
|
icons: ['icon1'],
|
||||||
|
};
|
||||||
|
expect(params).toEqual(expected);
|
||||||
|
|
||||||
|
// Send data
|
||||||
|
item.done({
|
||||||
|
prefix,
|
||||||
|
icons: {
|
||||||
|
icon1: {
|
||||||
|
body: '<path d="" />',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
setAPIModule(provider, {
|
||||||
|
prepare: prepareQuery,
|
||||||
|
send: sendQuery,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Load icon
|
||||||
|
await loadIcon(provider + ':' + prefix + ':icon1');
|
||||||
|
|
||||||
|
// Test isPending
|
||||||
|
expect(isPending({ provider, prefix, name: 'icon1' })).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Loading one icon twice with Promise', (done) => {
|
||||||
|
const provider = nextPrefix();
|
||||||
|
const prefix = nextPrefix();
|
||||||
|
|
||||||
|
// Set config
|
||||||
|
addAPIProvider(provider, {
|
||||||
|
resources: ['https://api1.local', 'https://api2.local'],
|
||||||
|
});
|
||||||
|
|
||||||
|
// Icon loader
|
||||||
|
const prepareQuery = (
|
||||||
|
provider: string,
|
||||||
|
prefix: string,
|
||||||
|
icons: string[]
|
||||||
|
): IconifyAPIIconsQueryParams[] => {
|
||||||
|
const item: IconifyAPIIconsQueryParams = {
|
||||||
|
type: 'icons',
|
||||||
|
provider,
|
||||||
|
prefix,
|
||||||
|
icons,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test input and return as one item
|
||||||
|
const expected: IconifyAPIIconsQueryParams = {
|
||||||
|
type: 'icons',
|
||||||
|
provider,
|
||||||
|
prefix,
|
||||||
|
icons: ['icon1'],
|
||||||
|
};
|
||||||
|
expect(item).toEqual(expected);
|
||||||
|
|
||||||
|
return [item];
|
||||||
|
};
|
||||||
|
|
||||||
|
const sendQuery = (
|
||||||
|
host: string,
|
||||||
|
params: IconifyAPIQueryParams,
|
||||||
|
item: PendingQueryItem
|
||||||
|
): void => {
|
||||||
|
expect(params.type).toBe('icons');
|
||||||
|
|
||||||
|
// Test input
|
||||||
|
expect(host).toBe('https://api1.local');
|
||||||
|
const expected: IconifyAPIQueryParams = {
|
||||||
|
type: 'icons',
|
||||||
|
provider,
|
||||||
|
prefix,
|
||||||
|
icons: ['icon1'],
|
||||||
|
};
|
||||||
|
expect(params).toEqual(expected);
|
||||||
|
|
||||||
|
// Send data
|
||||||
|
item.done({
|
||||||
|
prefix,
|
||||||
|
icons: {
|
||||||
|
icon1: {
|
||||||
|
body: '<path d="" />',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
setAPIModule(provider, {
|
||||||
|
prepare: prepareQuery,
|
||||||
|
send: sendQuery,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Load icon, twice
|
||||||
|
const p1 = loadIcon(provider + ':' + prefix + ':icon1');
|
||||||
|
const p2 = loadIcon(provider + ':' + prefix + ':icon1');
|
||||||
|
|
||||||
|
// Promise instances should be the same because parameter is a string that is cached
|
||||||
|
expect(p1).toEqual(p2);
|
||||||
|
|
||||||
|
// Test isPending
|
||||||
|
expect(isPending({ provider, prefix, name: 'icon1' })).toBe(true);
|
||||||
|
|
||||||
|
// Wait for Promise
|
||||||
|
p1.then((data) => {
|
||||||
|
expect(data.body).toEqual('<path d="" />');
|
||||||
|
done();
|
||||||
|
}).catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
done('Failed to load icon');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Split results', (done) => {
|
it('Split results', (done) => {
|
||||||
const provider = nextPrefix();
|
const provider = nextPrefix();
|
||||||
const prefix = nextPrefix();
|
const prefix = nextPrefix();
|
||||||
|
@ -51,7 +51,7 @@ import type {
|
|||||||
IconifyIconLoaderCallback,
|
IconifyIconLoaderCallback,
|
||||||
IconifyIconLoaderAbort,
|
IconifyIconLoaderAbort,
|
||||||
} from '@iconify/core/lib/api/icons';
|
} from '@iconify/core/lib/api/icons';
|
||||||
import { loadIcons } from '@iconify/core/lib/api/icons';
|
import { loadIcons, loadIcon } from '@iconify/core/lib/api/icons';
|
||||||
import { sendAPIQuery } from '@iconify/core/lib/api/query';
|
import { sendAPIQuery } from '@iconify/core/lib/api/query';
|
||||||
import { mergeParams } from '@iconify/core/lib/api/params';
|
import { mergeParams } from '@iconify/core/lib/api/params';
|
||||||
|
|
||||||
@ -230,7 +230,7 @@ const _api: IconifyAPIInternalFunctions = {
|
|||||||
export { _api };
|
export { _api };
|
||||||
|
|
||||||
// IconifyAPIFunctions
|
// IconifyAPIFunctions
|
||||||
export { addAPIProvider, loadIcons };
|
export { addAPIProvider, loadIcons, loadIcon };
|
||||||
|
|
||||||
// IconifyStorageFunctions
|
// IconifyStorageFunctions
|
||||||
export { iconExists, getIcon, listIcons, addIcon, addCollection, shareStorage };
|
export { iconExists, getIcon, listIcons, addIcon, addCollection, shareStorage };
|
||||||
|
@ -64,7 +64,7 @@ import type {
|
|||||||
IconifyIconLoaderCallback,
|
IconifyIconLoaderCallback,
|
||||||
IconifyIconLoaderAbort,
|
IconifyIconLoaderAbort,
|
||||||
} from '@iconify/core/lib/api/icons';
|
} from '@iconify/core/lib/api/icons';
|
||||||
import { loadIcons } from '@iconify/core/lib/api/icons';
|
import { loadIcons, loadIcon } from '@iconify/core/lib/api/icons';
|
||||||
import { sendAPIQuery } from '@iconify/core/lib/api/query';
|
import { sendAPIQuery } from '@iconify/core/lib/api/query';
|
||||||
import { mergeParams } from '@iconify/core/lib/api/params';
|
import { mergeParams } from '@iconify/core/lib/api/params';
|
||||||
|
|
||||||
@ -223,6 +223,7 @@ const Iconify: IconifyGlobal = {
|
|||||||
// IconifyAPIFunctions
|
// IconifyAPIFunctions
|
||||||
addAPIProvider,
|
addAPIProvider,
|
||||||
loadIcons,
|
loadIcons,
|
||||||
|
loadIcon,
|
||||||
|
|
||||||
// IconifyStorageFunctions
|
// IconifyStorageFunctions
|
||||||
iconExists,
|
iconExists,
|
||||||
|
@ -55,7 +55,7 @@ import type {
|
|||||||
IconifyIconLoaderCallback,
|
IconifyIconLoaderCallback,
|
||||||
IconifyIconLoaderAbort,
|
IconifyIconLoaderAbort,
|
||||||
} from '@iconify/core/lib/api/icons';
|
} from '@iconify/core/lib/api/icons';
|
||||||
import { loadIcons } from '@iconify/core/lib/api/icons';
|
import { loadIcons, loadIcon } from '@iconify/core/lib/api/icons';
|
||||||
import { sendAPIQuery } from '@iconify/core/lib/api/query';
|
import { sendAPIQuery } from '@iconify/core/lib/api/query';
|
||||||
import { mergeParams } from '@iconify/core/lib/api/params';
|
import { mergeParams } from '@iconify/core/lib/api/params';
|
||||||
|
|
||||||
@ -461,7 +461,7 @@ const _api: IconifyAPIInternalFunctions = {
|
|||||||
export { _api };
|
export { _api };
|
||||||
|
|
||||||
// IconifyAPIFunctions
|
// IconifyAPIFunctions
|
||||||
export { addAPIProvider, loadIcons };
|
export { addAPIProvider, loadIcons, loadIcon };
|
||||||
|
|
||||||
// IconifyStorageFunctions
|
// IconifyStorageFunctions
|
||||||
export { iconExists, getIcon, listIcons, addIcon, addCollection, shareStorage };
|
export { iconExists, getIcon, listIcons, addIcon, addCollection, shareStorage };
|
||||||
|
@ -15,6 +15,7 @@ import {
|
|||||||
replaceIDs,
|
replaceIDs,
|
||||||
buildIcon,
|
buildIcon,
|
||||||
loadIcons,
|
loadIcons,
|
||||||
|
loadIcon,
|
||||||
addAPIProvider,
|
addAPIProvider,
|
||||||
_api
|
_api
|
||||||
} from './functions';
|
} from './functions';
|
||||||
@ -32,6 +33,7 @@ export {
|
|||||||
replaceIDs,
|
replaceIDs,
|
||||||
buildIcon,
|
buildIcon,
|
||||||
loadIcons,
|
loadIcons,
|
||||||
|
loadIcon,
|
||||||
addAPIProvider,
|
addAPIProvider,
|
||||||
_api
|
_api
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ import type {
|
|||||||
IconifyIconLoaderCallback,
|
IconifyIconLoaderCallback,
|
||||||
IconifyIconLoaderAbort,
|
IconifyIconLoaderAbort,
|
||||||
} from '@iconify/core/lib/api/icons';
|
} from '@iconify/core/lib/api/icons';
|
||||||
import { loadIcons } from '@iconify/core/lib/api/icons';
|
import { loadIcons, loadIcon } from '@iconify/core/lib/api/icons';
|
||||||
import { sendAPIQuery } from '@iconify/core/lib/api/query';
|
import { sendAPIQuery } from '@iconify/core/lib/api/query';
|
||||||
import { mergeParams } from '@iconify/core/lib/api/params';
|
import { mergeParams } from '@iconify/core/lib/api/params';
|
||||||
|
|
||||||
@ -357,7 +357,7 @@ const _api: IconifyAPIInternalFunctions = {
|
|||||||
export { _api };
|
export { _api };
|
||||||
|
|
||||||
// IconifyAPIFunctions
|
// IconifyAPIFunctions
|
||||||
export { addAPIProvider, loadIcons };
|
export { addAPIProvider, loadIcons, loadIcon };
|
||||||
|
|
||||||
// IconifyStorageFunctions
|
// IconifyStorageFunctions
|
||||||
export { iconExists, getIcon, listIcons, addIcon, addCollection, shareStorage };
|
export { iconExists, getIcon, listIcons, addIcon, addCollection, shareStorage };
|
||||||
|
@ -62,4 +62,4 @@ export {
|
|||||||
|
|
||||||
export { calculateSize, replaceIDs, buildIcon } from './functions';
|
export { calculateSize, replaceIDs, buildIcon } from './functions';
|
||||||
|
|
||||||
export { loadIcons, addAPIProvider, _api } from './functions';
|
export { loadIcons, loadIcon, addAPIProvider, _api } from './functions';
|
||||||
|
@ -64,7 +64,7 @@ import type {
|
|||||||
IconifyIconLoaderCallback,
|
IconifyIconLoaderCallback,
|
||||||
IconifyIconLoaderAbort,
|
IconifyIconLoaderAbort,
|
||||||
} from '@iconify/core/lib/api/icons';
|
} from '@iconify/core/lib/api/icons';
|
||||||
import { loadIcons } from '@iconify/core/lib/api/icons';
|
import { loadIcons, loadIcon } from '@iconify/core/lib/api/icons';
|
||||||
import { sendAPIQuery } from '@iconify/core/lib/api/query';
|
import { sendAPIQuery } from '@iconify/core/lib/api/query';
|
||||||
import { mergeParams } from '@iconify/core/lib/api/params';
|
import { mergeParams } from '@iconify/core/lib/api/params';
|
||||||
|
|
||||||
@ -397,7 +397,7 @@ const _api: IconifyAPIInternalFunctions = {
|
|||||||
export { _api };
|
export { _api };
|
||||||
|
|
||||||
// IconifyAPIFunctions
|
// IconifyAPIFunctions
|
||||||
export { addAPIProvider, loadIcons };
|
export { addAPIProvider, loadIcons, loadIcon };
|
||||||
|
|
||||||
// IconifyStorageFunctions
|
// IconifyStorageFunctions
|
||||||
export { iconExists, getIcon, listIcons, addIcon, addCollection, shareStorage };
|
export { iconExists, getIcon, listIcons, addIcon, addCollection, shareStorage };
|
||||||
|
@ -57,7 +57,7 @@ import type {
|
|||||||
IconifyIconLoaderCallback,
|
IconifyIconLoaderCallback,
|
||||||
IconifyIconLoaderAbort,
|
IconifyIconLoaderAbort,
|
||||||
} from '@iconify/core/lib/api/icons';
|
} from '@iconify/core/lib/api/icons';
|
||||||
import { loadIcons } from '@iconify/core/lib/api/icons';
|
import { loadIcons, loadIcon } from '@iconify/core/lib/api/icons';
|
||||||
import { sendAPIQuery } from '@iconify/core/lib/api/query';
|
import { sendAPIQuery } from '@iconify/core/lib/api/query';
|
||||||
import { mergeParams } from '@iconify/core/lib/api/params';
|
import { mergeParams } from '@iconify/core/lib/api/params';
|
||||||
|
|
||||||
@ -399,7 +399,7 @@ const _api: IconifyAPIInternalFunctions = {
|
|||||||
export { _api };
|
export { _api };
|
||||||
|
|
||||||
// IconifyAPIFunctions
|
// IconifyAPIFunctions
|
||||||
export { addAPIProvider, loadIcons };
|
export { addAPIProvider, loadIcons, loadIcon };
|
||||||
|
|
||||||
// IconifyStorageFunctions
|
// IconifyStorageFunctions
|
||||||
export { iconExists, getIcon, listIcons, addIcon, addCollection, shareStorage };
|
export { iconExists, getIcon, listIcons, addIcon, addCollection, shareStorage };
|
||||||
|
Loading…
Reference in New Issue
Block a user