mirror of
https://github.com/iconify/iconify.git
synced 2024-11-09 23:00:56 +00:00
Merge branch 'userquin/feat-split-modern-loader-next' into next
This commit is contained in:
commit
37d36b4e09
1
packages/utils/.gitignore
vendored
1
packages/utils/.gitignore
vendored
@ -7,4 +7,5 @@ npm-debug.log
|
||||
yarn.lock
|
||||
tsconfig.tsbuildinfo
|
||||
lib
|
||||
dual-lib
|
||||
tests-compiled
|
||||
|
50
packages/utils/build.config.ts
Normal file
50
packages/utils/build.config.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import { defineBuildConfig } from 'unbuild'
|
||||
|
||||
export default defineBuildConfig({
|
||||
outDir: './lib',
|
||||
entries: [
|
||||
{ input: 'src/colors/types', name: 'colors/types' },
|
||||
{ input: 'src/colors/keywords', name: 'colors/keywords' },
|
||||
{ input: 'src/colors/index', name: 'colors/index' },
|
||||
{ input: 'src/customisations/bool', name: 'customisations/bool' },
|
||||
{ input: 'src/customisations/compare', name: 'customisations/compare' },
|
||||
{ input: 'src/customisations/index', name: 'customisations/index' },
|
||||
{ input: 'src/customisations/rotate', name: 'customisations/rotate' },
|
||||
{ input: 'src/customisations/shorthand', name: 'customisations/shorthand' },
|
||||
{ input: 'src/icon/index', name: 'icon/index' },
|
||||
{ input: 'src/icon/merge', name: 'icon/merge' },
|
||||
{ input: 'src/icon/name', name: 'icon/name' },
|
||||
{ input: 'src/icon-set/convert-info', name: 'icon-set/convert-info' },
|
||||
{ input: 'src/icon-set/expand', name: 'icon-set/expand' },
|
||||
{ input: 'src/icon-set/get-icon', name: 'icon-set/get-icon' },
|
||||
{ input: 'src/icon-set/get-icons', name: 'icon-set/get-icons' },
|
||||
{ input: 'src/icon-set/minify', name: 'icon-set/minify' },
|
||||
{ input: 'src/icon-set/parse', name: 'icon-set/parse' },
|
||||
{ input: 'src/icon-set/validate', name: 'icon-set/validate' },
|
||||
{ input: 'src/loader/custom', name: 'loader/custom' },
|
||||
{ input: 'src/loader/fs', name: 'loader/fs' },
|
||||
{ input: 'src/loader/install-pkg', name: 'loader/install-pkg' },
|
||||
{ input: 'src/loader/loader', name: 'loader/loader' },
|
||||
{ input: 'src/loader/modern', name: 'loader/modern' },
|
||||
{ input: 'src/loader/node-loader', name: 'loader/node-loader' },
|
||||
{ input: 'src/loader/node-loaders', name: 'loader/node-loaders' },
|
||||
{ input: 'src/loader/types', name: 'loader/types' },
|
||||
{ input: 'src/loader/utils', name: 'loader/utils' },
|
||||
{ input: 'src/loader/warn', name: 'loader/warn' },
|
||||
{ input: 'src/misc/strings', name: 'misc/strings' },
|
||||
{ input: 'src/svg/build', name: 'svg/build' },
|
||||
{ input: 'src/svg/encode-svg-for-css', name: 'svg/encode-svg-for-css' },
|
||||
{ input: 'src/svg/id', name: 'svg/id' },
|
||||
{ input: 'src/svg/size', name: 'svg/size' },
|
||||
{ input: 'src/index', name: 'index' },
|
||||
],
|
||||
clean: true,
|
||||
declaration: true,
|
||||
externals: [
|
||||
'local-pkg',
|
||||
'fs',
|
||||
],
|
||||
rollup: {
|
||||
emitCJS: true,
|
||||
},
|
||||
})
|
@ -1,17 +0,0 @@
|
||||
/* eslint-disable */
|
||||
const { buildFiles } = require('@iconify/library-builder');
|
||||
|
||||
buildFiles({
|
||||
root: __dirname,
|
||||
source: './src',
|
||||
target: './lib',
|
||||
cleanup: true,
|
||||
updateExports: true,
|
||||
})
|
||||
.then(() => {
|
||||
console.log('Done');
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
11
packages/utils/jest.config.cjs
Normal file
11
packages/utils/jest.config.cjs
Normal file
@ -0,0 +1,11 @@
|
||||
const { buildConfiguration } = require('./jest.shared.config.cjs');
|
||||
|
||||
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
|
||||
module.exports = buildConfiguration({
|
||||
moduleFileExtensions: ['ts', 'cjs', 'js'],
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
useESM: false,
|
||||
},
|
||||
},
|
||||
});
|
@ -1,7 +0,0 @@
|
||||
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
|
||||
module.exports = {
|
||||
verbose: true,
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/tests/*-test.ts'],
|
||||
};
|
10
packages/utils/jest.config.mjs
Normal file
10
packages/utils/jest.config.mjs
Normal file
@ -0,0 +1,10 @@
|
||||
import pkg from './jest.shared.config.cjs';
|
||||
|
||||
export default pkg.buildConfiguration({
|
||||
moduleFileExtensions: ['ts', 'mjs', 'js'],
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
useESM: true,
|
||||
},
|
||||
},
|
||||
})
|
26
packages/utils/jest.shared.config.cjs
Normal file
26
packages/utils/jest.shared.config.cjs
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Jest shared configuration: see https://jestjs.io/docs/ecmascript-modules.
|
||||
*
|
||||
* @param {import('ts-jest/dist/types').InitialOptionsTsJest} configuration
|
||||
* @return {import('ts-jest/dist/types').InitialOptionsTsJest}
|
||||
*/
|
||||
function buildConfiguration(configuration) {
|
||||
return Object.assign({}, {
|
||||
verbose: true,
|
||||
testEnvironment: 'node',
|
||||
moduleDirectories: [
|
||||
'node_modules',
|
||||
'src',
|
||||
],
|
||||
extensionsToTreatAsEsm: ['.ts'],
|
||||
transform: {
|
||||
'^.+\\.ts$': 'ts-jest',
|
||||
},
|
||||
testMatch: [
|
||||
'**/tests/*-test.ts',
|
||||
],
|
||||
}, configuration)
|
||||
}
|
||||
|
||||
exports.buildConfiguration = buildConfiguration;
|
||||
module.exports = { buildConfiguration };
|
3185
packages/utils/package-lock.json
generated
3185
packages/utils/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,6 @@
|
||||
{
|
||||
"name": "@iconify/utils",
|
||||
"type": "module",
|
||||
"description": "Common functions for working with Iconify icon sets used by various packages.",
|
||||
"author": "Vjacheslav Trushkin",
|
||||
"version": "1.0.23",
|
||||
@ -13,166 +14,191 @@
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "rimraf lib tests-compiled tsconfig.tsbuildinfo",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"lint": "eslint --fix src/**/*.ts",
|
||||
"prebuild": "npm run lint && npm run clean",
|
||||
"build": "node build",
|
||||
"build": "unbuild",
|
||||
"test:jest": "jest --runInBand",
|
||||
"test:jasmine": "cross-env NODE_OPTIONS=--experimental-vm-modules npx jasmine",
|
||||
"test": "npm run test:jest && npm run test:jasmine"
|
||||
"test": "npm run test:jest && npm run test:jasmine",
|
||||
"test:jest-cjs": "npm run build-dual && jest --clearCache && jest --config=jest.config.cjs",
|
||||
"test:jest-esm": "npm run build-dual && jest --clearCache && cross-env NODE_OPTIONS=--experimental-vm-modules npx jest --config=jest.config.mjs",
|
||||
"test-dual": "npm run test:jest-cjs && npm run test:jest-esm && npm run test:jasmine",
|
||||
"vitest:cjs": "npm run build-dual && vitest --config vitest.config.cjs",
|
||||
"vitest:esm": "npm run build-dual && vitest --config vitest.config.mjs",
|
||||
"vitest": "npm run vitest:cjs && npm run vitest:esm"
|
||||
},
|
||||
"main": "./lib/index.js",
|
||||
"module": "./lib/index.mjs",
|
||||
"sideEffects": false,
|
||||
"exports": {
|
||||
"./*": "./*",
|
||||
".": {
|
||||
"require": "./lib/index.js",
|
||||
"require": "./lib/index.cjs",
|
||||
"import": "./lib/index.mjs"
|
||||
},
|
||||
"./*": "./*",
|
||||
"./lib/colors": {
|
||||
"require": "./lib/colors/index.js",
|
||||
"require": "./lib/colors/index.cjs",
|
||||
"import": "./lib/colors/index.mjs"
|
||||
},
|
||||
"./lib/colors/index": {
|
||||
"require": "./lib/colors/index.js",
|
||||
"require": "./lib/colors/index.cjs",
|
||||
"import": "./lib/colors/index.mjs"
|
||||
},
|
||||
"./lib/colors/keywords": {
|
||||
"require": "./lib/colors/keywords.js",
|
||||
"require": "./lib/colors/keywords.cjs",
|
||||
"import": "./lib/colors/keywords.mjs"
|
||||
},
|
||||
"./lib/colors/types": {
|
||||
"require": "./lib/colors/types.js",
|
||||
"require": "./lib/colors/types.cjs",
|
||||
"import": "./lib/colors/types.mjs"
|
||||
},
|
||||
"./lib/customisations/bool": {
|
||||
"require": "./lib/customisations/bool.js",
|
||||
"require": "./lib/customisations/bool.cjs",
|
||||
"import": "./lib/customisations/bool.mjs"
|
||||
},
|
||||
"./lib/customisations/compare": {
|
||||
"require": "./lib/customisations/compare.js",
|
||||
"require": "./lib/customisations/compare.cjs",
|
||||
"import": "./lib/customisations/compare.mjs"
|
||||
},
|
||||
"./lib/customisations": {
|
||||
"require": "./lib/customisations/index.js",
|
||||
"require": "./lib/customisations/index.cjs",
|
||||
"import": "./lib/customisations/index.mjs"
|
||||
},
|
||||
"./lib/customisations/index": {
|
||||
"require": "./lib/customisations/index.js",
|
||||
"require": "./lib/customisations/index.cjs",
|
||||
"import": "./lib/customisations/index.mjs"
|
||||
},
|
||||
"./lib/customisations/rotate": {
|
||||
"require": "./lib/customisations/rotate.js",
|
||||
"require": "./lib/customisations/rotate.cjs",
|
||||
"import": "./lib/customisations/rotate.mjs"
|
||||
},
|
||||
"./lib/customisations/shorthand": {
|
||||
"require": "./lib/customisations/shorthand.js",
|
||||
"require": "./lib/customisations/shorthand.cjs",
|
||||
"import": "./lib/customisations/shorthand.mjs"
|
||||
},
|
||||
"./lib/icon-set/convert-info": {
|
||||
"require": "./lib/icon-set/convert-info.js",
|
||||
"require": "./lib/icon-set/convert-info.cjs",
|
||||
"import": "./lib/icon-set/convert-info.mjs"
|
||||
},
|
||||
"./lib/icon-set/expand": {
|
||||
"require": "./lib/icon-set/expand.js",
|
||||
"require": "./lib/icon-set/expand.cjs",
|
||||
"import": "./lib/icon-set/expand.mjs"
|
||||
},
|
||||
"./lib/icon-set/get-icon": {
|
||||
"require": "./lib/icon-set/get-icon.js",
|
||||
"require": "./lib/icon-set/get-icon.cjs",
|
||||
"import": "./lib/icon-set/get-icon.mjs"
|
||||
},
|
||||
"./lib/icon-set/get-icons": {
|
||||
"require": "./lib/icon-set/get-icons.js",
|
||||
"require": "./lib/icon-set/get-icons.cjs",
|
||||
"import": "./lib/icon-set/get-icons.mjs"
|
||||
},
|
||||
"./lib/icon-set/minify": {
|
||||
"require": "./lib/icon-set/minify.js",
|
||||
"require": "./lib/icon-set/minify.cjs",
|
||||
"import": "./lib/icon-set/minify.mjs"
|
||||
},
|
||||
"./lib/icon-set/parse": {
|
||||
"require": "./lib/icon-set/parse.js",
|
||||
"require": "./lib/icon-set/parse.cjs",
|
||||
"import": "./lib/icon-set/parse.mjs"
|
||||
},
|
||||
"./lib/icon-set/validate": {
|
||||
"require": "./lib/icon-set/validate.js",
|
||||
"require": "./lib/icon-set/validate.cjs",
|
||||
"import": "./lib/icon-set/validate.mjs"
|
||||
},
|
||||
"./lib/icon": {
|
||||
"require": "./lib/icon/index.js",
|
||||
"require": "./lib/icon/index.cjs",
|
||||
"import": "./lib/icon/index.mjs"
|
||||
},
|
||||
"./lib/icon/index": {
|
||||
"require": "./lib/icon/index.js",
|
||||
"require": "./lib/icon/index.cjs",
|
||||
"import": "./lib/icon/index.mjs"
|
||||
},
|
||||
"./lib/icon/merge": {
|
||||
"require": "./lib/icon/merge.js",
|
||||
"require": "./lib/icon/merge.cjs",
|
||||
"import": "./lib/icon/merge.mjs"
|
||||
},
|
||||
"./lib/icon/name": {
|
||||
"require": "./lib/icon/name.js",
|
||||
"require": "./lib/icon/name.cjs",
|
||||
"import": "./lib/icon/name.mjs"
|
||||
},
|
||||
"./lib": {
|
||||
"require": "./lib/index.js",
|
||||
"require": "./lib/index.cjs",
|
||||
"import": "./lib/index.mjs"
|
||||
},
|
||||
"./lib/index": {
|
||||
"require": "./lib/index.js",
|
||||
"require": "./lib/index.cjs",
|
||||
"import": "./lib/index.mjs"
|
||||
},
|
||||
"./lib/loader/custom": {
|
||||
"require": "./lib/loader/custom.js",
|
||||
"require": "./lib/loader/custom.cjs",
|
||||
"import": "./lib/loader/custom.mjs"
|
||||
},
|
||||
"./lib/loader/fs": {
|
||||
"require": "./lib/loader/fs.js",
|
||||
"import": "./lib/loader/fs.mjs"
|
||||
"require": "./lib/loader/fs.cjs",
|
||||
"import": "./lib/loader/fs.mjs",
|
||||
"types": "./lib/loader/fs.d.ts"
|
||||
},
|
||||
"./lib/loader/install-pkg": {
|
||||
"require": "./lib/loader/install-pkg.js",
|
||||
"import": "./lib/loader/install-pkg.mjs"
|
||||
"require": "./lib/loader/install-pkg.cjs",
|
||||
"import": "./lib/loader/install-pkg.mjs",
|
||||
"types": "./lib/loader/install-pkg.d.ts"
|
||||
},
|
||||
"./lib/loader/loader": {
|
||||
"require": "./lib/loader/loader.js",
|
||||
"require": "./lib/loader/loader.cjs",
|
||||
"import": "./lib/loader/loader.mjs"
|
||||
},
|
||||
"./lib/loader/loaders": {
|
||||
"require": "./lib/loader/loaders.js",
|
||||
"import": "./lib/loader/loaders.mjs"
|
||||
},
|
||||
"./lib/loader/modern": {
|
||||
"require": "./lib/loader/modern.js",
|
||||
"require": "./lib/loader/modern.cjs",
|
||||
"import": "./lib/loader/modern.mjs"
|
||||
},
|
||||
"./lib/loader/node-loader": {
|
||||
"require": "./lib/loader/node-loader.cjs",
|
||||
"import": "./lib/loader/node-loader.mjs",
|
||||
"types": "./lib/loader/node-loader.d.ts"
|
||||
},
|
||||
"./lib/loader/node-loaders": {
|
||||
"require": "./lib/loader/node-loaders.cjs",
|
||||
"import": "./lib/loader/node-loaders.mjs",
|
||||
"types": "./lib/loader/node-loaders.d.ts"
|
||||
},
|
||||
"./lib/loader/types": {
|
||||
"require": "./lib/loader/types.js",
|
||||
"require": "./lib/loader/types.cjs",
|
||||
"import": "./lib/loader/types.mjs"
|
||||
},
|
||||
"./lib/loader/utils": {
|
||||
"require": "./lib/loader/utils.js",
|
||||
"require": "./lib/loader/utils.cjs",
|
||||
"import": "./lib/loader/utils.mjs"
|
||||
},
|
||||
"./lib/loader/warn": {
|
||||
"require": "./lib/loader/warn.cjs",
|
||||
"import": "./lib/loader/warn.mjs",
|
||||
"types": "./lib/loader/warn.d.ts"
|
||||
},
|
||||
"./lib/misc/strings": {
|
||||
"require": "./lib/misc/strings.js",
|
||||
"require": "./lib/misc/strings.cjs",
|
||||
"import": "./lib/misc/strings.mjs"
|
||||
},
|
||||
"./lib/svg/build": {
|
||||
"require": "./lib/svg/build.js",
|
||||
"require": "./lib/svg/build.cjs",
|
||||
"import": "./lib/svg/build.mjs"
|
||||
},
|
||||
"./lib/svg/encode-svg-for-css": {
|
||||
"require": "./lib/svg/encode-svg-for-css.js",
|
||||
"require": "./lib/svg/encode-svg-for-css.cjs",
|
||||
"import": "./lib/svg/encode-svg-for-css.mjs"
|
||||
},
|
||||
"./lib/svg/id": {
|
||||
"require": "./lib/svg/id.js",
|
||||
"require": "./lib/svg/id.cjs",
|
||||
"import": "./lib/svg/id.mjs"
|
||||
},
|
||||
"./lib/svg/size": {
|
||||
"require": "./lib/svg/size.js",
|
||||
"require": "./lib/svg/size.cjs",
|
||||
"import": "./lib/svg/size.mjs"
|
||||
}
|
||||
},
|
||||
"main": "lib/index.cjs",
|
||||
"module": "lib/index.mjs",
|
||||
"types": "lib/index.d.ts",
|
||||
"files": [
|
||||
"lib",
|
||||
"*.d.ts"
|
||||
],
|
||||
"dependencies": {
|
||||
"@antfu/install-pkg": "^0.1.0",
|
||||
"@antfu/utils": "^0.3.0",
|
||||
@ -196,6 +222,9 @@
|
||||
"jest": "^27.2.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^27.0.5",
|
||||
"typescript": "^4.4.3"
|
||||
"ts-node": "^10.6.0",
|
||||
"typescript": "^4.4.3",
|
||||
"unbuild": "^0.6.9",
|
||||
"vitest": "^0.5.9"
|
||||
}
|
||||
}
|
||||
|
@ -53,12 +53,12 @@ export type {
|
||||
IconCustomizations,
|
||||
IconifyLoaderOptions,
|
||||
InlineCollection,
|
||||
UniversalIconLoader,
|
||||
} from './loader/types';
|
||||
export { mergeIconProps } from './loader/utils';
|
||||
export { isNode, loadIcon } from './loader/loader';
|
||||
export { FileSystemIconLoader } from './loader/loaders';
|
||||
export { getCustomIcon } from './loader/custom';
|
||||
export { searchForIcon } from './loader/modern';
|
||||
export { loadIcon } from './loader/loader';
|
||||
|
||||
// Misc
|
||||
export { camelize, camelToKebab, pascalize } from './misc/strings';
|
||||
export { camelize, camelToKebab, snakelize, pascalize } from './misc/strings';
|
||||
|
@ -1,82 +1,47 @@
|
||||
import { getCustomIcon } from './custom';
|
||||
import type { UniversalIconLoader } from './types';
|
||||
import { searchForIcon } from './modern';
|
||||
import { warnOnce } from './install-pkg';
|
||||
import type { IconifyLoaderOptions } from './types';
|
||||
|
||||
export const isNode = typeof process < 'u' && typeof process.stdout < 'u';
|
||||
|
||||
export async function loadIcon(
|
||||
collection: string,
|
||||
icon: string,
|
||||
options?: IconifyLoaderOptions
|
||||
): Promise<string | undefined> {
|
||||
export const loadIcon: UniversalIconLoader = async (
|
||||
collection,
|
||||
icon,
|
||||
options
|
||||
) => {
|
||||
const custom = options?.customCollections?.[collection];
|
||||
|
||||
if (custom) {
|
||||
const result = await getCustomIcon(custom, collection, icon, options);
|
||||
if (result) {
|
||||
return result;
|
||||
if (typeof custom === 'function') {
|
||||
const result = await custom(icon);
|
||||
if (result) {
|
||||
if (typeof result === 'string') {
|
||||
return await getCustomIcon(
|
||||
() => result,
|
||||
collection,
|
||||
icon,
|
||||
options
|
||||
);
|
||||
}
|
||||
// if using dynamic import and requesting the json file
|
||||
// for example: carbon: () => import('@iconify-json/carbon/icons.json').then(i => i.default as any)
|
||||
if ('icons' in result) {
|
||||
// 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(
|
||||
result,
|
||||
collection,
|
||||
ids,
|
||||
options
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return await getCustomIcon(custom, collection, icon, options);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
return require('./fs.js') as Promise<
|
||||
typeof import('./fs') | undefined
|
||||
>;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function loadNodeBuiltinIcon(
|
||||
collection: string,
|
||||
icon: string,
|
||||
options?: IconifyLoaderOptions,
|
||||
warn = true
|
||||
): Promise<string | undefined> {
|
||||
type IconifyJSON = Parameters<typeof searchForIcon>[0];
|
||||
type LoadCollectionFromFS = (
|
||||
collection: string,
|
||||
autoInstall?: boolean
|
||||
) => Promise<IconifyJSON>;
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
const {
|
||||
loadCollectionFromFS,
|
||||
}: {
|
||||
loadCollectionFromFS: 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);
|
||||
}
|
||||
|
||||
if (warn) {
|
||||
warnOnce(
|
||||
`failed to load \`@iconify-json/${collection}\`, have you installed it?`
|
||||
);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
36
packages/utils/src/loader/node-loader.ts
Normal file
36
packages/utils/src/loader/node-loader.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import type { UniversalIconLoader } from './types';
|
||||
import { searchForIcon } from './modern';
|
||||
import { loadCollectionFromFS } from './fs';
|
||||
import { warnOnce } from './warn';
|
||||
import { loadIcon } from './loader';
|
||||
|
||||
export const loadNodeIcon: UniversalIconLoader = async (
|
||||
collection,
|
||||
icon,
|
||||
options
|
||||
) => {
|
||||
let result = await loadIcon(collection, icon, options);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
@ -1,7 +1,7 @@
|
||||
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 { camelize, pascalize, snakelize } from '../misc/strings';
|
||||
|
||||
/**
|
||||
* Returns CustomIconLoader for loading icons from a directory
|
||||
@ -15,6 +15,7 @@ export function FileSystemIconLoader(
|
||||
`${dir}/${name}.svg`,
|
||||
`${dir}/${camelize(name)}.svg`,
|
||||
`${dir}/${pascalize(name)}.svg`,
|
||||
`${dir}/${snakelize(name)}.svg`,
|
||||
];
|
||||
let stat: Stats;
|
||||
for (const path of paths) {
|
@ -1,5 +1,15 @@
|
||||
import type { Awaitable } from '@antfu/utils';
|
||||
import type { FullIconCustomisations } from '../customisations';
|
||||
import type { IconifyJSON } from '@iconify/types';
|
||||
|
||||
/**
|
||||
* Type for universal icon loader.
|
||||
*/
|
||||
export type UniversalIconLoader = (
|
||||
collection: string,
|
||||
icon: string,
|
||||
options?: IconifyLoaderOptions
|
||||
) => Promise<string | undefined>;
|
||||
|
||||
/**
|
||||
* Custom icon loader, used by `getCustomIcon`.
|
||||
@ -75,6 +85,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.
|
||||
*
|
||||
@ -104,7 +119,13 @@ export type IconifyLoaderOptions = {
|
||||
/**
|
||||
* Loader for custom loaders
|
||||
*/
|
||||
customCollections?: Record<string, CustomIconLoader | InlineCollection>;
|
||||
customCollections?: Record<
|
||||
string,
|
||||
| (() => Awaitable<IconifyJSON>)
|
||||
| undefined
|
||||
| CustomIconLoader
|
||||
| InlineCollection
|
||||
>;
|
||||
|
||||
/**
|
||||
* Icon customizer
|
||||
|
10
packages/utils/src/loader/warn.ts
Normal file
10
packages/utils/src/loader/warn.ts
Normal 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}`));
|
||||
}
|
||||
}
|
@ -23,3 +23,11 @@ export function camelToKebab(key: string): string {
|
||||
.trim();
|
||||
return result.split(/\s+/g).join('-').toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert string string to snake-case
|
||||
*/
|
||||
export function snakelize(str: string): string {
|
||||
const kebab = camelToKebab(str);
|
||||
return kebab.replace(/-/g, '_');
|
||||
}
|
||||
|
@ -1,20 +1,17 @@
|
||||
import { FileSystemIconLoader } from '../lib';
|
||||
import { FileSystemIconLoader } from '../lib/loader/node-loaders';
|
||||
|
||||
const fixturesDir = './tests/fixtures';
|
||||
|
||||
describe('Testing FileSystemIconLoader', () => {
|
||||
test('FileSystemIconLoader', async () => {
|
||||
const result = await FileSystemIconLoader(__dirname + '/fixtures')(
|
||||
'circle'
|
||||
);
|
||||
const result = await FileSystemIconLoader(fixturesDir)('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');
|
||||
const result = await FileSystemIconLoader(fixturesDir, (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();
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { promises as fs } from 'fs';
|
||||
import { getCustomIcon } from '../lib';
|
||||
|
||||
const fixturesDir = __dirname + '/fixtures';
|
||||
const fixturesDir = './tests/fixtures';
|
||||
|
||||
describe('Testing getCustomIcon', () => {
|
||||
test('CustomIconLoader', async () => {
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { loadIcon } from '../lib';
|
||||
import { loadNodeIcon } from '../lib/loader/node-loader';
|
||||
|
||||
describe('Testing loadIcon with @iconify-json/flat-color-icons>', () => {
|
||||
test('loadIcon works', async () => {
|
||||
const result = await loadIcon('flat-color-icons', 'up-right');
|
||||
const result = await loadNodeIcon('flat-color-icons', 'up-right');
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
|
||||
test('loadIcon adds xmlns:xlink', async () => {
|
||||
const result = await loadIcon('flat-color-icons', 'up-right', {
|
||||
const result = await loadNodeIcon('flat-color-icons', 'up-right', {
|
||||
addXmlNs: true,
|
||||
});
|
||||
expect(result).toBeTruthy();
|
||||
@ -15,7 +15,7 @@ describe('Testing loadIcon with @iconify-json/flat-color-icons>', () => {
|
||||
});
|
||||
|
||||
test('loadIcon with customize with default style and class', async () => {
|
||||
const result = await loadIcon('flat-color-icons', 'up-right', {
|
||||
const result = await loadNodeIcon('flat-color-icons', 'up-right', {
|
||||
defaultStyle: 'margin-top: 1rem;',
|
||||
defaultClass: 'clazz',
|
||||
customizations: {
|
||||
@ -34,7 +34,7 @@ describe('Testing loadIcon with @iconify-json/flat-color-icons>', () => {
|
||||
});
|
||||
|
||||
test('loadIcon preserves customizations order', async () => {
|
||||
const result = await loadIcon('flat-color-icons', 'up-right', {
|
||||
const result = await loadNodeIcon('flat-color-icons', 'up-right', {
|
||||
scale: 1,
|
||||
defaultStyle: 'color: red;',
|
||||
defaultClass: 'clazz1',
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { promises as fs } from 'fs';
|
||||
import { CustomIconLoader, loadIcon } from '../lib';
|
||||
import type { CustomIconLoader } from '../lib';
|
||||
import { loadIcon } from '../lib';
|
||||
|
||||
const fixturesDir = __dirname + '/fixtures';
|
||||
const fixturesDir = './tests/fixtures';
|
||||
|
||||
const loader: CustomIconLoader = async (name) => {
|
||||
return await fs.readFile(`${fixturesDir}/${name}.svg`, 'utf8');
|
||||
@ -22,6 +23,21 @@ describe('Testing loadIcon', () => {
|
||||
expect(svg).toEqual(result);
|
||||
});
|
||||
|
||||
test('CustomCollection using dynamic import', async () => {
|
||||
// @ts-ignore
|
||||
const result = await loadIcon('flat-color-icons', 'up-right', {
|
||||
customCollections: {
|
||||
'flat-color-icons': () =>
|
||||
import(
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
'@iconify-json/flat-color-icons/icons.json'
|
||||
).then((i) => i?.default),
|
||||
},
|
||||
});
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
|
||||
test('CustomCollection with transform', async () => {
|
||||
const svg = await loader('circle');
|
||||
expect(svg).toBeTruthy();
|
||||
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"extends": "../tsconfig-base.json",
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["node", "jest"],
|
||||
"rootDir": ".",
|
||||
"outDir": "../tests-compiled"
|
||||
}
|
||||
"outDir": "../tests-compiled",
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib",
|
||||
"target": "ES2019",
|
||||
"module": "CommonJS",
|
||||
"declaration": true,
|
||||
"declarationMap": false,
|
||||
"sourceMap": false,
|
||||
"composite": true,
|
||||
"strict": true,
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"importsNotUsedAsValues": "error"
|
||||
}
|
||||
}
|
@ -1,8 +1,17 @@
|
||||
{
|
||||
"extends": "./tsconfig-base.json",
|
||||
"include": ["src/**/*.ts", ".eslintrc.js"],
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib"
|
||||
}
|
||||
"rootDir": "./",
|
||||
"outDir": "./lib",
|
||||
"target": "ES2019",
|
||||
"module": "ESNext",
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"importsNotUsedAsValues": "error",
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
|
13
packages/utils/vitest.config.cjs
Normal file
13
packages/utils/vitest.config.cjs
Normal file
@ -0,0 +1,13 @@
|
||||
const { defineConfig } = require('vitest/config');
|
||||
|
||||
module.exports = defineConfig({
|
||||
resolve: {
|
||||
mainFields: ['require'],
|
||||
extensions: ['.cjs'],
|
||||
},
|
||||
test: {
|
||||
globals: true,
|
||||
watch: false,
|
||||
include: ['**/tests/*-test.ts'],
|
||||
},
|
||||
});
|
9
packages/utils/vitest.config.mjs
Normal file
9
packages/utils/vitest.config.mjs
Normal file
@ -0,0 +1,9 @@
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
globals: true,
|
||||
watch: false,
|
||||
include: ['**/tests/*-test.ts'],
|
||||
},
|
||||
});
|
Loading…
Reference in New Issue
Block a user