From 6134d1f62b70fb49d3cd50336ec56790c5b4e829 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaqu=C3=ADn=20S=C3=A1nchez=20Jim=C3=A9nez?= Date: Sun, 27 Feb 2022 15:03:40 +0100 Subject: [PATCH] chore: move some modules and update types test: include some tests for `writeOnce` --- packages/utils/package.json | 4 ++ packages/utils/src/index.ts | 3 +- packages/utils/src/loader/install-pkg.ts | 12 +--- packages/utils/src/loader/loader.ts | 37 ++++++------ packages/utils/src/loader/loaders.ts | 42 +++++++------ packages/utils/src/loader/types.ts | 5 ++ packages/utils/src/loader/warn.ts | 10 ++++ packages/utils/tests/file-system-icon-test.ts | 2 +- packages/utils/tests/iconify-icon-test.ts | 59 ++++++++++++++++++- packages/utils/tests/load-icon-test.ts | 3 +- 10 files changed, 123 insertions(+), 54 deletions(-) create mode 100644 packages/utils/src/loader/warn.ts diff --git a/packages/utils/package.json b/packages/utils/package.json index 0ced1a3..fb46f80 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -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" diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index badee3e..08428bd 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -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'; diff --git a/packages/utils/src/loader/install-pkg.ts b/packages/utils/src/loader/install-pkg.ts index 282b1e9..8edcfd5 100644 --- a/packages/utils/src/loader/install-pkg.ts +++ b/packages/utils/src/loader/install-pkg.ts @@ -1,15 +1,7 @@ import { installPackage } from '@antfu/install-pkg'; import { sleep } from '@antfu/utils'; -import { cyan, yellow } from 'kolorist'; - -const warned = new Set(); - -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 | undefined; const tasks: Record | undefined> = {}; diff --git a/packages/utils/src/loader/loader.ts b/packages/utils/src/loader/loader.ts index 830a799..10d53a1 100644 --- a/packages/utils/src/loader/loader.ts +++ b/packages/utils/src/loader/loader.ts @@ -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 { - // 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; } diff --git a/packages/utils/src/loader/loaders.ts b/packages/utils/src/loader/loaders.ts index fe2c3f8..21c5e1c 100644 --- a/packages/utils/src/loader/loaders.ts +++ b/packages/utils/src/loader/loaders.ts @@ -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 ): 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; + } + } + }; } diff --git a/packages/utils/src/loader/types.ts b/packages/utils/src/loader/types.ts index ce0018c..7522530 100644 --- a/packages/utils/src/loader/types.ts +++ b/packages/utils/src/loader/types.ts @@ -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. * diff --git a/packages/utils/src/loader/warn.ts b/packages/utils/src/loader/warn.ts new file mode 100644 index 0000000..09a224f --- /dev/null +++ b/packages/utils/src/loader/warn.ts @@ -0,0 +1,10 @@ +import { yellow } from 'kolorist'; + +const warned = new Set(); + +export function warnOnce(msg: string): void { + if (!warned.has(msg)) { + warned.add(msg); + console.warn(yellow(`[@iconify-loader] ${msg}`)); + } +} diff --git a/packages/utils/tests/file-system-icon-test.ts b/packages/utils/tests/file-system-icon-test.ts index 9f0a131..f08219b 100644 --- a/packages/utils/tests/file-system-icon-test.ts +++ b/packages/utils/tests/file-system-icon-test.ts @@ -1,4 +1,4 @@ -import { FileSystemIconLoader } from '../lib'; +import { FileSystemIconLoader } from '../lib/loader/loaders'; describe('Testing FileSystemIconLoader', () => { test('FileSystemIconLoader', async () => { diff --git a/packages/utils/tests/iconify-icon-test.ts b/packages/utils/tests/iconify-icon-test.ts index 75a284a..d6e8830 100644 --- a/packages/utils/tests/iconify-icon-test.ts +++ b/packages/utils/tests/iconify-icon-test.ts @@ -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); + }); }); diff --git a/packages/utils/tests/load-icon-test.ts b/packages/utils/tests/load-icon-test.ts index 514208d..85513a4 100644 --- a/packages/utils/tests/load-icon-test.ts +++ b/packages/utils/tests/load-icon-test.ts @@ -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';