2
0
mirror of https://github.com/iconify/iconify.git synced 2024-09-19 08:49:02 +00:00

Store partial icon data in storage to reduce memory usage

This commit is contained in:
Vjacheslav Trushkin 2022-07-02 10:53:06 +03:00
parent 21d45bc28c
commit a5c9edb4da
30 changed files with 228 additions and 227 deletions

View File

@ -1,6 +1,4 @@
import { defineNuxtConfig } from 'nuxt3'
import { defineNuxtConfig } from 'nuxt';
// https://v3.nuxtjs.org/docs/directory-structure/nuxt.config
export default defineNuxtConfig({
})
export default defineNuxtConfig({});

View File

@ -7,7 +7,7 @@
"start": "node .output/server/index.mjs"
},
"devDependencies": {
"nuxt3": "latest",
"nuxt": "npm:nuxt3@latest",
"ufo": "^0.8.4"
},
"dependencies": {

View File

@ -5,8 +5,7 @@ import { tracked } from '@glimmer/tracking';
import type { IconifyIconName } from '@iconify/utils/lib/icon/name';
import { stringToIcon } from '@iconify/utils/lib/icon/name';
import { getIconData } from '@iconify/core/lib/storage/functions';
import type { FullIconifyIcon } from '@iconify/utils/lib/icon/defaults';
import { defaultIconProps } from '@iconify/utils/lib/icon/defaults';
import type { IconifyIcon } from '@iconify/utils/lib/icon/defaults';
// API
import { loadIcon } from '@iconify/core/lib/api/icons';
@ -24,7 +23,7 @@ interface CurrentIconData {
className: string;
// Data if icon has been loaded
data?: FullIconifyIcon;
data?: IconifyIcon;
}
/**
@ -69,7 +68,7 @@ export class IconifyIconComponent extends Component<IconifyIconProps> {
this._icon = null;
// Render object
return render({ ...defaultIconProps, ...icon }, this.args, '');
return render(icon, this.args, '');
}
// Already loaded

View File

@ -26,7 +26,7 @@ export interface RenderResult {
*/
export const render = (
// Icon must be validated before calling this function
icon: Required<IconifyIcon>,
icon: IconifyIcon,
// Partial properties
props: IconifyIconProps,

View File

@ -20,7 +20,6 @@ import { iconToSVG as buildIcon } from '@iconify/utils/lib/svg/build';
import { replaceIDs } from '@iconify/utils/lib/svg/id';
import { calculateSize } from '@iconify/utils/lib/svg/size';
import type { IconifyIconBuildResult } from '@iconify/utils/lib/svg/build';
import { defaultIconProps } from '@iconify/utils/lib/icon/defaults';
// API
import type {
@ -77,6 +76,7 @@ import type {
// Render SVG
import { render } from './render';
import { defaultIconProps } from '@iconify/utils/lib/icon/defaults';
/**
* Export required types
@ -221,7 +221,7 @@ interface InternalIconProps extends IconProps {
}
interface IconComponentData {
data: Required<IconifyIcon>;
data: IconifyIcon;
classes?: string[];
}
@ -290,7 +290,7 @@ class IconComponent extends React.Component<
if (changed || state.icon === null) {
// Set data if it was changed
this._setData({
data: { ...defaultIconProps, ...icon },
data: icon,
});
}
return;
@ -406,7 +406,15 @@ class IconComponent extends React.Component<
}
// Render icon
return render(icon.data, newProps, props._inline, props._ref);
return render(
{
...defaultIconProps,
...icon.data,
},
newProps,
props._inline,
props._ref
);
}
}

View File

@ -26,7 +26,7 @@ export { IconifyIcon, IconifyJSON, IconifyIconSize, IconifyRenderMode };
/**
* Storage for icons referred by name
*/
const storage: Record<string, Required<IconifyIcon>> = Object.create(null);
const storage: Record<string, IconifyIcon> = Object.create(null);
/**
* Generate icon
@ -37,11 +37,12 @@ function component(
ref?: React.ForwardedRef<IconRef>
): JSX.Element {
// Split properties
const propsIcon = props.icon;
const icon =
typeof props.icon === 'string'
? storage[props.icon]
: typeof props.icon === 'object'
? { ...defaultIconProps, ...props.icon }
typeof propsIcon === 'string'
? storage[propsIcon]
: typeof propsIcon === 'object'
? propsIcon
: null;
// Validate icon object
@ -56,7 +57,15 @@ function component(
}
// Valid icon: render it
return render(icon, props, inline, ref as IconRef);
return render(
{
...defaultIconProps,
...icon,
},
props,
inline,
ref as IconRef
);
}
/**
@ -89,7 +98,7 @@ export const InlineIcon = React.forwardRef<IconRef, IconProps>(
* @param data
*/
export function addIcon(name: string, data: IconifyIcon): void {
storage[name] = { ...defaultIconProps, ...data };
storage[name] = data;
}
/**

View File

@ -217,7 +217,7 @@ interface IconLoadingState {
abort: IconifyIconLoaderAbort;
}
type IconComponentData = Required<IconifyIcon> | null;
type IconComponentData = IconifyIcon | null;
interface IconState {
// Last icon name
@ -330,7 +330,15 @@ export function generateIcon(
icon: IconComponentData,
props: IconProps
): RenderResult | null {
return icon ? render(icon, props) : null;
return icon
? render(
{
...defaultIconProps,
...icon,
},
props
)
: null;
}
/**

View File

@ -9,7 +9,7 @@ import type { IconProps } from './props';
/**
* Storage for icons referred by name
*/
const storage: Record<string, Required<IconifyIcon>> = Object.create(null);
const storage: Record<string, IconifyIcon> = Object.create(null);
/**
* Generate icon
@ -32,7 +32,13 @@ export function generateIcon(props: IconProps): RenderResult | null {
return null;
}
return render(icon, props);
return render(
{
...defaultIconProps,
...icon,
},
props
);
}
/**
@ -42,7 +48,7 @@ export function generateIcon(props: IconProps): RenderResult | null {
* @param data
*/
export function addIcon(name: string, data: IconifyIcon): void {
storage[name] = { ...defaultIconProps, ...data };
storage[name] = data;
}
/**

View File

@ -1,4 +1,4 @@
import type { FullIconifyIcon } from '@iconify/utils/lib/icon/defaults';
import type { IconifyIcon } from '@iconify/utils/lib/icon/defaults';
import { iconToSVG } from '@iconify/utils/lib/svg/build';
import { replaceIDs } from '@iconify/utils/lib/svg/id';
import { iconToHTML } from '@iconify/utils/lib/svg/html';
@ -17,7 +17,7 @@ import { applyStyle } from './style';
export function renderInlineSVG(
element: IconifyElement,
props: IconifyElementProps,
iconData: FullIconifyIcon
iconData: IconifyIcon
): IconifyElement {
// Create placeholder. Why placeholder? innerHTML setter on SVG does not work in some environments.
let span: HTMLSpanElement;

View File

@ -10,8 +10,8 @@ import {
IconifyElementProps,
} from './config';
import { scanRootNode } from './find';
import type { IconifyIconName } from '../iconify';
import type { FullIconifyIcon } from '@iconify/utils/lib/icon/defaults';
import type { IconifyIconName, IconifyIcon } from '../iconify';
import { defaultIconProps } from '@iconify/utils/lib/icon/defaults';
import {
observe,
pauseObservingNode,
@ -56,7 +56,7 @@ export function scanDOM(rootNode?: ObservedNode, addTempNode = false): void {
*/
interface GetIconResult {
status: IconifyElementData['status'];
icon?: FullIconifyIcon;
icon?: IconifyIcon;
}
function getIcon(icon: IconifyIconName, load: boolean): GetIconResult {
const { provider, prefix, name } = icon;
@ -114,7 +114,7 @@ export function scanDOM(rootNode?: ObservedNode, addTempNode = false): void {
function render(
element: IconifyElement,
props: IconifyElementProps,
iconData: FullIconifyIcon
iconData: IconifyIcon
) {
if (!paused) {
paused = true;
@ -133,7 +133,15 @@ export function scanDOM(rootNode?: ObservedNode, addTempNode = false): void {
: null);
if (typeof isMask === 'boolean') {
renderBackground(element, props, iconData, isMask);
renderBackground(
element,
props,
{
...defaultIconProps,
...iconData,
},
isMask
);
return;
}
}

View File

@ -232,7 +232,7 @@ const emptyIcon = {
* Component
*/
interface IconComponentData {
data: Required<IconifyIcon>;
data: IconifyIcon;
classes?: string[];
}
@ -289,7 +289,7 @@ export const Icon = defineComponent({
this._name = '';
this.abortLoading();
return {
data: { ...defaultIconProps, ...icon },
data: icon,
};
}
@ -376,7 +376,13 @@ export const Icon = defineComponent({
}
// Render icon
return render(icon.data, newProps);
return render(
{
...defaultIconProps,
...icon.data,
},
newProps
);
},
});

View File

@ -34,7 +34,7 @@ export { IconifyIcon, IconifyJSON, IconifyIconSize, IconifyRenderMode };
/**
* Storage for icons referred by name
*/
const storage: Record<string, Required<IconifyIcon>> = Object.create(null);
const storage: Record<string, IconifyIcon> = Object.create(null);
/**
* Add icon to storage, allowing to call it by name
@ -43,7 +43,7 @@ const storage: Record<string, Required<IconifyIcon>> = Object.create(null);
* @param data
*/
export function addIcon(name: string, data: IconifyIcon): void {
storage[name] = { ...defaultIconProps, ...data };
storage[name] = data;
}
/**
@ -82,11 +82,12 @@ export const Icon = defineComponent({
const props = this.$attrs;
// Check icon
const icon =
typeof props.icon === 'string'
? storage[props.icon]
: typeof props.icon === 'object'
? { ...defaultIconProps, ...props.icon }
const propsIcon = props.icon;
const icon: IconifyIcon | null =
typeof propsIcon === 'string'
? storage[propsIcon]
: typeof propsIcon === 'object'
? propsIcon
: null;
// Validate icon object
@ -99,6 +100,12 @@ export const Icon = defineComponent({
}
// Valid icon: render it
return render(icon, props);
return render(
{
...defaultIconProps,
...icon,
},
props
);
},
});

View File

@ -22,7 +22,6 @@ import { iconToSVG as buildIcon } from '@iconify/utils/lib/svg/build';
import { replaceIDs } from '@iconify/utils/lib/svg/id';
import { calculateSize } from '@iconify/utils/lib/svg/size';
import type { IconifyIconBuildResult } from '@iconify/utils/lib/svg/build';
import { defaultIconProps } from '@iconify/utils/lib/icon/defaults';
// API
import type {
@ -215,7 +214,6 @@ if (typeof document !== 'undefined' && typeof window !== 'undefined') {
* Empty icon data, rendered when icon is not available
*/
const emptyIcon = {
...defaultIconProps,
body: '',
};
@ -223,7 +221,7 @@ const emptyIcon = {
* Component
*/
interface IconComponentData {
data: Required<IconifyIcon>;
data: IconifyIcon;
classes?: string[];
}
@ -277,7 +275,7 @@ export const Icon = Vue.extend({
this._name = '';
this.abortLoading();
return {
data: { ...defaultIconProps, ...icon },
data: icon,
};
}

View File

@ -3,7 +3,6 @@ import type { CreateElement, VNode } from 'vue';
import type { ExtendedVue } from 'vue/types/vue';
import type { IconifyIcon, IconifyJSON } from '@iconify/types';
import type { IconifyIconSize } from '@iconify/utils/lib/customisations/defaults';
import { defaultIconProps } from '@iconify/utils/lib/icon/defaults';
import { parseIconSet } from '@iconify/utils/lib/icon-set/parse';
import { quicklyValidateIconSet } from '@iconify/utils/lib/icon-set/validate-basic';
import type {
@ -21,16 +20,12 @@ export { IconifyIconCustomisations, IconifyIconProps, IconProps };
/**
* Export types that could be used in component
*/
export {
IconifyIcon,
IconifyJSON,
IconifyIconSize,
};
export { IconifyIcon, IconifyJSON, IconifyIconSize };
/**
* Storage for icons referred by name
*/
const storage: Record<string, Required<IconifyIcon>> = Object.create(null);
const storage: Record<string, IconifyIcon> = Object.create(null);
/**
* Add icon to storage, allowing to call it by name
@ -39,7 +34,7 @@ const storage: Record<string, Required<IconifyIcon>> = Object.create(null);
* @param data
*/
export function addIcon(name: string, data: IconifyIcon): void {
storage[name] = {...defaultIconProps, ...data};
storage[name] = data;
}
/**
@ -58,11 +53,12 @@ export function addCollection(
: prefix !== false && typeof data.prefix === 'string'
? data.prefix + ':'
: '';
quicklyValidateIconSet(data) && parseIconSet(data, (name, icon) => {
if (icon) {
storage[iconPrefix + name] = icon;
}
});
quicklyValidateIconSet(data) &&
parseIconSet(data, (name, icon) => {
if (icon) {
storage[iconPrefix + name] = icon;
}
});
}
/**
@ -78,11 +74,12 @@ export const Icon = Vue.extend({
const props = this.$attrs;
// Check icon
const propsIcon = props.icon;
const icon =
typeof props.icon === 'string'
? storage[props.icon]
: typeof props.icon === 'object'
? {...defaultIconProps, ...props.icon}
typeof propsIcon === 'string'
? storage[propsIcon]
: typeof propsIcon === 'object'
? propsIcon
: null;
// Validate icon object

View File

@ -1,14 +1,12 @@
import type _Vue from 'vue';
import type { VNode, VNodeData, RenderContext } from 'vue';
import type { IconifyIcon } from '@iconify/types';
import {
mergeCustomisations,
} from '@iconify/utils/lib/customisations/merge';
import { mergeCustomisations } from '@iconify/utils/lib/customisations/merge';
import { flipFromString } from '@iconify/utils/lib/customisations/flip';
import { rotateFromString } from '@iconify/utils/lib/customisations/rotate';
import { iconToSVG } from '@iconify/utils/lib/svg/build';
import { replaceIDs } from '@iconify/utils/lib/svg/id';
import type { IconifyIconCustomisations, IconProps } from './props';
import type { IconProps } from './props';
import { defaultExtendedIconCustomisations } from './props';
/**
@ -25,18 +23,17 @@ const svgDefaults: Record<string, unknown> = {
* Aliases for customisations.
* In Vue 'v-' properties are reserved, so v-flip must be renamed
*/
const customisationAliases: Record<string, string> = {};
['horizontal', 'vertical'].forEach((prefix) => {
const attr = prefix.slice(0, 1) + 'Flip';
// vertical-flip
customisationAliases[prefix + '-flip'] = attr;
// v-flip
customisationAliases[prefix.slice(0, 1) + '-flip'] = attr;
// verticalFlip
customisationAliases[prefix + 'Flip'] = attr;
});
const customisationAliases: Record<string, string> = {};
['horizontal', 'vertical'].forEach((prefix) => {
const attr = prefix.slice(0, 1) + 'Flip';
// vertical-flip
customisationAliases[prefix + '-flip'] = attr;
// v-flip
customisationAliases[prefix.slice(0, 1) + '-flip'] = attr;
// verticalFlip
customisationAliases[prefix + 'Flip'] = attr;
});
/**
* Render icon
@ -51,7 +48,7 @@ export const render = (
contextData: VNodeData,
// Icon must be validated before calling this function
icon: Required<IconifyIcon>
icon: IconifyIcon
): VNode => {
// Split properties
const customisations = mergeCustomisations(

View File

@ -1,4 +1,4 @@
import { defineNuxtConfig } from 'nuxt3';
import { defineNuxtConfig } from 'nuxt';
// https://v3.nuxtjs.org/docs/directory-structure/nuxt.config
export default defineNuxtConfig({

View File

@ -8,7 +8,7 @@
},
"devDependencies": {
"iconify-icon": "workspace:*",
"nuxt3": "latest",
"nuxt": "npm:nuxt3@latest",
"ufo": "^0.8.4"
}
}

View File

@ -12,7 +12,7 @@ import type { CurrentIconData } from './state';
export type IconOnLoadCallback = (
value: unknown,
name: IconifyIconName,
data?: Required<IconifyIcon> | null
data?: IconifyIcon | null
) => void;
/**

View File

@ -1,17 +1,13 @@
import type { IconifyIcon } from '@iconify/types';
import { defaultIconProps } from '@iconify/utils/lib/icon/defaults';
/**
* Test icon string
*/
export function testIconObject(
value: unknown
): Required<IconifyIcon> | undefined {
export function testIconObject(value: unknown): IconifyIcon | undefined {
try {
const obj = typeof value === 'string' ? JSON.parse(value) : value;
if (typeof obj.body === 'string') {
return {
...defaultIconProps,
...obj,
};
}

View File

@ -10,7 +10,7 @@ export interface CurrentIconData {
value: unknown;
// Data, if available. Can be null if icon is missing in API
data?: Required<IconifyIcon> | null;
data?: IconifyIcon | null;
// Icon name as object, if `value` is a valid icon name
name?: IconifyIconName | null;
@ -20,9 +20,9 @@ export interface CurrentIconData {
}
/**
* Same as above, if
* Same as above, used if icon is currenly being rendered
*/
export interface RenderedCurrentIconData extends CurrentIconData {
// Full icon data
data: Required<IconifyIcon>;
// Icon data
data: IconifyIcon;
}

View File

@ -1,3 +1,4 @@
import { defaultIconProps } from '@iconify/utils/lib/icon/defaults';
import { iconToSVG } from '@iconify/utils/lib/svg/build';
import type { RenderedState } from '../state';
import { renderSPAN } from './span';
@ -25,7 +26,14 @@ export function renderIcon(parent: Element | ShadowRoot, state: RenderedState) {
break;
default:
node = renderSPAN(renderData, iconData, mode === 'mask');
node = renderSPAN(
renderData,
{
...defaultIconProps,
...iconData,
},
mode === 'mask'
);
}
// Set element

View File

@ -1,5 +1,4 @@
import { fakeAPI, nextPrefix, mockAPIData } from './helpers';
import { defaultIconProps } from '@iconify/utils/lib/icon/defaults';
import { addCollection } from '@iconify/core/lib/storage/functions';
import { parseIconValue } from '../src/attributes/icon/index';
@ -41,7 +40,6 @@ describe('Testing parseIconValue with API', () => {
name,
});
expect(data).toEqual({
...defaultIconProps,
body: '<g />',
});
@ -111,7 +109,6 @@ describe('Testing parseIconValue with API', () => {
name,
},
data: {
...defaultIconProps,
body: '<g id="test" />',
},
});

View File

@ -1,5 +1,4 @@
import { parseIconValue } from '../src/attributes/icon/index';
import { defaultIconProps } from '@iconify/utils/lib/icon/defaults';
describe('Testing parseIconValue without API', () => {
it('Instantly loading object', () => {
@ -11,10 +10,7 @@ describe('Testing parseIconValue without API', () => {
});
expect(result).toEqual({
value,
data: {
...defaultIconProps,
...value,
},
data: value,
});
expect(result.value).toBe(value);
});
@ -29,7 +25,6 @@ describe('Testing parseIconValue without API', () => {
expect(result).toEqual({
value,
data: {
...defaultIconProps,
body: '<g />',
},
});

View File

@ -1,5 +1,4 @@
import { testIconObject } from '../src/attributes/icon/object';
import { defaultIconProps } from '@iconify/utils/lib/icon/defaults';
describe('Testing testIconObject', () => {
it('Objects', () => {
@ -8,7 +7,6 @@ describe('Testing testIconObject', () => {
body: '<g />',
})
).toEqual({
...defaultIconProps,
body: '<g />',
});
@ -19,7 +17,6 @@ describe('Testing testIconObject', () => {
height: '32',
})
).toEqual({
...defaultIconProps,
body: '<g />',
width: 24,
// Validation is simple, this will fail during render
@ -50,7 +47,6 @@ describe('Testing testIconObject', () => {
})
)
).toEqual({
...defaultIconProps,
body: '<g />',
});

View File

@ -10,6 +10,7 @@ import { allowSimpleNames, getIconData } from '../storage/functions';
import { sendAPIQuery } from './query';
import { storeInBrowserStorage } from '../browser-storage/store';
import type { IconStorageWithAPI } from './types';
import { defaultIconProps } from '@iconify/utils/lib/icon/defaults';
// Empty abort callback for loadIcons()
function emptyCallback(): void {
@ -249,7 +250,7 @@ export const loadIcons: IconifyLoadIcons = (
};
/**
* Cache for loadIcon promises
* Load one icon using Promise
*/
export const loadIcon = (
icon: IconifyIconName | string
@ -261,6 +262,7 @@ export const loadIcon = (
const data = getIconData(iconObj);
if (data) {
fulfill({
...defaultIconProps,
...data,
});
return;

View File

@ -1,5 +1,5 @@
import type { IconifyJSON, IconifyIcon } from '@iconify/types';
import type { FullIconifyIcon } from '@iconify/utils/lib/icon/defaults';
import { defaultIconProps } from '@iconify/utils/lib/icon/defaults';
import { parseIconSet } from '@iconify/utils/lib/icon-set/parse';
import { quicklyValidateIconSet } from '@iconify/utils/lib/icon-set/validate-basic';
import type { IconifyIconName } from '@iconify/utils/lib/icon/name';
@ -53,25 +53,24 @@ export function allowSimpleNames(allow?: boolean): boolean {
* Get icon data
*
* Returns:
* - Required<IconifyIcon> on success, object directly from storage so don't modify it
* - 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(
name: string | IconifyIconName
): FullIconifyIcon | null | undefined {
): IconifyIcon | null | undefined {
const icon =
typeof name === 'string' ? stringToIcon(name, true, simpleNames) : name;
if (!icon) {
return;
if (icon) {
const storage = getStorage(icon.provider, icon.prefix);
const iconName = icon.name;
return (
storage.icons[iconName] ||
(storage.missing.has(iconName) ? null : void 0)
);
}
const storage = getStorage(icon.provider, icon.prefix);
const iconName = icon.name;
return (
storage.icons[iconName] ||
(storage.missing.has(iconName) ? null : void 0)
);
}
/**
@ -143,10 +142,16 @@ export function addCollection(data: IconifyJSON, provider?: string): boolean {
export function iconExists(name: string): boolean {
return !!getIconData(name);
}
/**
* Get icon
* Get full icon
*/
export function getIcon(name: string): Required<IconifyIcon> | null {
const result = getIconData(name);
return result ? { ...result } : null;
return result
? {
...defaultIconProps,
...result,
}
: null;
}

View File

@ -1,13 +1,11 @@
import type { IconifyJSON, IconifyIcon } from '@iconify/types';
import type { FullIconifyIcon } from '@iconify/utils/lib/icon/defaults';
import { defaultIconProps } from '@iconify/utils/lib/icon/defaults';
import { parseIconSet } from '@iconify/utils/lib/icon-set/parse';
import { quicklyValidateIconSet } from '@iconify/utils/lib/icon-set/validate-basic';
/**
* List of icons
*/
type IconRecords = Record<string, FullIconifyIcon>;
type IconRecords = Record<string, IconifyIcon>;
/**
* Storage type
@ -72,10 +70,7 @@ export function addIconSet(storage: IconStorage, data: IconifyJSON): string[] {
return parseIconSet(data, (name: string, icon: IconifyIcon | null) => {
if (icon) {
storage.icons[name] = {
...defaultIconProps,
...icon,
};
storage.icons[name] = icon;
} else {
storage.missing.add(name);
}
@ -92,11 +87,8 @@ export function addIconToStorage(
): boolean {
try {
if (typeof icon.body === 'string') {
// Freeze icon to make sure it will not be modified
storage.icons[name] = Object.freeze({
...defaultIconProps,
...icon,
});
// Make a copy of object to make sure it will not be not modified
storage.icons[name] = { ...icon };
return true;
}
} catch (err) {

View File

@ -29,8 +29,8 @@ describe('Testing IconifyStorageFunctions', () => {
// Empty
expect(iconExists(testName)).toBe(false);
expect(getIcon(testName)).toBeNull();
expect(getIconData(testName)).toBeUndefined();
expect(getIcon(testName)).toBeNull();
expect(listIcons(provider)).toEqual([]);
// Add and test one icon
@ -43,11 +43,13 @@ describe('Testing IconifyStorageFunctions', () => {
expect(listIcons(provider)).toEqual([testName]);
let expected = {
...defaultIconProps,
body: '<g />',
};
expect(getIconData(testName)).toEqual(expected);
expect(getIcon(testName)).toEqual(expected);
expect(getIcon(testName)).toEqual({
...defaultIconProps,
...expected,
});
// Add icon set
const prefix = 'prefix' + (count++).toString();
@ -65,11 +67,13 @@ describe('Testing IconifyStorageFunctions', () => {
// Test 'home' icon
expect(iconExists(`${prefix}:home`)).toBe(true);
expected = {
...defaultIconProps,
body: '<g id="home" />',
};
expect(getIconData(`${prefix}:home`)).toEqual(expected);
expect(getIcon(`${prefix}:home`)).toEqual(expected);
expect(getIcon(`${prefix}:home`)).toEqual({
...defaultIconProps,
...expected,
});
// Test 'missing' icon
expect(iconExists(`${prefix}:missing`)).toBe(false);
@ -87,8 +91,8 @@ describe('Testing IconifyStorageFunctions', () => {
// Empty
expect(iconExists(testName)).toBe(false);
expect(getIcon(testName)).toBeNull();
expect(getIconData(testName)).toBeUndefined();
expect(getIcon(testName)).toBeNull();
// Add and test one icon (icon should not be added)
expect(
@ -164,36 +168,42 @@ describe('Testing IconifyStorageFunctions', () => {
name = name1;
expect(iconExists(name)).toBe(true);
let expected = {
...defaultIconProps,
body: '<g data-icon="basic-icon" />',
};
expect(getIcon(name)).toEqual(expected);
expect(getIconData(name)).toEqual(expected);
expect(getIcon(name)).toEqual({
...defaultIconProps,
...expected,
});
// Test prefixed icon, using ':' separator
name = `${prefix2}:${name2}`;
expect(listIcons('', prefix2)).toEqual([name]);
expect(iconExists(name)).toBe(true);
expected = {
...defaultIconProps,
body: '<g data-icon="prefixed-icon" />',
};
expect(getIcon(name)).toEqual(expected);
expect(getIconData(name)).toEqual(expected);
expect(getIcon(name)).toEqual({
...defaultIconProps,
...expected,
});
// Test prefixed icon, using '-' separator
name = `${prefix2}-${name2}`;
expect(iconExists(name)).toBe(true);
expected = {
...defaultIconProps,
body: '<g data-icon="prefixed-icon" />',
};
expect(getIcon(name)).toEqual(expected);
expect(getIconData(name)).toEqual(expected);
expect(getIcon(name)).toEqual({
...defaultIconProps,
...expected,
});
// Test missing icon: should not exist because without provider missing icon cannot be added
expect(iconExists(missing)).toBe(false);
expect(getIcon(missing)).toBeNull();
expect(getIconData(missing)).toBeUndefined();
expect(getIcon(missing)).toBeNull();
});
});

View File

@ -1,4 +1,5 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
import type { IconifyIcon } from '@iconify/types';
import {
newStorage,
addIconToStorage,
@ -7,10 +8,6 @@ import {
getStorage,
listIcons,
} from '../../lib/storage/storage';
import type {
IconifyIcon,
FullIconifyIcon,
} from '@iconify/utils/lib/icon/defaults';
describe('Testing storage', () => {
it('Adding icon', () => {
@ -57,37 +54,18 @@ describe('Testing storage', () => {
expect(iconExists(storage, 'not-really-missing')).toBe(true);
// Test getIcon
let expected: FullIconifyIcon = {
let expected: IconifyIcon = {
body: '<path d="" />',
width: 20,
height: 16,
top: 0,
left: 0,
hFlip: false,
vFlip: false,
rotate: 0,
};
const icon = storage.icons['test'];
expect(icon).toEqual(expected);
// Test icon mutation
let thrown = false;
try {
// @ts-ignore
icon.width = 12;
} catch (err) {
thrown = true;
}
expect(thrown).toBe(true);
expected = {
body: '<g></g>',
width: 24,
height: 24,
top: 0,
left: 0,
hFlip: false,
vFlip: false,
rotate: 1,
};
expect(storage.icons['constructor']).toEqual(expected);
@ -125,26 +103,16 @@ describe('Testing storage', () => {
expect(iconExists(storage, 'missing')).toBe(false);
// Test getIcon
let expected: FullIconifyIcon = {
let expected: IconifyIcon = {
body: '<path d="icon1" />',
width: 20,
height: 24,
top: 0,
left: 0,
hFlip: false,
vFlip: false,
rotate: 0,
};
expect(storage.icons['icon1']).toEqual(expected);
expected = {
body: '<path d="icon2" />',
width: 24,
height: 24,
top: 0,
left: 0,
hFlip: false,
vFlip: false,
rotate: 0,
};
expect(storage.icons['icon2']).toEqual(expected);
});
@ -179,15 +147,10 @@ describe('Testing storage', () => {
]);
// Test icon
let expected: FullIconifyIcon = {
let expected: IconifyIcon = {
body: iconBody,
width: 128,
height: 128,
top: 0,
left: 0,
hFlip: false,
vFlip: false,
rotate: 0,
};
expect(storage.icons['16-chevron-left']).toEqual(expected);
@ -196,11 +159,7 @@ describe('Testing storage', () => {
body: iconBody,
width: 128,
height: 128,
top: 0,
left: 0,
hFlip: true,
vFlip: false,
rotate: 0,
};
expect(storage.icons['16-chevron-right']).toEqual(expected);
});

View File

@ -107,12 +107,12 @@ importers:
components-demo/nuxt3-demo:
specifiers:
'@iconify/vue': workspace:*
nuxt3: latest
nuxt: npm:nuxt3@latest
ufo: ^0.8.4
dependencies:
'@iconify/vue': link:../../components/vue
devDependencies:
nuxt3: 3.0.0-rc.4-27605536.8c2c80e_5cbeqmovjazlwrjcfaylsl5bey
nuxt: /nuxt3/3.0.0-rc.4-27611167.a41644e_5cbeqmovjazlwrjcfaylsl5bey
ufo: 0.8.4
components-demo/react-demo:
@ -691,11 +691,11 @@ importers:
iconify-icon-demo/nuxt3-demo:
specifiers:
iconify-icon: workspace:*
nuxt3: latest
nuxt: npm:nuxt3@latest
ufo: ^0.8.4
devDependencies:
iconify-icon: link:../../iconify-icon/icon
nuxt3: 3.0.0-rc.4-27605536.8c2c80e
nuxt: /nuxt3/3.0.0-rc.4-27611167.a41644e
ufo: 0.8.4
iconify-icon-demo/react-demo:
@ -943,7 +943,7 @@ importers:
eslint-plugin-jasmine: 4.1.3
jasmine: 4.2.1
jest: 28.0.0-alpha.11_@types+node@17.0.45
ts-jest: 28.0.0-next.3_wacmy45vuvn6xci2xoa2yuot5q
ts-jest: 28.0.0-next.3_siglip3kymrenbe7xdfdfpitau
tsup: 5.12.9_typescript@4.7.4
packages/core:
@ -1032,7 +1032,7 @@ importers:
eslint-plugin-prettier: 4.0.0_xu6ewijrtliw5q5lksq5uixwby
jest: 28.0.0-alpha.11_jbmz3vlfopghb5mdasddsdxfzq
rimraf: 3.0.2
ts-jest: 28.0.0-next.3_siglip3kymrenbe7xdfdfpitau
ts-jest: 28.0.0-next.3_wacmy45vuvn6xci2xoa2yuot5q
ts-node: 10.8.1_qiyc72axg2v44xl4yovan2v55u
typescript: 4.7.4
unbuild: 0.7.4
@ -3714,11 +3714,11 @@ packages:
resolution: {integrity: sha512-YBI/6o2EBz02tdEJRBK8xkt3zvOFOWlLBf7WKYGBsSYSRtjjgrqPe2skp6VLLmKx5WbHHDNcW+6oACaurxGzeA==}
dev: true
/@nuxt/kit-edge/3.0.0-rc.4-27605536.8c2c80e:
resolution: {integrity: sha512-Fu9ygT3Gi5zbthzZC5PVzaDhVUxLunF1mgfF9b7RoHaO+UoQSWI7AptRwx2jxkUHpftLZjELtDV6MW96xZiWqg==}
/@nuxt/kit-edge/3.0.0-rc.4-27611167.a41644e:
resolution: {integrity: sha512-T9rWEkGG4XmVt/5+oam1aSmX8W7kU2FnXrSl4rTlYT09/po0cNbmvDhUQWqt5LUkJMjPsZB5j+87pq2/m0RUEg==}
engines: {node: ^14.16.0 || ^16.11.0 || ^17.0.0 || ^18.0.0}
dependencies:
'@nuxt/schema': /@nuxt/schema-edge/3.0.0-rc.4-27605536.8c2c80e
'@nuxt/schema': /@nuxt/schema-edge/3.0.0-rc.4-27611167.a41644e
c12: 0.2.7
consola: 2.15.3
defu: 6.0.0
@ -3744,11 +3744,11 @@ packages:
- webpack
dev: true
/@nuxt/kit-edge/3.0.0-rc.4-27605536.8c2c80e_5cbeqmovjazlwrjcfaylsl5bey:
resolution: {integrity: sha512-Fu9ygT3Gi5zbthzZC5PVzaDhVUxLunF1mgfF9b7RoHaO+UoQSWI7AptRwx2jxkUHpftLZjELtDV6MW96xZiWqg==}
/@nuxt/kit-edge/3.0.0-rc.4-27611167.a41644e_5cbeqmovjazlwrjcfaylsl5bey:
resolution: {integrity: sha512-T9rWEkGG4XmVt/5+oam1aSmX8W7kU2FnXrSl4rTlYT09/po0cNbmvDhUQWqt5LUkJMjPsZB5j+87pq2/m0RUEg==}
engines: {node: ^14.16.0 || ^16.11.0 || ^17.0.0 || ^18.0.0}
dependencies:
'@nuxt/schema': /@nuxt/schema-edge/3.0.0-rc.4-27605536.8c2c80e_5cbeqmovjazlwrjcfaylsl5bey
'@nuxt/schema': /@nuxt/schema-edge/3.0.0-rc.4-27611167.a41644e_5cbeqmovjazlwrjcfaylsl5bey
c12: 0.2.7
consola: 2.15.3
defu: 6.0.0
@ -3834,8 +3834,8 @@ packages:
- webpack
dev: true
/@nuxt/schema-edge/3.0.0-rc.4-27605536.8c2c80e:
resolution: {integrity: sha512-KOFpjN2efx9lXj84kSHhJV/XWJ8n0zztnJjjmEY3RhgBTd7mYtdI7BsYPtZ30Tz5vJGMlHrIGkLZW6c+IYAKzw==}
/@nuxt/schema-edge/3.0.0-rc.4-27611167.a41644e:
resolution: {integrity: sha512-FaM88rk9lvgaTUe+YpiNbMDg/iEb98Lejo33B+pHuPFyrZWR+hAFOL27LeEIAGBZk3xQaDfXRU6TYKEPE5iGsQ==}
engines: {node: ^14.16.0 || ^16.11.0 || ^17.0.0 || ^18.0.0}
dependencies:
c12: 0.2.7
@ -3855,8 +3855,8 @@ packages:
- webpack
dev: true
/@nuxt/schema-edge/3.0.0-rc.4-27605536.8c2c80e_5cbeqmovjazlwrjcfaylsl5bey:
resolution: {integrity: sha512-KOFpjN2efx9lXj84kSHhJV/XWJ8n0zztnJjjmEY3RhgBTd7mYtdI7BsYPtZ30Tz5vJGMlHrIGkLZW6c+IYAKzw==}
/@nuxt/schema-edge/3.0.0-rc.4-27611167.a41644e_5cbeqmovjazlwrjcfaylsl5bey:
resolution: {integrity: sha512-FaM88rk9lvgaTUe+YpiNbMDg/iEb98Lejo33B+pHuPFyrZWR+hAFOL27LeEIAGBZk3xQaDfXRU6TYKEPE5iGsQ==}
engines: {node: ^14.16.0 || ^16.11.0 || ^17.0.0 || ^18.0.0}
dependencies:
c12: 0.2.7
@ -3986,13 +3986,13 @@ packages:
resolution: {integrity: sha512-ejiWi7RJfUp71K5IRpfrhoiZcvxhn1K+YH5mWdwwCT7jeQyE+Ok6WdFMpSg4LYy8YsVw6XHr5I+g23OCebc24w==}
dev: true
/@nuxt/vite-builder-edge/3.0.0-rc.4-27605536.8c2c80e_vue@3.2.37:
resolution: {integrity: sha512-iQkb9iz+X5QdSpQwawaf2vCXFSvY+VwNXxh5irAiJ91eWh4hwq1QlkB4F4aXEL20oOy72tYP/Pyd76j/ZDfZGQ==}
/@nuxt/vite-builder-edge/3.0.0-rc.4-27611167.a41644e_vue@3.2.37:
resolution: {integrity: sha512-h5omNouNcLIL0D/Q41JQYMimiB17oxmV9ZGHKXjj2VcYTzNyWsSlvS6h5AWu19m1N4Ctp5uS5amCGA26F/2E5A==}
engines: {node: ^14.16.0 || ^16.11.0 || ^17.0.0 || ^18.0.0}
peerDependencies:
vue: ^3.2.37
dependencies:
'@nuxt/kit': /@nuxt/kit-edge/3.0.0-rc.4-27605536.8c2c80e_5cbeqmovjazlwrjcfaylsl5bey
'@nuxt/kit': /@nuxt/kit-edge/3.0.0-rc.4-27611167.a41644e_5cbeqmovjazlwrjcfaylsl5bey
'@rollup/plugin-replace': 4.0.0_rollup@2.75.7
'@vitejs/plugin-vue': 2.3.3_vite@2.9.12+vue@3.2.37
'@vitejs/plugin-vue-jsx': 1.3.10
@ -16826,25 +16826,25 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
/nuxi-edge/3.0.0-rc.4-27605536.8c2c80e:
resolution: {integrity: sha512-z2+uUI5DeG3/OT+MN14kLIty+XMBYe2vj+33pMBC7dtv04akN7eYD9LEclqg5BdDc+SgOMZ+g3KKEvl9mQdT1Q==}
/nuxi-edge/3.0.0-rc.4-27611167.a41644e:
resolution: {integrity: sha512-Lz+7WKTj3ES9T5EKobt2DZyuVqUYWpmnMqnGfOXWJbV+9aMTc4jhZOfp4Z57cDEOGHr7C06OBjHoWAHQY9D7Xw==}
engines: {node: ^14.16.0 || ^16.11.0 || ^17.0.0 || ^18.0.0}
hasBin: true
optionalDependencies:
fsevents: 2.3.2
dev: true
/nuxt3/3.0.0-rc.4-27605536.8c2c80e:
resolution: {integrity: sha512-/flVMCyPraeozADNbPsOlJfjOUGlUXdPO4eycCyw6uQHz/RQBDfKDS2RGHa6g51Ef5h7bJWhnNc/o1zCgWzedQ==}
/nuxt3/3.0.0-rc.4-27611167.a41644e:
resolution: {integrity: sha512-+gVgU9IUxgvQws4iyoMbBaSplNVa7nwURL18IZybvhubvNepgXzxmcnfWfwjExgSi0tNR5aZ+VICfXpGrPYBNA==}
engines: {node: ^14.16.0 || ^16.11.0 || ^17.0.0 || ^18.0.0}
hasBin: true
dependencies:
'@nuxt/devalue': 2.0.0
'@nuxt/kit': /@nuxt/kit-edge/3.0.0-rc.4-27605536.8c2c80e
'@nuxt/schema': /@nuxt/schema-edge/3.0.0-rc.4-27605536.8c2c80e
'@nuxt/kit': /@nuxt/kit-edge/3.0.0-rc.4-27611167.a41644e
'@nuxt/schema': /@nuxt/schema-edge/3.0.0-rc.4-27611167.a41644e
'@nuxt/telemetry': 2.1.3
'@nuxt/ui-templates': 0.1.1
'@nuxt/vite-builder': /@nuxt/vite-builder-edge/3.0.0-rc.4-27605536.8c2c80e_vue@3.2.37
'@nuxt/vite-builder': /@nuxt/vite-builder-edge/3.0.0-rc.4-27611167.a41644e_vue@3.2.37
'@vue/reactivity': 3.2.37
'@vue/shared': 3.2.37
'@vueuse/head': 0.7.6_vue@3.2.37
@ -16862,7 +16862,7 @@ packages:
magic-string: 0.26.2
mlly: 0.5.3
nitropack: 0.4.8
nuxi: /nuxi-edge/3.0.0-rc.4-27605536.8c2c80e
nuxi: /nuxi-edge/3.0.0-rc.4-27611167.a41644e
ohash: 0.1.0
ohmyfetch: 0.4.18
pathe: 0.3.0
@ -16892,17 +16892,17 @@ packages:
- webpack
dev: true
/nuxt3/3.0.0-rc.4-27605536.8c2c80e_5cbeqmovjazlwrjcfaylsl5bey:
resolution: {integrity: sha512-/flVMCyPraeozADNbPsOlJfjOUGlUXdPO4eycCyw6uQHz/RQBDfKDS2RGHa6g51Ef5h7bJWhnNc/o1zCgWzedQ==}
/nuxt3/3.0.0-rc.4-27611167.a41644e_5cbeqmovjazlwrjcfaylsl5bey:
resolution: {integrity: sha512-+gVgU9IUxgvQws4iyoMbBaSplNVa7nwURL18IZybvhubvNepgXzxmcnfWfwjExgSi0tNR5aZ+VICfXpGrPYBNA==}
engines: {node: ^14.16.0 || ^16.11.0 || ^17.0.0 || ^18.0.0}
hasBin: true
dependencies:
'@nuxt/devalue': 2.0.0
'@nuxt/kit': /@nuxt/kit-edge/3.0.0-rc.4-27605536.8c2c80e_5cbeqmovjazlwrjcfaylsl5bey
'@nuxt/schema': /@nuxt/schema-edge/3.0.0-rc.4-27605536.8c2c80e_5cbeqmovjazlwrjcfaylsl5bey
'@nuxt/kit': /@nuxt/kit-edge/3.0.0-rc.4-27611167.a41644e_5cbeqmovjazlwrjcfaylsl5bey
'@nuxt/schema': /@nuxt/schema-edge/3.0.0-rc.4-27611167.a41644e_5cbeqmovjazlwrjcfaylsl5bey
'@nuxt/telemetry': 2.1.3_5cbeqmovjazlwrjcfaylsl5bey
'@nuxt/ui-templates': 0.1.1
'@nuxt/vite-builder': /@nuxt/vite-builder-edge/3.0.0-rc.4-27605536.8c2c80e_vue@3.2.37
'@nuxt/vite-builder': /@nuxt/vite-builder-edge/3.0.0-rc.4-27611167.a41644e_vue@3.2.37
'@vue/reactivity': 3.2.37
'@vue/shared': 3.2.37
'@vueuse/head': 0.7.6_vue@3.2.37
@ -16920,7 +16920,7 @@ packages:
magic-string: 0.26.2
mlly: 0.5.3
nitropack: 0.4.8_vite@2.9.12
nuxi: /nuxi-edge/3.0.0-rc.4-27605536.8c2c80e
nuxi: /nuxi-edge/3.0.0-rc.4-27611167.a41644e
ohash: 0.1.0
ohmyfetch: 0.4.18
pathe: 0.3.0
@ -20899,7 +20899,7 @@ packages:
bs-logger: 0.2.6
esbuild: 0.14.48
fast-json-stable-stringify: 2.1.0
jest: 28.0.0-alpha.11_jbmz3vlfopghb5mdasddsdxfzq
jest: 28.0.0-alpha.11_@types+node@17.0.45
jest-util: 28.1.1
json5: 2.2.1
lodash.memoize: 4.1.2
@ -20934,7 +20934,7 @@ packages:
bs-logger: 0.2.6
esbuild: 0.14.48
fast-json-stable-stringify: 2.1.0
jest: 28.0.0-alpha.11_@types+node@17.0.45
jest: 28.0.0-alpha.11_jbmz3vlfopghb5mdasddsdxfzq
jest-util: 28.1.1
json5: 2.2.1
lodash.memoize: 4.1.2