refactor(docs-infra): Lazy-loads SVG icons (#38268)
Prior to this commit, SVG icons were all loaded in the constructor of the `CustomIconRegistry`. This commit avoids that, and loads SVG icons on demand. PR Close #38268
This commit is contained in:
parent
b280d54470
commit
1b17722091
|
@ -39,35 +39,48 @@ const DEFAULT_NS = '$$default';
|
||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CustomIconRegistry extends MatIconRegistry {
|
export class CustomIconRegistry extends MatIconRegistry {
|
||||||
private preloadedSvgElements: SvgIconMap = {[DEFAULT_NS]: {}};
|
private cachedSvgElements: SvgIconMap = {[DEFAULT_NS]: {}};
|
||||||
|
|
||||||
constructor(http: HttpClient, sanitizer: DomSanitizer, @Optional() @Inject(DOCUMENT) document: Document,
|
constructor(http: HttpClient, sanitizer: DomSanitizer, @Optional() @Inject(DOCUMENT) document: Document,
|
||||||
errorHandler: ErrorHandler, @Inject(SVG_ICONS) svgIcons: SvgIconInfo[]) {
|
errorHandler: ErrorHandler, @Inject(SVG_ICONS) private svgIcons: SvgIconInfo[]) {
|
||||||
super(http, sanitizer, document, errorHandler);
|
super(http, sanitizer, document, errorHandler);
|
||||||
this.loadSvgElements(svgIcons);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getNamedSvgIcon(iconName: string, namespace?: string) {
|
getNamedSvgIcon(iconName: string, namespace?: string) {
|
||||||
const nsIconMap = this.preloadedSvgElements[namespace || DEFAULT_NS];
|
const nsIconMap = this.cachedSvgElements[namespace || DEFAULT_NS];
|
||||||
const preloadedElement = nsIconMap && nsIconMap[iconName];
|
let preloadedElement: SVGElement | undefined = nsIconMap && nsIconMap[iconName];
|
||||||
|
if (!preloadedElement) {
|
||||||
|
preloadedElement = this.loadSvgElement(iconName, namespace);
|
||||||
|
}
|
||||||
|
|
||||||
return preloadedElement
|
return preloadedElement
|
||||||
? of(preloadedElement.cloneNode(true) as SVGElement)
|
? of(preloadedElement.cloneNode(true) as SVGElement)
|
||||||
: super.getNamedSvgIcon(iconName, namespace);
|
: super.getNamedSvgIcon(iconName, namespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
private loadSvgElements(svgIcons: SvgIconInfo[]) {
|
private loadSvgElement(iconName: string, namespace?: string): SVGElement | undefined {
|
||||||
svgIcons.forEach(icon => {
|
const svgIcon = this.svgIcons.find(icon => {
|
||||||
const ns = icon.namespace || DEFAULT_NS;
|
return namespace
|
||||||
const nsIconMap = this.preloadedSvgElements[ns] || (this.preloadedSvgElements[ns] = {});
|
? icon.name === iconName && icon.namespace === namespace
|
||||||
|
: icon.name === iconName;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!svgIcon) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ns = svgIcon.namespace || DEFAULT_NS;
|
||||||
|
const nsIconMap = this.cachedSvgElements[ns] || (this.cachedSvgElements[ns] = {});
|
||||||
|
|
||||||
// Creating a new `<div>` per icon is necessary for the SVGs to work correctly in IE11.
|
// Creating a new `<div>` per icon is necessary for the SVGs to work correctly in IE11.
|
||||||
const div = document.createElement('DIV');
|
const div = document.createElement('DIV');
|
||||||
|
|
||||||
// SECURITY: the source for the SVG icons is provided in code by trusted developers
|
// SECURITY: the source for the SVG icons is provided in code by trusted developers
|
||||||
div.innerHTML = icon.svgSource;
|
div.innerHTML = svgIcon.svgSource;
|
||||||
|
|
||||||
nsIconMap[icon.name] = div.querySelector('svg')!;
|
const svgElement = div.querySelector('svg')!;
|
||||||
});
|
nsIconMap[svgIcon.name] = svgElement;
|
||||||
|
|
||||||
|
return svgElement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue