mirror of
https://github.com/iconify/iconify.git
synced 2025-01-06 07:20:40 +00:00
Parse icons tree only once when parsing icon set
This commit is contained in:
parent
89a2def126
commit
7b4409665a
@ -4,6 +4,57 @@ import type { IconifyIcon, FullIconifyIcon } from '../icon/defaults';
|
||||
import { mergeIconData } from '../icon/merge';
|
||||
import { getIconsTree } from './tree';
|
||||
|
||||
/**
|
||||
* Get icon data, using prepared aliases tree
|
||||
*/
|
||||
export function internalGetIconData(
|
||||
data: IconifyJSON,
|
||||
name: string,
|
||||
tree: string[],
|
||||
full: true
|
||||
): FullIconifyIcon;
|
||||
export function internalGetIconData(
|
||||
data: IconifyJSON,
|
||||
name: string,
|
||||
tree: string[],
|
||||
full: false
|
||||
): IconifyIcon;
|
||||
export function internalGetIconData(
|
||||
data: IconifyJSON,
|
||||
name: string,
|
||||
tree: string[],
|
||||
full: boolean
|
||||
): FullIconifyIcon | IconifyIcon {
|
||||
const icons = data.icons;
|
||||
const aliases = data.aliases || {};
|
||||
|
||||
let currentProps = {} as IconifyIcon;
|
||||
|
||||
// Parse parent item
|
||||
function parse(name: string) {
|
||||
currentProps = mergeIconData(
|
||||
icons[name] || aliases[name],
|
||||
currentProps,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
parse(name);
|
||||
tree.forEach(parse);
|
||||
|
||||
// Add default values
|
||||
currentProps = mergeIconData(
|
||||
data,
|
||||
currentProps,
|
||||
false
|
||||
) as unknown as IconifyIcon;
|
||||
|
||||
// Return icon
|
||||
return full
|
||||
? Object.assign({}, defaultIconProps, currentProps)
|
||||
: currentProps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data for icon
|
||||
*/
|
||||
@ -22,43 +73,12 @@ export function getIconData(
|
||||
name: string,
|
||||
full = false
|
||||
): FullIconifyIcon | IconifyIcon | null {
|
||||
const icons = data.icons;
|
||||
const aliases = data.aliases || {};
|
||||
|
||||
let currentProps = {} as IconifyIcon;
|
||||
|
||||
// Parse parent item
|
||||
function parse(name: string) {
|
||||
currentProps = mergeIconData(
|
||||
icons[name] || aliases[name],
|
||||
currentProps,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
const icon = icons[name];
|
||||
if (icon) {
|
||||
if (data.icons[name]) {
|
||||
// Parse only icon
|
||||
parse(name);
|
||||
} else {
|
||||
// Resolve tree
|
||||
const tree = getIconsTree(data, [name])[name];
|
||||
if (!tree) {
|
||||
return null;
|
||||
}
|
||||
parse(name);
|
||||
tree.forEach(parse);
|
||||
return internalGetIconData(data, name, [], full as true);
|
||||
}
|
||||
|
||||
// Add default values
|
||||
currentProps = mergeIconData(
|
||||
data,
|
||||
currentProps,
|
||||
false
|
||||
) as unknown as IconifyIcon;
|
||||
|
||||
// Return icon
|
||||
return full
|
||||
? Object.assign({}, defaultIconProps, currentProps)
|
||||
: currentProps;
|
||||
// Resolve tree
|
||||
const tree = getIconsTree(data, [name])[name];
|
||||
return tree ? internalGetIconData(data, name, tree, full as true) : null;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import type { IconifyJSON } from '@iconify/types';
|
||||
import type { FullIconifyIcon } from '../icon/defaults';
|
||||
import { getIconData } from './get-icon';
|
||||
import { internalGetIconData } from './get-icon';
|
||||
import { getIconsTree } from './tree';
|
||||
|
||||
/**
|
||||
* Callback to call for each icon.
|
||||
@ -37,29 +38,15 @@ export function parseIconSet(
|
||||
});
|
||||
}
|
||||
|
||||
// Get icons
|
||||
const icons = data.icons;
|
||||
for (const name in icons) {
|
||||
const iconData = getIconData(data, name, true);
|
||||
if (iconData) {
|
||||
// Call callback
|
||||
callback(name, iconData);
|
||||
// Get tree
|
||||
const tree = getIconsTree(data);
|
||||
for (const name in tree) {
|
||||
const item = tree[name];
|
||||
if (item) {
|
||||
callback(name, internalGetIconData(data, name, item, true));
|
||||
names.push(name);
|
||||
}
|
||||
}
|
||||
|
||||
// Get aliases
|
||||
const aliases = data.aliases;
|
||||
if (aliases) {
|
||||
for (const name in aliases) {
|
||||
const iconData = icons[name] ? null : getIconData(data, name, true);
|
||||
if (iconData) {
|
||||
// Call callback
|
||||
callback(name, iconData);
|
||||
names.push(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
@ -66,8 +66,8 @@ describe('Testing parsing icon set', () => {
|
||||
|
||||
test('Aliases', () => {
|
||||
// Names list
|
||||
const names: string[] = ['icon1', 'icon2', 'alias1', 'alias2'];
|
||||
const namesCopy = names.slice(0);
|
||||
let names: string[] = ['icon1', 'icon2', 'alias1', 'alias2'];
|
||||
const expectedNames = names.slice(0).sort((a, b) => a.localeCompare(b));
|
||||
|
||||
// Resolved data
|
||||
const expected: Record<string, FullIconifyIcon | null> = {
|
||||
@ -114,56 +114,57 @@ describe('Testing parsing icon set', () => {
|
||||
};
|
||||
|
||||
// Do stuff
|
||||
expect(
|
||||
parseIconSet(
|
||||
{
|
||||
prefix: 'foo',
|
||||
icons: {
|
||||
icon1: {
|
||||
body: '<path d="icon1" />',
|
||||
width: 20,
|
||||
},
|
||||
icon2: {
|
||||
body: '<path d="icon2" />',
|
||||
width: 24,
|
||||
vFlip: true,
|
||||
rotate: 3,
|
||||
},
|
||||
const parsedNames = parseIconSet(
|
||||
{
|
||||
prefix: 'foo',
|
||||
icons: {
|
||||
icon1: {
|
||||
body: '<path d="icon1" />',
|
||||
width: 20,
|
||||
},
|
||||
aliases: {
|
||||
alias1: {
|
||||
parent: 'icon1',
|
||||
},
|
||||
alias2: {
|
||||
parent: 'icon2',
|
||||
hFlip: true,
|
||||
width: 20,
|
||||
},
|
||||
// invalid alias
|
||||
icon2: {
|
||||
parent: 'icon1',
|
||||
},
|
||||
icon2: {
|
||||
body: '<path d="icon2" />',
|
||||
width: 24,
|
||||
vFlip: true,
|
||||
rotate: 3,
|
||||
},
|
||||
height: 24,
|
||||
},
|
||||
(name, data) => {
|
||||
// Make sure name matches
|
||||
expect(names.length).toBeGreaterThanOrEqual(1);
|
||||
expect(name).toBe(names.shift());
|
||||
aliases: {
|
||||
alias1: {
|
||||
parent: 'icon1',
|
||||
},
|
||||
alias2: {
|
||||
parent: 'icon2',
|
||||
hFlip: true,
|
||||
width: 20,
|
||||
},
|
||||
// invalid alias
|
||||
icon2: {
|
||||
parent: 'icon1',
|
||||
},
|
||||
},
|
||||
height: 24,
|
||||
},
|
||||
(name, data) => {
|
||||
// Make sure name exists in array of pending names
|
||||
const index = names.indexOf(name);
|
||||
expect(index).not.toBe(-1);
|
||||
names = names.slice(0, index).concat(names.slice(index + 1));
|
||||
|
||||
// Check icon data
|
||||
expect(data).toEqual(expected[name]);
|
||||
}
|
||||
)
|
||||
).toEqual(namesCopy);
|
||||
// Check icon data
|
||||
expect(data).toEqual(expected[name]);
|
||||
}
|
||||
);
|
||||
|
||||
// All names should have been parsed
|
||||
// All names should have been parsed, not necessary in expected order
|
||||
expect(names).toEqual([]);
|
||||
parsedNames.sort((a, b) => a.localeCompare(b));
|
||||
expect(parsedNames).toEqual(expectedNames);
|
||||
});
|
||||
|
||||
test('Nested aliases', () => {
|
||||
// Names list
|
||||
const names: string[] = [
|
||||
let names: string[] = [
|
||||
'icon1',
|
||||
'icon2',
|
||||
'alias2a',
|
||||
@ -175,7 +176,7 @@ describe('Testing parsing icon set', () => {
|
||||
'alias2z6',
|
||||
'alias2z7',
|
||||
];
|
||||
const namesCopy = names.slice(0);
|
||||
const expectedNames = names.slice(0).sort((a, b) => a.localeCompare(b));
|
||||
|
||||
// Resolved data
|
||||
const expected: Record<string, FullIconifyIcon | null> = {
|
||||
@ -290,82 +291,83 @@ describe('Testing parsing icon set', () => {
|
||||
};
|
||||
|
||||
// Do stuff
|
||||
expect(
|
||||
parseIconSet(
|
||||
{
|
||||
prefix: 'foo',
|
||||
icons: {
|
||||
icon1: {
|
||||
body: '<path d="icon1" />',
|
||||
width: 20,
|
||||
height: 20,
|
||||
},
|
||||
icon2: {
|
||||
body: '<path d="icon2" />',
|
||||
width: 24,
|
||||
rotate: 1,
|
||||
hFlip: true,
|
||||
},
|
||||
const parsedNames = parseIconSet(
|
||||
{
|
||||
prefix: 'foo',
|
||||
icons: {
|
||||
icon1: {
|
||||
body: '<path d="icon1" />',
|
||||
width: 20,
|
||||
height: 20,
|
||||
},
|
||||
aliases: {
|
||||
alias2a: {
|
||||
// Alias before parent
|
||||
parent: 'alias2f',
|
||||
width: 20,
|
||||
height: 20,
|
||||
},
|
||||
alias2f: {
|
||||
parent: 'icon2',
|
||||
width: 22,
|
||||
rotate: 1,
|
||||
hFlip: true,
|
||||
vFlip: true,
|
||||
},
|
||||
alias2z: {
|
||||
// Alias after parent
|
||||
parent: 'alias2f',
|
||||
width: 21,
|
||||
rotate: 3,
|
||||
},
|
||||
alias2z3: {
|
||||
// 3 parents: alias2z, alias2f, icon2
|
||||
parent: 'alias2z',
|
||||
},
|
||||
alias2z4: {
|
||||
// 4 parents: alias2z3, alias2z, alias2f, icon2
|
||||
parent: 'alias2z3',
|
||||
},
|
||||
alias2z5: {
|
||||
// 5 parents: alias2z4, alias2z3, alias2z, alias2f, icon2
|
||||
parent: 'alias2z4',
|
||||
},
|
||||
alias2z6: {
|
||||
// 6 parents: alias2z5, alias2z4, alias2z3, alias2z, alias2f, icon2
|
||||
parent: 'alias2z5',
|
||||
},
|
||||
alias2z7: {
|
||||
// 7 parents: alias2z6, alias2z5, alias2z4, alias2z3, alias2z, alias2f, icon2
|
||||
parent: 'alias2z6',
|
||||
},
|
||||
alias3: {
|
||||
// invalid parent
|
||||
parent: 'icon3',
|
||||
},
|
||||
icon2: {
|
||||
body: '<path d="icon2" />',
|
||||
width: 24,
|
||||
rotate: 1,
|
||||
hFlip: true,
|
||||
},
|
||||
height: 24,
|
||||
},
|
||||
(name, data) => {
|
||||
// Make sure name matches
|
||||
expect(names.length).toBeGreaterThanOrEqual(1);
|
||||
expect(name).toBe(names.shift());
|
||||
aliases: {
|
||||
alias2a: {
|
||||
// Alias before parent
|
||||
parent: 'alias2f',
|
||||
width: 20,
|
||||
height: 20,
|
||||
},
|
||||
alias2f: {
|
||||
parent: 'icon2',
|
||||
width: 22,
|
||||
rotate: 1,
|
||||
hFlip: true,
|
||||
vFlip: true,
|
||||
},
|
||||
alias2z: {
|
||||
// Alias after parent
|
||||
parent: 'alias2f',
|
||||
width: 21,
|
||||
rotate: 3,
|
||||
},
|
||||
alias2z3: {
|
||||
// 3 parents: alias2z, alias2f, icon2
|
||||
parent: 'alias2z',
|
||||
},
|
||||
alias2z4: {
|
||||
// 4 parents: alias2z3, alias2z, alias2f, icon2
|
||||
parent: 'alias2z3',
|
||||
},
|
||||
alias2z5: {
|
||||
// 5 parents: alias2z4, alias2z3, alias2z, alias2f, icon2
|
||||
parent: 'alias2z4',
|
||||
},
|
||||
alias2z6: {
|
||||
// 6 parents: alias2z5, alias2z4, alias2z3, alias2z, alias2f, icon2
|
||||
parent: 'alias2z5',
|
||||
},
|
||||
alias2z7: {
|
||||
// 7 parents: alias2z6, alias2z5, alias2z4, alias2z3, alias2z, alias2f, icon2
|
||||
parent: 'alias2z6',
|
||||
},
|
||||
alias3: {
|
||||
// invalid parent
|
||||
parent: 'icon3',
|
||||
},
|
||||
},
|
||||
height: 24,
|
||||
},
|
||||
(name, data) => {
|
||||
// Make sure name exists in array of pending names
|
||||
const index = names.indexOf(name);
|
||||
expect(index).not.toBe(-1);
|
||||
names = names.slice(0, index).concat(names.slice(index + 1));
|
||||
|
||||
// Check icon data
|
||||
expect(data).toEqual(expected[name]);
|
||||
}
|
||||
)
|
||||
).toEqual(namesCopy);
|
||||
// Check icon data
|
||||
expect(data).toEqual(expected[name]);
|
||||
}
|
||||
);
|
||||
|
||||
// All names should have been parsed
|
||||
// All names should have been parsed, not necessary in expected order
|
||||
expect(names).toEqual([]);
|
||||
parsedNames.sort((a, b) => a.localeCompare(b));
|
||||
expect(parsedNames).toEqual(expectedNames);
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user