2
0
mirror of https://github.com/iconify/iconify.git synced 2025-01-07 15:44:05 +00:00

Remove getIconFromStorage, change getIconData to return null if icon is marked as missing

This commit is contained in:
Vjacheslav Trushkin 2022-04-29 22:59:34 +03:00
parent 5967e3c469
commit 2c2a9647fa
13 changed files with 153 additions and 116 deletions

View File

@ -8,9 +8,9 @@ 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, getIconFromStorage } from '../storage/storage'; import { getStorage, addIconSet } from '../storage/storage';
import { listToIcons } from '../icon/list'; import { listToIcons } from '../icon/list';
import { allowSimpleNames } from '../storage/functions'; import { allowSimpleNames, getIconData } from '../storage/functions';
import { sendAPIQuery } from './query'; import { sendAPIQuery } from './query';
import { cache } from '../cache'; import { cache } from '../cache';
@ -364,10 +364,11 @@ export const loadIcon = (
const iconObj = typeof icon === 'string' ? stringToIcon(icon) : icon; const iconObj = typeof icon === 'string' ? stringToIcon(icon) : icon;
loadIcons([iconObj || icon], (loaded) => { loadIcons([iconObj || icon], (loaded) => {
if (loaded.length && iconObj) { if (loaded.length && iconObj) {
const storage = getStorage(iconObj.provider, iconObj.prefix); const data = getIconData(iconObj);
const data = getIconFromStorage(storage, iconObj.name);
if (data) { if (data) {
fulfill(data); fulfill({
...data,
});
return; return;
} }
} }

View File

@ -27,7 +27,7 @@ const detectFetch = (): FetchType | null => {
if (typeof callback === 'function') { if (typeof callback === 'function') {
return callback; return callback;
} }
} catch (err) { } catch {
// //
} }

View File

@ -89,7 +89,7 @@ function getGlobal(key: keyof StorageConfig): typeof localStorage | null {
) { ) {
return _window[attr]; return _window[attr];
} }
} catch (err) { } catch {
// //
} }
@ -110,9 +110,10 @@ function setCount(
storage.setItem(countKey, value.toString()); storage.setItem(countKey, value.toString());
count[key] = value; count[key] = value;
return true; return true;
} catch (err) { } catch {
return false; //
} }
return false;
} }
/** /**
@ -141,7 +142,7 @@ function initCache(
): void { ): void {
try { try {
storage.setItem(versionKey, cacheVersion); storage.setItem(versionKey, cacheVersion);
} catch (err) { } catch {
// //
} }
setCount(storage, key, 0); setCount(storage, key, 0);
@ -158,7 +159,7 @@ function destroyCache(storage: typeof localStorage): void {
for (let i = 0; i < total; i++) { for (let i = 0; i < total; i++) {
storage.removeItem(cachePrefix + i.toString()); storage.removeItem(cachePrefix + i.toString());
} }
} catch (err) { } catch {
// //
} }
} }
@ -213,7 +214,7 @@ export const loadCache: LoadIconsCache = (): void => {
const storage = getStorage(provider, prefix); const storage = getStorage(provider, prefix);
valid = addIconSet(storage, data.data).length > 0; valid = addIconSet(storage, data.data).length > 0;
} }
} catch (err) { } catch {
valid = false; valid = false;
} }
@ -253,7 +254,7 @@ export const loadCache: LoadIconsCache = (): void => {
// Update total // Update total
setCount(func, key, total); setCount(func, key, total);
} catch (err) { } catch {
// //
} }
} }
@ -302,7 +303,7 @@ export const storeCache: CacheIcons = (
data, data,
}; };
func.setItem(cachePrefix + index.toString(), JSON.stringify(item)); func.setItem(cachePrefix + index.toString(), JSON.stringify(item));
} catch (err) { } catch {
return false; return false;
} }
return true; return true;

View File

@ -4,12 +4,7 @@ import { parseIconSet } from '@iconify/utils/lib/icon-set/parse';
import { quicklyValidateIconSet } from '@iconify/utils/lib/icon-set/validate-basic'; import { quicklyValidateIconSet } from '@iconify/utils/lib/icon-set/validate-basic';
import type { IconifyIconName } from '@iconify/utils/lib/icon/name'; import type { IconifyIconName } from '@iconify/utils/lib/icon/name';
import { stringToIcon, validateIcon } from '@iconify/utils/lib/icon/name'; import { stringToIcon, validateIcon } from '@iconify/utils/lib/icon/name';
import { import { getStorage, addIconToStorage, addIconSet } from './storage';
getStorage,
getIconFromStorage,
addIconToStorage,
addIconSet,
} from './storage';
/** /**
* Interface for exported storage functions * Interface for exported storage functions
@ -65,15 +60,26 @@ export function allowSimpleNames(allow?: boolean): boolean {
/** /**
* Get icon data * Get icon data
*
* Returns:
* - Required<IconifyIcon> on success, object directly from storage so don't modify it
* - null if icon is marked as missing (returned in `not_found` property from API, so don't bother sending API requests)
* - undefined if icon is missing
*/ */
export function getIconData( export function getIconData(
name: string | IconifyIconName name: string | IconifyIconName
): FullIconifyIcon | null { ): FullIconifyIcon | null | undefined {
const icon = const icon =
typeof name === 'string' ? stringToIcon(name, true, simpleNames) : name; typeof name === 'string' ? stringToIcon(name, true, simpleNames) : name;
return icon
? getIconFromStorage(getStorage(icon.provider, icon.prefix), icon.name) if (!icon) {
: null; return;
}
const storage = getStorage(icon.provider, icon.prefix);
const iconName = icon.name;
return (
storage.icons[iconName] || (storage.missing[iconName] ? null : void 0)
);
} }
/** /**
@ -143,9 +149,8 @@ export function addCollection(data: IconifyJSON, provider?: string): boolean {
* Check if icon exists * Check if icon exists
*/ */
export function iconExists(name: string): boolean { export function iconExists(name: string): boolean {
return getIconData(name) !== null; return !!getIconData(name);
} }
/** /**
* Get icon * Get icon
*/ */

View File

@ -47,7 +47,7 @@ try {
if (w && w._iconifyStorage.version === storageVersion) { if (w && w._iconifyStorage.version === storageVersion) {
storage = w._iconifyStorage.storage; storage = w._iconifyStorage.storage;
} }
} catch (err) { } catch {
// //
} }
@ -63,7 +63,7 @@ export function shareStorage(): void {
storage, storage,
}; };
} }
} catch (err) { } catch {
// //
} }
} }
@ -128,7 +128,7 @@ export function addIconToStorage(
storage.icons[name] = Object.freeze(fullIcon(icon)); storage.icons[name] = Object.freeze(fullIcon(icon));
return true; return true;
} }
} catch (err) { } catch {
// Do nothing // Do nothing
} }
return false; return false;
@ -141,17 +141,6 @@ export function iconExists(storage: IconStorage, name: string): boolean {
return storage.icons[name] !== void 0; return storage.icons[name] !== void 0;
} }
/**
* Get icon data
*/
export function getIconFromStorage(
storage: IconStorage,
name: string
): Readonly<FullIconifyIcon> | null {
const value = storage.icons[name];
return value === void 0 ? null : value;
}
/** /**
* List available icons * List available icons
*/ */

View File

@ -1,11 +1,12 @@
import { fullIcon } from '@iconify/utils/lib/icon'; import { fullIcon } from '@iconify/utils/lib/icon';
import { listIcons } from '../../lib/storage/storage'; import { addIconSet, getStorage, listIcons } from '../../lib/storage/storage';
import { import {
iconExists, iconExists,
getIcon, getIcon,
addIcon, addIcon,
addCollection, addCollection,
allowSimpleNames, allowSimpleNames,
getIconData,
} from '../../lib/storage/functions'; } from '../../lib/storage/functions';
describe('Testing IconifyStorageFunctions', () => { describe('Testing IconifyStorageFunctions', () => {
@ -15,6 +16,13 @@ describe('Testing IconifyStorageFunctions', () => {
return 'storage-test-' + (count++).toString(); return 'storage-test-' + (count++).toString();
} }
beforeEach(() => {
allowSimpleNames(false);
});
afterAll(() => {
allowSimpleNames(false);
});
it('Storage functions', () => { it('Storage functions', () => {
const provider = nextProvider(); const provider = nextProvider();
const testName = `@${provider}:foo:bar`; const testName = `@${provider}:foo:bar`;
@ -22,6 +30,7 @@ describe('Testing IconifyStorageFunctions', () => {
// Empty // Empty
expect(iconExists(testName)).toBe(false); expect(iconExists(testName)).toBe(false);
expect(getIcon(testName)).toBeNull(); expect(getIcon(testName)).toBeNull();
expect(getIconData(testName)).toBeUndefined();
expect(listIcons(provider)).toEqual([]); expect(listIcons(provider)).toEqual([]);
// Add and test one icon // Add and test one icon
@ -32,17 +41,52 @@ describe('Testing IconifyStorageFunctions', () => {
).toBe(true); ).toBe(true);
expect(iconExists(testName)).toBe(true); expect(iconExists(testName)).toBe(true);
expect(listIcons(provider)).toEqual([testName]); expect(listIcons(provider)).toEqual([testName]);
let expected = fullIcon({
body: '<g />',
});
expect(getIconData(testName)).toEqual(expected);
expect(getIcon(testName)).toEqual(expected);
// Add icon set
const prefix = 'prefix' + (count++).toString();
const storage = getStorage('', prefix);
addIconSet(storage, {
prefix,
icons: {
home: {
body: '<g id="home" />',
},
},
not_found: ['missing'],
});
// Test 'home' icon
expect(iconExists(`${prefix}:home`)).toBe(true);
expected = fullIcon({
body: '<g id="home" />',
});
expect(getIconData(`${prefix}:home`)).toEqual(expected);
expect(getIcon(`${prefix}:home`)).toEqual(expected);
// Test 'missing' icon
expect(iconExists(`${prefix}:missing`)).toBe(false);
expect(getIconData(`${prefix}:missing`)).toBeNull();
expect(getIcon(`${prefix}:missing`)).toBeNull();
// Test 'invalid' icon
expect(iconExists(`${prefix}:invalid`)).toBe(false);
expect(getIconData(`${prefix}:invalid`)).toBeUndefined();
expect(getIcon(`${prefix}:invalid`)).toBeNull();
}); });
it('Invalid icon name', () => { it('Invalid icon name', () => {
const testName = 'storage' + (count++).toString(); const testName = 'storage' + (count++).toString();
// Reset module
allowSimpleNames(false);
// Empty // Empty
expect(iconExists(testName)).toBe(false); expect(iconExists(testName)).toBe(false);
expect(getIcon(testName)).toBeNull(); expect(getIcon(testName)).toBeNull();
expect(getIconData(testName)).toBeUndefined();
// Add and test one icon (icon should not be added) // Add and test one icon (icon should not be added)
expect( expect(
@ -54,9 +98,6 @@ describe('Testing IconifyStorageFunctions', () => {
}); });
it('Invalid icon set', () => { it('Invalid icon set', () => {
// Reset module
allowSimpleNames(false);
// Icon set without prefix (should work only when simple names are allowed, tested later in this file) // Icon set without prefix (should work only when simple names are allowed, tested later in this file)
expect( expect(
addCollection({ addCollection({
@ -87,9 +128,6 @@ describe('Testing IconifyStorageFunctions', () => {
}) })
).toBe(true); ).toBe(true);
expect(iconExists(testName)).toBe(true); expect(iconExists(testName)).toBe(true);
// Reset config after test
allowSimpleNames(false);
}); });
it('Collection with simple icon name', () => { it('Collection with simple icon name', () => {
@ -104,6 +142,7 @@ describe('Testing IconifyStorageFunctions', () => {
const name1 = 'test' + n.toString(); const name1 = 'test' + n.toString();
const prefix2 = `prefixed${n}`; const prefix2 = `prefixed${n}`;
const name2 = `icon${n2}`; const name2 = `icon${n2}`;
const missing = `missing${n}`;
expect( expect(
addCollection({ addCollection({
prefix: '', prefix: '',
@ -115,38 +154,41 @@ describe('Testing IconifyStorageFunctions', () => {
body: '<g data-icon="prefixed-icon" />', body: '<g data-icon="prefixed-icon" />',
}, },
}, },
not_found: [missing],
}) })
).toBe(true); ).toBe(true);
// Test 'test' // Test 'test'
name = name1; name = name1;
expect(iconExists(name)).toBe(true); expect(iconExists(name)).toBe(true);
expect(getIcon(name)).toEqual( let expected = fullIcon({
fullIcon({ body: '<g data-icon="basic-icon" />',
body: '<g data-icon="basic-icon" />', });
}) expect(getIcon(name)).toEqual(expected);
); expect(getIconData(name)).toEqual(expected);
// Test prefixed icon, using ':' separator // Test prefixed icon, using ':' separator
name = `${prefix2}:${name2}`; name = `${prefix2}:${name2}`;
expect(listIcons('', prefix2)).toEqual([name]); expect(listIcons('', prefix2)).toEqual([name]);
expect(iconExists(name)).toBe(true); expect(iconExists(name)).toBe(true);
expect(getIcon(name)).toEqual( expected = fullIcon({
fullIcon({ body: '<g data-icon="prefixed-icon" />',
body: '<g data-icon="prefixed-icon" />', });
}) expect(getIcon(name)).toEqual(expected);
); expect(getIconData(name)).toEqual(expected);
// Test prefixed icon, using '-' separator // Test prefixed icon, using '-' separator
name = `${prefix2}-${name2}`; name = `${prefix2}-${name2}`;
expect(iconExists(name)).toBe(true); expect(iconExists(name)).toBe(true);
expect(getIcon(name)).toEqual( expected = fullIcon({
fullIcon({ body: '<g data-icon="prefixed-icon" />',
body: '<g data-icon="prefixed-icon" />', });
}) expect(getIcon(name)).toEqual(expected);
); expect(getIconData(name)).toEqual(expected);
// Reset config after test // Test missing icon: should not exist because without provider missing icon cannot be added
allowSimpleNames(false); expect(iconExists(missing)).toBe(false);
expect(getIcon(missing)).toBeNull();
expect(getIconData(missing)).toBeUndefined();
}); });
}); });

View File

@ -3,7 +3,6 @@ import {
newStorage, newStorage,
addIconToStorage, addIconToStorage,
iconExists, iconExists,
getIconFromStorage,
addIconSet, addIconSet,
getStorage, getStorage,
listIcons, listIcons,
@ -65,7 +64,7 @@ describe('Testing storage', () => {
vFlip: false, vFlip: false,
rotate: 0, rotate: 0,
}; };
const icon = getIconFromStorage(storage, 'test'); const icon = storage.icons['test'];
expect(icon).toEqual(expected); expect(icon).toEqual(expected);
// Test icon mutation // Test icon mutation
@ -88,10 +87,9 @@ describe('Testing storage', () => {
vFlip: false, vFlip: false,
rotate: 1, rotate: 1,
}; };
expect(getIconFromStorage(storage, 'constructor')).toEqual(expected); expect(storage.icons['constructor']).toEqual(expected);
expect(getIconFromStorage(storage, 'invalid')).toBeNull(); expect(storage.icons['invalid']).toBeUndefined();
expect(getIconFromStorage(storage, 'missing')).toBeNull();
}); });
it('Adding simple icon set', () => { it('Adding simple icon set', () => {
@ -134,7 +132,7 @@ describe('Testing storage', () => {
vFlip: false, vFlip: false,
rotate: 0, rotate: 0,
}; };
expect(getIconFromStorage(storage, 'icon1')).toEqual(expected); expect(storage.icons['icon1']).toEqual(expected);
expected = { expected = {
body: '<path d="icon2" />', body: '<path d="icon2" />',
width: 24, width: 24,
@ -145,9 +143,7 @@ describe('Testing storage', () => {
vFlip: false, vFlip: false,
rotate: 0, rotate: 0,
}; };
expect(getIconFromStorage(storage, 'icon2')).toEqual(expected); expect(storage.icons['icon2']).toEqual(expected);
expect(getIconFromStorage(storage, 'invalid')).toBeNull();
expect(getIconFromStorage(storage, 'missing')).toBeNull();
}); });
it('Icon set with aliases that use transformations', () => { it('Icon set with aliases that use transformations', () => {
@ -190,9 +186,7 @@ describe('Testing storage', () => {
vFlip: false, vFlip: false,
rotate: 0, rotate: 0,
}; };
expect(getIconFromStorage(storage, '16-chevron-left')).toEqual( expect(storage.icons['16-chevron-left']).toEqual(expected);
expected
);
// Test alias // Test alias
expected = { expected = {
@ -205,9 +199,7 @@ describe('Testing storage', () => {
vFlip: false, vFlip: false,
rotate: 0, rotate: 0,
}; };
expect(getIconFromStorage(storage, '16-chevron-right')).toEqual( expect(storage.icons['16-chevron-right']).toEqual(expected);
expected
);
}); });
it('List icons in a global storage', () => { it('List icons in a global storage', () => {

View File

@ -1,7 +1,4 @@
import { import { getStorage } from '@iconify/core/lib/storage/storage';
getIconFromStorage,
getStorage,
} from '@iconify/core/lib/storage/storage';
import { isPending, loadIcons } from '@iconify/core/lib/api/icons'; import { isPending, loadIcons } from '@iconify/core/lib/api/icons';
import { findRootNode, listRootNodes } from '../observer/root'; import { findRootNode, listRootNodes } from '../observer/root';
import type { ObservedNode } from '../observer/types'; import type { ObservedNode } from '../observer/types';
@ -65,10 +62,11 @@ export function scanDOM(rootNode?: ObservedNode, addTempNode = false): void {
const { provider, prefix, name } = icon; const { provider, prefix, name } = icon;
const storage = getStorage(provider, prefix); const storage = getStorage(provider, prefix);
if (storage.icons[name]) { const storedIcon = storage.icons[name];
if (storedIcon) {
return { return {
status: 'loaded', status: 'loaded',
icon: getIconFromStorage(storage, name), icon: storedIcon,
}; };
} }

View File

@ -4,7 +4,7 @@ import { addAPIProvider } from '@iconify/core/lib/api/config';
import { setAPIModule } from '@iconify/core/lib/api/modules'; import { setAPIModule } from '@iconify/core/lib/api/modules';
import { removeRootNode, listRootNodes } from '../src/observer/root'; import { removeRootNode, listRootNodes } from '../src/observer/root';
import { onReady } from '../src/helpers/ready'; import { onReady } from '../src/helpers/ready';
import { stopObserver, stopObserving } from '../src/observer'; import { stopObserver } from '../src/observer';
/** /**
* Generate next prefix * Generate next prefix

View File

@ -316,20 +316,23 @@ class IconComponent extends React.Component<
// Load icon // Load icon
const data = getIconData(iconName); const data = getIconData(iconName);
if (data === null) { if (!data) {
// Icon needs to be loaded // Icon data is not available
if (!this._loading || this._loading.name !== icon) { if (!this._loading || this._loading.name !== icon) {
// New icon to load // New icon to load
this._abortLoading(); this._abortLoading();
this._icon = ''; this._icon = '';
this._setData(null); this._setData(null);
this._loading = { if (data !== null) {
name: icon, // Icon was not loaded
abort: loadIcons( this._loading = {
[iconName], name: icon,
this._checkIcon.bind(this, false) abort: loadIcons(
), [iconName],
}; this._checkIcon.bind(this, false)
),
};
}
} }
return; return;
} }

View File

@ -293,8 +293,8 @@ export function checkIconState(
// Load icon // Load icon
const data = getIconData(iconName); const data = getIconData(iconName);
if (data === null) { if (!data) {
// Icon needs to be loaded // Icon data is not available
// Do not load icon until component is mounted // Do not load icon until component is mounted
if (mounted && (!state.loading || state.loading.name !== icon)) { if (mounted && (!state.loading || state.loading.name !== icon)) {
// New icon to load // New icon to load

View File

@ -311,18 +311,21 @@ export const Icon = defineComponent({
// Load icon // Load icon
const data = getIconData(iconName); const data = getIconData(iconName);
if (data === null) { if (!data) {
// Icon needs to be loaded // Icon data is not available
if (!this._loadingIcon || this._loadingIcon.name !== icon) { if (!this._loadingIcon || this._loadingIcon.name !== icon) {
// New icon to load // New icon to load
this.abortLoading(); this.abortLoading();
this._name = ''; this._name = '';
this._loadingIcon = { if (data !== null) {
name: icon, // Icon was not loaded
abort: loadIcons([iconName], () => { this._loadingIcon = {
this.counter++; name: icon,
}), abort: loadIcons([iconName], () => {
}; this.counter++;
}),
};
}
} }
return null; return null;
} }

View File

@ -297,18 +297,21 @@ export const Icon = Vue.extend({
// Load icon // Load icon
const data = getIconData(iconName); const data = getIconData(iconName);
if (data === null) { if (!data) {
// Icon needs to be loaded // Icon data is not available
if (!this._loadingIcon || this._loadingIcon.name !== icon) { if (!this._loadingIcon || this._loadingIcon.name !== icon) {
// New icon to load // New icon to load
this.abortLoading(); this.abortLoading();
this._name = ''; this._name = '';
this._loadingIcon = { if (data !== null) {
name: icon, // Icon was not loaded
abort: loadIcons([iconName], () => { this._loadingIcon = {
this.$forceUpdate(); name: icon,
}), abort: loadIcons([iconName], () => {
}; this.$forceUpdate();
}),
};
}
} }
return null; return null;
} }