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

chore: move some modules and update types

test: include some tests for `writeOnce`
This commit is contained in:
Joaquín Sánchez Jiménez 2022-02-27 15:03:40 +01:00
parent 062a852a79
commit 6134d1f62b
10 changed files with 123 additions and 54 deletions

View File

@ -152,6 +152,10 @@
"require": "./lib/loader/utils.js",
"import": "./lib/loader/utils.mjs"
},
"./lib/loader/warn": {
"require": "./lib/loader/warn.js",
"import": "./lib/loader/warn.mjs"
},
"./lib/misc/strings": {
"require": "./lib/misc/strings.js",
"import": "./lib/misc/strings.mjs"

View File

@ -55,8 +55,7 @@ export type {
InlineCollection,
} from './loader/types';
export { mergeIconProps } from './loader/utils';
export { isNode, loadIcon } from './loader/loader';
export { FileSystemIconLoader } from './loader/loaders';
export { warnOnce } from './loader/warn';
export { getCustomIcon } from './loader/custom';
export { searchForIcon } from './loader/modern';

View File

@ -1,15 +1,7 @@
import { installPackage } from '@antfu/install-pkg';
import { sleep } from '@antfu/utils';
import { cyan, yellow } from 'kolorist';
const warned = new Set<string>();
export function warnOnce(msg: string): void {
if (!warned.has(msg)) {
warned.add(msg);
console.warn(yellow(`[@iconify-loader] ${msg}`));
}
}
import { cyan } from 'kolorist';
import { warnOnce } from './warn';
let pending: Promise<void> | undefined;
const tasks: Record<string, Promise<void> | undefined> = {};

View File

@ -1,9 +1,9 @@
import { getCustomIcon } from './custom';
import { searchForIcon } from './modern';
import { warnOnce } from './install-pkg';
import { warnOnce } from './warn';
import type { IconifyLoaderOptions } from './types';
export const isNode = typeof process < 'u' && typeof process.stdout < 'u'
export const isNode = typeof process < 'u' && typeof process.stdout < 'u';
export async function loadIcon(
collection: string,
@ -44,24 +44,27 @@ async function loadNodeBuiltinIcon(
collection: string,
icon: string,
options?: IconifyLoaderOptions,
warn = true,
): Promise<string | undefined> {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const { loadCollectionFromFS } = await importFsModule();
const iconSet = await loadCollectionFromFS(collection, options?.autoInstall);
if (iconSet) {
// possible icon names
const ids = [
icon,
icon.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(),
icon.replace(/([a-z])(\d+)/g, '$1-$2'),
];
return await searchForIcon(iconSet, collection, ids, options);
let result: string | undefined;
const loadCollectionFromFS = await importFsModule().then(i => i?.loadCollectionFromFS);
if (loadCollectionFromFS) {
const iconSet = await loadCollectionFromFS(collection, options?.autoInstall);
if (iconSet) {
// possible icon names
const ids = [
icon,
icon.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(),
icon.replace(/([a-z])(\d+)/g, '$1-$2'),
];
result = await searchForIcon(iconSet, collection, ids, options);
}
}
if (warn) {
warnOnce(`failed to load \`@iconify-json/${collection}\`, have you installed it?`);
if (!result && options?.warn) {
warnOnce(`failed to load ${options.warn} icon`);
}
return result;
}

View File

@ -2,7 +2,6 @@ import type { Awaitable } from '@antfu/utils';
import { promises as fs, Stats } from 'fs';
import type { CustomIconLoader } from './types';
import { camelize, pascalize } from '../misc/strings';
import { isNode } from './loader';
/**
* Returns CustomIconLoader for loading icons from a directory
@ -11,26 +10,25 @@ export function FileSystemIconLoader(
dir: string,
transform?: (svg: string) => Awaitable<string>
): CustomIconLoader {
return isNode
? async (name) => {
const paths = [
`${dir}/${name}.svg`,
`${dir}/${camelize(name)}.svg`,
`${dir}/${pascalize(name)}.svg`,
];
let stat: Stats;
for (const path of paths) {
try {
stat = await fs.lstat(path);
} catch (err) {
continue;
}
if (stat.isFile()) {
const svg = await fs.readFile(path, 'utf-8');
return typeof transform === 'function'
? await transform(svg)
: svg;
}
return async (name) => {
const paths = [
`${dir}/${name}.svg`,
`${dir}/${camelize(name)}.svg`,
`${dir}/${pascalize(name)}.svg`,
];
let stat: Stats;
for (const path of paths) {
try {
stat = await fs.lstat(path);
} catch {
continue;
}
} : () => undefined;
if (stat.isFile()) {
const svg = await fs.readFile(path, 'utf-8');
return typeof transform === 'function'
? await transform(svg)
: svg;
}
}
};
}

View File

@ -75,6 +75,11 @@ export type CustomCollections = Record<
* Options to use with the modern loader.
*/
export type IconifyLoaderOptions = {
/**
* Emit warning when missing icons are matched
*/
warn?: string
/**
* Add svg and xlink xml namespace when necessary.
*

View File

@ -0,0 +1,10 @@
import { yellow } from 'kolorist';
const warned = new Set<string>();
export function warnOnce(msg: string): void {
if (!warned.has(msg)) {
warned.add(msg);
console.warn(yellow(`[@iconify-loader] ${msg}`));
}
}

View File

@ -1,4 +1,4 @@
import { FileSystemIconLoader } from '../lib';
import { FileSystemIconLoader } from '../lib/loader/loaders';
describe('Testing FileSystemIconLoader', () => {
test('FileSystemIconLoader', async () => {

View File

@ -1,4 +1,4 @@
import { loadIcon } from '../lib';
import { loadIcon } from '../lib/loader/loader';
describe('Testing loadIcon with @iconify-json/flat-color-icons>', () => {
@ -56,4 +56,61 @@ describe('Testing loadIcon with @iconify-json/flat-color-icons>', () => {
expect(result && result.includes('width="2em"')).toBeTruthy();
expect(result && result.includes('height="2em"')).toBeTruthy();
});
test('loadIcon warn missing icon', async () => {
// Intercept console.warn
let warned = false;
const warn = console.warn;
console.warn = (/*...args*/) => {
// warn.apply(this, args);
warned = true;
};
const result = await loadIcon('flat-color-icons', 'missing1', {
warn: 'flat-color-icons:missing'
});
// Restore console.warn
console.warn = warn;
expect(result).toBeFalsy();
expect(warned).toEqual(true);
});
test('test warnOnce on loadIcon on missing icon', async () => {
// Intercept console.warn
let warned = false;
const warn = console.warn;
console.warn = (/*...args*/) => {
// warn.apply(this, args);
warned = true;
};
// use another name since it is using warnOnce
const result = await loadIcon('flat-color-icons', 'missing1', {
warn: 'flat-color-icons:missing'
});
// Restore console.warn
console.warn = warn;
expect(result).toBeFalsy();
expect(warned).toEqual(false);
});
test('loadIcon doesn\'t warn missing icon', async () => {
// Intercept console.warn
let warned = false;
const warn = console.warn;
console.warn = (/*...args*/) => {
// warn.apply(this, args);
warned = true;
};
// use another name since it is using warnOnce
const result = await loadIcon('flat-color-icons', 'missing2');
// Restore console.warn
console.warn = warn;
expect(result).toBeFalsy();
expect(warned).toEqual(false);
});
});

View File

@ -1,5 +1,6 @@
import { promises as fs } from 'fs';
import { CustomIconLoader, loadIcon } from '../lib';
import type { CustomIconLoader } from '../lib';
import { loadIcon } from '../lib/loader/loader';
const fixturesDir = __dirname + '/fixtures';