2
0
mirror of https://github.com/iconify/iconify.git synced 2024-11-09 23:00:56 +00:00

Revert "chore: move some modules and update types test: include some tests for writeOnce"

This reverts commit 6134d1f6
This commit is contained in:
Joaquín Sánchez Jiménez 2022-03-02 18:55:03 +01:00
parent b59a49ece4
commit 79e4530fab
7 changed files with 209 additions and 8 deletions

View File

@ -0,0 +1,42 @@
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}`));
}
}
let pending: Promise<void> | undefined;
const tasks: Record<string, Promise<void> | undefined> = {};
export async function tryInstallPkg(name: string): Promise<void | undefined> {
if (pending) {
await pending;
}
if (!tasks[name]) {
// eslint-disable-next-line no-console
console.log(cyan(`Installing ${name}...`));
tasks[name] = pending = installPackage(name, {
dev: true,
preferOffline: true,
})
.then(() => sleep(300))
// eslint-disable-next-line
.catch((e: any) => {
warnOnce(`Failed to install ${name}`);
console.error(e);
})
.finally(() => {
pending = undefined;
});
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return tasks[name]!;
}

View File

@ -1,7 +1,11 @@
import { getCustomIcon } from './custom';
import { searchForIcon } from './modern';
import { warnOnce } from './warn';
import type { IconifyLoaderOptions } from './types';
import { searchForIcon } from './modern';
export const isNode = typeof process < 'u' && typeof process.stdout < 'u';
export async function loadIcon(
collection: string,
icon: string,
@ -33,7 +37,52 @@ export async function loadIcon(
}
}
return undefined;
if (!isNode) {
return undefined;
}
return await loadNodeBuiltinIcon(collection, icon, options);
}
async function importFsModule(): Promise<typeof import('./fs') | undefined> {
try {
return await import('./fs');
} catch {
try {
// cjs environments
return require('./fs.js');
}
catch {
return undefined;
}
}
}
async function loadNodeBuiltinIcon(
collection: string,
icon: string,
options?: IconifyLoaderOptions,
): Promise<string | undefined> {
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 (!result && options?.warn) {
warnOnce(`failed to load ${options.warn} icon`);
}
return result;
}

View File

@ -0,0 +1,36 @@
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
*/
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;
}
}
} : () => undefined;
}

View File

@ -76,11 +76,6 @@ 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,21 @@
import { FileSystemIconLoader } from '../lib';
describe('Testing FileSystemIconLoader', () => {
test('FileSystemIconLoader', async () => {
const result = await FileSystemIconLoader(__dirname + '/fixtures')(
'circle'
);
expect(result && result.indexOf('svg') > -1).toBeTruthy();
});
test('FileSystemIconLoader with transform', async () => {
const result = await FileSystemIconLoader(
__dirname + '/fixtures',
(icon) => {
return icon.replace('<svg ', '<svg width="1em" height="1em" ');
}
)('circle');
expect(result && result.indexOf('width="1em"') > -1).toBeTruthy();
expect(result && result.indexOf('height="1em"') > -1).toBeTruthy();
});
});

View File

@ -0,0 +1,59 @@
import { loadIcon } from '../lib';
describe('Testing loadIcon with @iconify-json/flat-color-icons>', () => {
test('loadIcon works', async () => {
const result = await loadIcon('flat-color-icons', 'up-right');
expect(result).toBeTruthy();
});
test('loadIcon adds xmlns:xlink', async () => {
const result = await loadIcon('flat-color-icons', 'up-right', { addXmlNs: true });
expect(result).toBeTruthy();
expect(result && result.indexOf('xmlns:xlink=') > - 1).toBeTruthy();
});
test('loadIcon with customize with default style and class', async () => {
const result = await loadIcon('flat-color-icons', 'up-right', {
defaultStyle: 'margin-top: 1rem;',
defaultClass: 'clazz',
customizations: {
customize(props) {
props.width = '2em';
props.height = '2em';
return props;
},
}
});
expect(result).toBeTruthy();
expect(result && result.indexOf('margin-top: 1rem;') > - 1).toBeTruthy();
expect(result && result.indexOf('class="clazz"') > - 1).toBeTruthy();
expect(result && result.indexOf('width="2em"') > - 1).toBeTruthy();
expect(result && result.indexOf('height="2em"') > - 1).toBeTruthy();
});
test('loadIcon preserves customizations order', async () => {
const result = await loadIcon('flat-color-icons', 'up-right', {
scale: 1,
defaultStyle: 'color: red;',
defaultClass: 'clazz1',
customizations: {
additionalProps: {
'width': '2em',
'height': '2em',
'style': 'color: blue;',
'class': 'clazz2',
},
// it will never be called, it is not a custom icon
transform(icon) {
return icon.replace('<svg ', '<svg width="4em" height="4em" ');
},
}
});
expect(result).toBeTruthy();
expect(result && result.includes('style="color: blue;"')).toBeTruthy();
expect(result && result.includes('class="clazz2"')).toBeTruthy();
expect(result && result.includes('width="2em"')).toBeTruthy();
expect(result && result.includes('height="2em"')).toBeTruthy();
});
});

View File

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