mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-12 12:09:26 +00:00
Aliases and external mappings
This commit is contained in:
@@ -9,14 +9,28 @@ export const CACHEABLE_HTTP_ERRORS = [410];
|
||||
|
||||
let parser: DOMParser;
|
||||
|
||||
const defaultFallback = function (name: string, family?: string, variant?: string): IconLocator | undefined {
|
||||
if (this.name !== 'wa') {
|
||||
return {
|
||||
name,
|
||||
family,
|
||||
variant,
|
||||
library: 'wa',
|
||||
};
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export default class IconLibrary {
|
||||
/** The original object used to create this library */
|
||||
private spec: UnregisteredIconLibrary;
|
||||
readonly spec: UnregisteredIconLibrary;
|
||||
|
||||
readonly name: string;
|
||||
readonly mutator?: IconLibraryMutator;
|
||||
readonly system?: IconMapping;
|
||||
readonly spriteSheet?: boolean;
|
||||
readonly fallback?: IconMapping;
|
||||
|
||||
/** Inlined markup, keyed by URL */
|
||||
inlined: IconLibraryCacheFlat = {};
|
||||
@@ -33,6 +47,7 @@ export default class IconLibrary {
|
||||
this.mutator = library.mutator;
|
||||
this.system = library.system;
|
||||
this.spriteSheet = library.spriteSheet;
|
||||
this.fallback = library.fallback ?? defaultFallback;
|
||||
|
||||
if (library.inlined) {
|
||||
this.inline(library.inlined);
|
||||
@@ -42,7 +57,7 @@ export default class IconLibrary {
|
||||
/**
|
||||
* Convert an icon name, family, and variant into a URL
|
||||
*/
|
||||
getUrl(name: string, family?: string, variant?: string) {
|
||||
getUrl(name: string, family?: string, variant?: string): string {
|
||||
// console.warn('getUrl', name, family, variant);
|
||||
if (name.startsWith('system:')) {
|
||||
name = name.slice(7);
|
||||
@@ -54,6 +69,14 @@ export default class IconLibrary {
|
||||
name = resolved.name ?? name;
|
||||
family = resolved.family ?? family;
|
||||
variant = resolved.variant ?? variant;
|
||||
|
||||
if (resolved.library && resolved.library !== this.name) {
|
||||
let library = IconLibrary.registry.get(resolved.library);
|
||||
|
||||
if (library) {
|
||||
return library.getUrl(name, family, variant);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,7 +148,15 @@ export default class IconLibrary {
|
||||
// Try again with fallback
|
||||
let fallback = this.spec.fallback(name, family, variant);
|
||||
if (fallback) {
|
||||
return this.getElement(fallback.name, fallback.family, fallback.variant);
|
||||
let library: IconLibrary | undefined = this;
|
||||
|
||||
if (fallback.library && fallback.library !== this.name) {
|
||||
library = IconLibrary.registry.get(fallback.library);
|
||||
}
|
||||
|
||||
if (library) {
|
||||
return library.getElement(fallback.name, fallback.family, fallback.variant);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,14 +226,20 @@ export default class IconLibrary {
|
||||
|
||||
Object.assign(this.inlined, flatCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a clone of this library, optionally overriding some of its properties.
|
||||
*/
|
||||
extend(library: Partial<UnregisteredIconLibrary> = {}) {
|
||||
return new IconLibrary({ ...this.spec, ...library });
|
||||
}
|
||||
|
||||
static registry = new Map<string, IconLibrary>();
|
||||
}
|
||||
|
||||
export type IconLibraryResolver = (name: string, family?: string, variant?: string) => string;
|
||||
export type IconMapping = (
|
||||
name: string,
|
||||
family?: string,
|
||||
variant?: string,
|
||||
) => { name: string; family?: string; variant?: string; library?: string } | undefined;
|
||||
export type IconLocator = { name: string; family?: string; variant?: string; library?: string };
|
||||
export type IconMapping = (name: string, family?: string, variant?: string) => IconLocator | undefined;
|
||||
export type IconLibraryGetKey = (name: string) => string;
|
||||
export type IconLibraryMutator = (svg: SVGElement) => void;
|
||||
export type IconFetchedResult = string | typeof CACHEABLE_ERROR | typeof RETRYABLE_ERROR;
|
||||
|
||||
@@ -108,7 +108,7 @@ export const inlined: IconLibraryCacheDeep = {
|
||||
};
|
||||
|
||||
const library: UnregisteredIconLibrary = {
|
||||
name: 'default',
|
||||
name: 'wa',
|
||||
getUrl: getIconUrl,
|
||||
// Cache icons using the free URL
|
||||
getCacheKey: url => url.replace(/\?token=[^&]+/, '').replace(/ka-p\./, 'ka-f.'),
|
||||
@@ -1,5 +1,4 @@
|
||||
import type WaIcon from './icon.js';
|
||||
import defaultLibrary from './library.default.js';
|
||||
import IconLibrary, {
|
||||
CACHEABLE_ERROR,
|
||||
RETRYABLE_ERROR,
|
||||
@@ -9,14 +8,16 @@ import IconLibrary, {
|
||||
type IconLibraryCacheFlat,
|
||||
type UnregisteredIconLibrary,
|
||||
} from './library.js';
|
||||
import waDefaultLibrary from './library.wa.js';
|
||||
|
||||
export { CACHEABLE_ERROR, RETRYABLE_ERROR, fetchIcon };
|
||||
export type { IconFetchedResult, IconLibrary, IconLibraryCacheDeep, IconLibraryCacheFlat, UnregisteredIconLibrary };
|
||||
|
||||
let registry: IconLibrary[] = [];
|
||||
let registry = IconLibrary.registry;
|
||||
let watchedIcons: WaIcon[] = [];
|
||||
|
||||
registerIconLibrary(defaultLibrary);
|
||||
registerIconLibrary(waDefaultLibrary);
|
||||
registerIconLibrary('default', waDefaultLibrary);
|
||||
registerIconLibrary({ name: 'custom' });
|
||||
|
||||
/** Adds an icon to the list of watched icons. */
|
||||
@@ -31,16 +32,37 @@ export function unwatchIcon(icon: WaIcon) {
|
||||
|
||||
/** Returns a library from the registry. */
|
||||
export function getIconLibrary(name?: string) {
|
||||
return registry.find(lib => lib.name === name);
|
||||
return name ? registry.get(name) : undefined;
|
||||
}
|
||||
|
||||
/** Adds an icon library to the registry, or overrides an existing one. */
|
||||
export function registerIconLibrary(library: UnregisteredIconLibrary) {
|
||||
unregisterIconLibrary(library.name);
|
||||
/**
|
||||
* Adds an icon library to the registry, or overrides an existing one.
|
||||
* Optionally accepts a name argument, which will override the library's built-in name, allowing you to register aliases.
|
||||
*/
|
||||
export function registerIconLibrary(name: string, library: UnregisteredIconLibrary | IconLibrary): void;
|
||||
export function registerIconLibrary(library: UnregisteredIconLibrary | IconLibrary): void;
|
||||
export function registerIconLibrary(
|
||||
nameOrLibrary: string | UnregisteredIconLibrary | IconLibrary,
|
||||
library?: UnregisteredIconLibrary | IconLibrary,
|
||||
) {
|
||||
let name;
|
||||
if (typeof nameOrLibrary === 'string') {
|
||||
name = nameOrLibrary;
|
||||
} else {
|
||||
library = nameOrLibrary;
|
||||
}
|
||||
|
||||
let registeredLibrary = new IconLibrary(library);
|
||||
if (!library) {
|
||||
throw new Error('No library provided');
|
||||
}
|
||||
|
||||
registry.push(registeredLibrary);
|
||||
let instance = library instanceof IconLibrary ? library : new IconLibrary(library);
|
||||
|
||||
if (name) {
|
||||
instance = instance.extend({ name });
|
||||
}
|
||||
|
||||
registry.set(instance.name, instance);
|
||||
|
||||
// Redraw watched icons
|
||||
watchedIcons.forEach(icon => {
|
||||
@@ -52,5 +74,5 @@ export function registerIconLibrary(library: UnregisteredIconLibrary) {
|
||||
|
||||
/** Removes an icon library from the registry. */
|
||||
export function unregisterIconLibrary(name: string) {
|
||||
registry = registry.filter(lib => lib.name !== name);
|
||||
registry.delete(name);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export { getKitCode, setKitCode } from './components/icon/library.default.js';
|
||||
export { getKitCode, setKitCode } from './components/icon/library.wa.js';
|
||||
export { registerIconLibrary, unregisterIconLibrary } from './components/icon/registry.js';
|
||||
export { discover, preventTurboFouce, startLoader, stopLoader } from './utilities/autoloader.js';
|
||||
export { getBasePath, setBasePath } from './utilities/base-path.js';
|
||||
|
||||
Reference in New Issue
Block a user