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:
Sonu Kapoor 2020-07-28 08:19:35 -04:00 committed by Misko Hevery
parent b280d54470
commit 1b17722091
1 changed files with 30 additions and 17 deletions

View File

@ -39,35 +39,48 @@ const DEFAULT_NS = '$$default';
*/
@Injectable()
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,
errorHandler: ErrorHandler, @Inject(SVG_ICONS) svgIcons: SvgIconInfo[]) {
errorHandler: ErrorHandler, @Inject(SVG_ICONS) private svgIcons: SvgIconInfo[]) {
super(http, sanitizer, document, errorHandler);
this.loadSvgElements(svgIcons);
}
getNamedSvgIcon(iconName: string, namespace?: string) {
const nsIconMap = this.preloadedSvgElements[namespace || DEFAULT_NS];
const preloadedElement = nsIconMap && nsIconMap[iconName];
const nsIconMap = this.cachedSvgElements[namespace || DEFAULT_NS];
let preloadedElement: SVGElement | undefined = nsIconMap && nsIconMap[iconName];
if (!preloadedElement) {
preloadedElement = this.loadSvgElement(iconName, namespace);
}
return preloadedElement
? of(preloadedElement.cloneNode(true) as SVGElement)
: super.getNamedSvgIcon(iconName, namespace);
}
private loadSvgElements(svgIcons: SvgIconInfo[]) {
svgIcons.forEach(icon => {
const ns = icon.namespace || DEFAULT_NS;
const nsIconMap = this.preloadedSvgElements[ns] || (this.preloadedSvgElements[ns] = {});
private loadSvgElement(iconName: string, namespace?: string): SVGElement | undefined {
const svgIcon = this.svgIcons.find(icon => {
return namespace
? 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.
const div = document.createElement('DIV');
// 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;
}
}