mirror of
https://github.com/iconify/iconify.git
synced 2025-01-06 07:20:40 +00:00
Replace unnecessary complex icon set validation function with basic function
This commit is contained in:
parent
0f21f877b8
commit
19e951cdb7
@ -1,6 +1,7 @@
|
||||
import type { IconifyJSON, IconifyIcon } from '@iconify/types';
|
||||
import type { FullIconifyIcon } from '@iconify/utils/lib/icon';
|
||||
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';
|
||||
import { stringToIcon, validateIcon } from '@iconify/utils/lib/icon/name';
|
||||
import {
|
||||
@ -108,21 +109,17 @@ export function addCollection(data: IconifyJSON, provider?: string): boolean {
|
||||
) {
|
||||
// Simple names: add icons one by one
|
||||
let added = false;
|
||||
parseIconSet(
|
||||
data,
|
||||
(name, icon) => {
|
||||
|
||||
if (quicklyValidateIconSet(data)) {
|
||||
// Reset prefix
|
||||
data.prefix = '';
|
||||
|
||||
parseIconSet(data, (name, icon) => {
|
||||
if (icon && addIcon(name, icon)) {
|
||||
added = true;
|
||||
}
|
||||
},
|
||||
{
|
||||
// Validate icon set and set prefix to empty
|
||||
validate: {
|
||||
fix: true,
|
||||
prefix: '',
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ import type { IconifyJSON, IconifyIcon } from '@iconify/types';
|
||||
import type { FullIconifyIcon } from '@iconify/utils/lib/icon';
|
||||
import { fullIcon } from '@iconify/utils/lib/icon';
|
||||
import { parseIconSet } from '@iconify/utils/lib/icon-set/parse';
|
||||
import { quicklyValidateIconSet } from '@iconify/utils/lib/icon-set/validate-basic';
|
||||
|
||||
/**
|
||||
* List of icons
|
||||
@ -99,6 +100,10 @@ export function getStorage(provider: string, prefix: string): IconStorage {
|
||||
* Returns array of added icons
|
||||
*/
|
||||
export function addIconSet(storage: IconStorage, data: IconifyJSON): string[] {
|
||||
if (!quicklyValidateIconSet(data)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const t = Date.now();
|
||||
return parseIconSet(data, (name, icon: FullIconifyIcon | null) => {
|
||||
if (icon) {
|
||||
|
@ -7,6 +7,7 @@ import type {
|
||||
} from '@iconify/utils/lib/customisations';
|
||||
import { fullIcon } from '@iconify/utils/lib/icon';
|
||||
import { parseIconSet } from '@iconify/utils/lib/icon-set/parse';
|
||||
import { quicklyValidateIconSet } from '@iconify/utils/lib/icon-set/validate-basic';
|
||||
import type {
|
||||
IconifyIconCustomisations,
|
||||
IconifyIconProps,
|
||||
@ -116,19 +117,11 @@ export function addCollection(
|
||||
: prefix !== false && typeof data.prefix === 'string'
|
||||
? data.prefix + ':'
|
||||
: '';
|
||||
parseIconSet(
|
||||
data,
|
||||
(name, icon) => {
|
||||
|
||||
quicklyValidateIconSet(data) &&
|
||||
parseIconSet(data, (name, icon) => {
|
||||
if (icon) {
|
||||
storage[iconPrefix + name] = icon;
|
||||
}
|
||||
},
|
||||
{
|
||||
// Allow empty prefix
|
||||
validate: {
|
||||
fix: true,
|
||||
prefix: iconPrefix,
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import type { IconifyIcon, IconifyJSON } from '@iconify/types';
|
||||
import { fullIcon } from '@iconify/utils/lib/icon';
|
||||
import { parseIconSet } from '@iconify/utils/lib/icon-set/parse';
|
||||
import { quicklyValidateIconSet } from '@iconify/utils/lib/icon-set/validate-basic';
|
||||
import { render } from './render';
|
||||
import type { RenderResult } from './render';
|
||||
import type { IconProps } from './props';
|
||||
@ -60,19 +61,10 @@ export function addCollection(
|
||||
: prefix !== false && typeof data.prefix === 'string'
|
||||
? data.prefix + ':'
|
||||
: '';
|
||||
parseIconSet(
|
||||
data,
|
||||
(name, icon) => {
|
||||
quicklyValidateIconSet(data) &&
|
||||
parseIconSet(data, (name, icon) => {
|
||||
if (icon) {
|
||||
storage[iconPrefix + name] = icon;
|
||||
}
|
||||
},
|
||||
{
|
||||
// Allow empty prefix
|
||||
validate: {
|
||||
fix: true,
|
||||
prefix: iconPrefix,
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -102,6 +102,10 @@
|
||||
"require": "./lib/icon-set/validate.cjs",
|
||||
"import": "./lib/icon-set/validate.mjs"
|
||||
},
|
||||
"./lib/icon-set/validate-basic": {
|
||||
"require": "./lib/icon-set/validate-basic.cjs",
|
||||
"import": "./lib/icon-set/validate-basic.mjs"
|
||||
},
|
||||
"./lib/icon": {
|
||||
"require": "./lib/icon/index.cjs",
|
||||
"import": "./lib/icon/index.mjs"
|
||||
|
@ -1,7 +1,6 @@
|
||||
import type { IconifyAlias, IconifyJSON } from '@iconify/types';
|
||||
import { FullIconifyIcon, iconDefaults } from '../icon';
|
||||
import { getIconData } from './get-icon';
|
||||
import { IconSetValidationOptions, validateIconSet } from './validate';
|
||||
|
||||
/**
|
||||
* Which aliases to parse:
|
||||
@ -35,7 +34,6 @@ export function isVariation(item: IconifyAlias): boolean {
|
||||
}
|
||||
|
||||
export interface ParseIconSetOptions {
|
||||
validate?: boolean | IconSetValidationOptions;
|
||||
aliases?: ParseIconSetAliases;
|
||||
}
|
||||
|
||||
@ -59,20 +57,6 @@ export function parseIconSet(
|
||||
return names;
|
||||
}
|
||||
|
||||
// Validate icon set
|
||||
const validate = options.validate;
|
||||
if (validate !== false) {
|
||||
// Validate icon set
|
||||
try {
|
||||
validateIconSet(
|
||||
data,
|
||||
typeof validate === 'object' ? validate : { fix: true }
|
||||
);
|
||||
} catch (err) {
|
||||
return names;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for missing icons list returned by API
|
||||
if (data.not_found instanceof Array) {
|
||||
data.not_found.forEach((name) => {
|
||||
|
99
packages/utils/src/icon-set/validate-basic.ts
Normal file
99
packages/utils/src/icon-set/validate-basic.ts
Normal file
@ -0,0 +1,99 @@
|
||||
import type { IconifyJSON } from '@iconify/types';
|
||||
import { iconDefaults, matchName } from '../icon';
|
||||
|
||||
/**
|
||||
* Optional properties
|
||||
*/
|
||||
const optionalProperties = {
|
||||
provider: 'string',
|
||||
aliases: 'object',
|
||||
not_found: 'object',
|
||||
} as Record<string, string>;
|
||||
|
||||
for (const prop in iconDefaults) {
|
||||
optionalProperties[prop] =
|
||||
typeof iconDefaults[prop as keyof typeof iconDefaults];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate icon set, return it as IconifyJSON on success, null on failure
|
||||
*
|
||||
* Unlike validateIconSet(), this function is very basic.
|
||||
* It does not throw exceptions, it does not check metadata, it does not fix stuff.
|
||||
*/
|
||||
export function quicklyValidateIconSet(obj: unknown): IconifyJSON | null {
|
||||
// Check for object with 'icons' nested object
|
||||
if (typeof obj !== 'object' || obj === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Convert type
|
||||
const data = obj as IconifyJSON;
|
||||
|
||||
// Check for prefix and icons
|
||||
if (
|
||||
typeof data.prefix !== 'string' ||
|
||||
!(obj as Record<string, unknown>).icons ||
|
||||
typeof (obj as Record<string, unknown>).icons !== 'object'
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check for optional properties
|
||||
for (const prop in optionalProperties) {
|
||||
if (
|
||||
(obj as Record<string, unknown>)[prop] !== void 0 &&
|
||||
typeof (obj as Record<string, unknown>)[prop] !==
|
||||
optionalProperties[prop]
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Check all icons
|
||||
const icons = data.icons;
|
||||
for (const name in icons) {
|
||||
const icon = icons[name];
|
||||
if (!name.match(matchName) || typeof icon.body !== 'string') {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (const prop in iconDefaults) {
|
||||
if (
|
||||
icon[prop as keyof typeof icon] !== void 0 &&
|
||||
typeof icon[prop as keyof typeof icon] !==
|
||||
typeof iconDefaults[prop as keyof typeof iconDefaults]
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check all aliases
|
||||
const aliases = data.aliases;
|
||||
if (aliases) {
|
||||
for (const name in aliases) {
|
||||
const icon = aliases[name];
|
||||
const parent = icon.parent;
|
||||
if (
|
||||
!name.match(matchName) ||
|
||||
typeof parent !== 'string' ||
|
||||
(!icons[parent] && !aliases[parent])
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (const prop in iconDefaults) {
|
||||
if (
|
||||
icon[prop as keyof typeof icon] !== void 0 &&
|
||||
typeof icon[prop as keyof typeof icon] !==
|
||||
typeof iconDefaults[prop as keyof typeof iconDefaults]
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
@ -27,6 +27,7 @@ export {
|
||||
// Icon set functions
|
||||
export { parseIconSet, isVariation } from './icon-set/parse';
|
||||
export { validateIconSet } from './icon-set/validate';
|
||||
export { quicklyValidateIconSet } from './icon-set/validate-basic';
|
||||
export { expandIconSet } from './icon-set/expand';
|
||||
export { minifyIconSet } from './icon-set/minify';
|
||||
export { getIcons } from './icon-set/get-icons';
|
||||
|
152
packages/utils/tests/validate-basic-test.ts
Normal file
152
packages/utils/tests/validate-basic-test.ts
Normal file
@ -0,0 +1,152 @@
|
||||
import { quicklyValidateIconSet } from '../lib/icon-set/validate-basic';
|
||||
|
||||
describe('Testing validation', () => {
|
||||
test('Not object', () => {
|
||||
expect(quicklyValidateIconSet(void 0)).toBe(null);
|
||||
expect(quicklyValidateIconSet({})).toBe(null);
|
||||
expect(quicklyValidateIconSet(null)).toBe(null);
|
||||
expect(quicklyValidateIconSet([])).toBe(null);
|
||||
});
|
||||
|
||||
test('Valid sets', () => {
|
||||
expect(
|
||||
quicklyValidateIconSet({
|
||||
prefix: 'foo',
|
||||
icons: {
|
||||
bar: {
|
||||
body: '<g />',
|
||||
},
|
||||
},
|
||||
width: 24,
|
||||
height: 24,
|
||||
})
|
||||
).toEqual({
|
||||
prefix: 'foo',
|
||||
icons: {
|
||||
bar: {
|
||||
body: '<g />',
|
||||
},
|
||||
},
|
||||
width: 24,
|
||||
height: 24,
|
||||
});
|
||||
|
||||
expect(
|
||||
quicklyValidateIconSet({
|
||||
prefix: 'foo',
|
||||
icons: {
|
||||
bar: {
|
||||
body: '<g />',
|
||||
width: 32,
|
||||
height: 32,
|
||||
rotate: 0,
|
||||
hFlip: false,
|
||||
vFlip: true,
|
||||
// Legacy property
|
||||
verticalAlign: -0.14,
|
||||
},
|
||||
},
|
||||
aliases: {
|
||||
baz: {
|
||||
parent: 'bar',
|
||||
hFlip: true,
|
||||
},
|
||||
},
|
||||
width: 24,
|
||||
height: 24,
|
||||
})
|
||||
).toEqual({
|
||||
prefix: 'foo',
|
||||
icons: {
|
||||
bar: {
|
||||
body: '<g />',
|
||||
width: 32,
|
||||
height: 32,
|
||||
rotate: 0,
|
||||
hFlip: false,
|
||||
vFlip: true,
|
||||
verticalAlign: -0.14,
|
||||
},
|
||||
},
|
||||
aliases: {
|
||||
baz: {
|
||||
parent: 'bar',
|
||||
hFlip: true,
|
||||
},
|
||||
},
|
||||
width: 24,
|
||||
height: 24,
|
||||
});
|
||||
|
||||
// Empty is allowed
|
||||
expect(
|
||||
quicklyValidateIconSet({
|
||||
prefix: 'foo',
|
||||
icons: {},
|
||||
})
|
||||
).toEqual({
|
||||
prefix: 'foo',
|
||||
icons: {},
|
||||
});
|
||||
});
|
||||
|
||||
test('Missing required properties', () => {
|
||||
expect(
|
||||
quicklyValidateIconSet({
|
||||
prefix: 'foo',
|
||||
})
|
||||
).toBe(null);
|
||||
|
||||
expect(
|
||||
quicklyValidateIconSet({
|
||||
icons: {},
|
||||
})
|
||||
).toBe(null);
|
||||
});
|
||||
|
||||
test('Invalid optional properties', () => {
|
||||
expect(
|
||||
quicklyValidateIconSet({
|
||||
prefix: 'foo',
|
||||
icons: {
|
||||
icon1: {
|
||||
body: '<path d="icon1" />',
|
||||
},
|
||||
},
|
||||
height: 24,
|
||||
// Object
|
||||
rotate: {
|
||||
foo: 1,
|
||||
},
|
||||
})
|
||||
).toBe(null);
|
||||
|
||||
expect(
|
||||
quicklyValidateIconSet({
|
||||
prefix: 'foo',
|
||||
icons: {
|
||||
icon1: {
|
||||
body: '<path d="icon1" />',
|
||||
},
|
||||
},
|
||||
height: 24,
|
||||
// Object
|
||||
hFlip: null,
|
||||
})
|
||||
).toBe(null);
|
||||
|
||||
expect(
|
||||
quicklyValidateIconSet({
|
||||
prefix: 'foo',
|
||||
icons: {
|
||||
icon1: {
|
||||
body: '<path d="icon1" />',
|
||||
},
|
||||
},
|
||||
height: 24,
|
||||
// String
|
||||
width: '32',
|
||||
})
|
||||
).toBe(null);
|
||||
});
|
||||
});
|
@ -16,6 +16,7 @@ import type {
|
||||
} from '@iconify/utils/lib/customisations';
|
||||
import { fullIcon } from '@iconify/utils/lib/icon';
|
||||
import { parseIconSet } from '@iconify/utils/lib/icon-set/parse';
|
||||
import { quicklyValidateIconSet } from '@iconify/utils/lib/icon-set/validate-basic';
|
||||
import type {
|
||||
IconifyIconCustomisations,
|
||||
IconifyIconProps,
|
||||
@ -70,21 +71,12 @@ export function addCollection(
|
||||
: prefix !== false && typeof data.prefix === 'string'
|
||||
? data.prefix + ':'
|
||||
: '';
|
||||
parseIconSet(
|
||||
data,
|
||||
(name, icon) => {
|
||||
quicklyValidateIconSet(data) &&
|
||||
parseIconSet(data, (name, icon) => {
|
||||
if (icon) {
|
||||
storage[iconPrefix + name] = icon;
|
||||
}
|
||||
},
|
||||
{
|
||||
// Allow empty prefix
|
||||
validate: {
|
||||
fix: true,
|
||||
prefix: iconPrefix,
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -9,6 +9,7 @@ import type {
|
||||
} from '@iconify/utils/lib/customisations';
|
||||
import { fullIcon } from '@iconify/utils/lib/icon';
|
||||
import { parseIconSet } from '@iconify/utils/lib/icon-set/parse';
|
||||
import { quicklyValidateIconSet } from '@iconify/utils/lib/icon-set/validate-basic';
|
||||
import type {
|
||||
IconifyIconCustomisations,
|
||||
IconifyIconProps,
|
||||
@ -63,16 +64,10 @@ export function addCollection(
|
||||
: prefix !== false && typeof data.prefix === 'string'
|
||||
? data.prefix + ':'
|
||||
: '';
|
||||
parseIconSet(data, (name, icon) => {
|
||||
quicklyValidateIconSet(data) && parseIconSet(data, (name, icon) => {
|
||||
if (icon) {
|
||||
storage[iconPrefix + name] = icon;
|
||||
}
|
||||
}, {
|
||||
// Allow empty prefix
|
||||
validate: {
|
||||
fix: true,
|
||||
prefix: iconPrefix,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user