import { Injectable , Optional } from '@angular/core' ; import { HttpClient } from '@angular/common/http' ; import { of , Observable } from 'rxjs' ; import { catchError , finalize , map , share } from 'rxjs/operators' ; import { SvgViewerConfig } from './svg-viewer.config' ; dynamic @ Injectable ( ) export class SvgViewerService { private static cache : Map < string , SVGElement > ; private static inProgressReqs : Map < string , Observable < SVGElement > > ; private static baseUrl : string ; constructor ( @ Optional ( ) config , private http ) { if ( config && ! SvgViewerService . baseUrl ) { this . setBaseUrl ( config ) ; } if ( ! SvgViewerService . cache ) { SvgViewerService . cache = new Map < string , SVGElement > ( ) ; } if ( ! SvgViewerService . inProgressReqs ) { SvgViewerService . inProgressReqs = new Map < string , Observable < SVGElement > > ( ) ; } } getSVG ( url , cache = true ) { const absUrl = this . getAbsoluteUrl ( url ) ; if ( cache && SvgViewerService . cache . has ( absUrl ) ) { return of ( this . cloneSVG ( SvgViewerService . cache . get ( absUrl ) ) ) ; } if ( SvgViewerService . inProgressReqs . has ( absUrl ) ) { return SvgViewerService . inProgressReqs . get ( absUrl ) ; } const req = this . http . get ( absUrl , { responseType : 'text' } ) . pipe ( catchError ( ( err ) => err ) , finalize ( ( ) => SvgViewerService . inProgressReqs . delete ( absUrl ) ) , share ( ) , map ( ( svgText ) => { const svgEl = this . svgElementFromString ( svgText ) ; SvgViewerService . cache . set ( absUrl , svgEl ) ; return this . cloneSVG ( svgEl ) ; } ) ) ; SvgViewerService . inProgressReqs . set ( absUrl , req ) ; return req ; } setBaseUrl ( config ) { if ( config ) { SvgViewerService . baseUrl = config . baseUrl ; } } getAbsoluteUrl ( url ) { if ( SvgViewerService . baseUrl && ! /^https?:\/\//i . test ( url ) ) { url = SvgViewerService . baseUrl + url . slice ( url . indexOf ( 'assets/' ) ) ; if ( url . indexOf ( '//' ) === 0 ) { url = url . substring ( 1 ) ; } } return url ; } private svgElementFromString ( str ) { const div = document . createElement ( 'DIV' ) ; div . innerHTML = str ; const svg = div . querySelector ( 'svg' ) as SVGElement ; if ( ! svg ) { throw new Error ( 'No SVG found in loaded contents' ) ; } return svg ; } private cloneSVG ( svg ) { return svg . cloneNode ( true ) as SVGElement ; } }