@@ -16,7 +16,7 @@ import {
16
16
SecurityContext ,
17
17
SkipSelf ,
18
18
} from '@angular/core' ;
19
- import { DomSanitizer , SafeResourceUrl } from '@angular/platform-browser' ;
19
+ import { DomSanitizer , SafeResourceUrl , SafeHtml } from '@angular/platform-browser' ;
20
20
import { forkJoin , Observable , of as observableOf , throwError as observableThrow } from 'rxjs' ;
21
21
import { catchError , finalize , map , share , tap } from 'rxjs/operators' ;
22
22
@@ -48,18 +48,34 @@ export function getMatIconNoHttpProviderError(): Error {
48
48
* @param url URL that was attempted to be sanitized.
49
49
* @docs -private
50
50
*/
51
- export function getMatIconFailedToSanitizeError ( url : SafeResourceUrl ) : Error {
51
+ export function getMatIconFailedToSanitizeUrlError ( url : SafeResourceUrl ) : Error {
52
52
return Error ( `The URL provided to MatIconRegistry was not trusted as a resource URL ` +
53
53
`via Angular's DomSanitizer. Attempted URL was "${ url } ".` ) ;
54
54
}
55
55
56
+ export function getMatIconFailedToSanitizeTemplateError ( template : SafeHtml ) : Error {
57
+ return Error ( `The template provided to MatIconRegistry was not trusted as safe HTML by ` +
58
+ `Angular's DomSanitizer. Attempted template was "${ template } ".` ) ;
59
+ }
60
+
61
+
56
62
/**
57
63
* Configuration for an icon, including the URL and possibly the cached SVG element.
58
64
* @docs -private
59
65
*/
60
66
class SvgIconConfig {
61
- svgElement : SVGElement | null = null ;
62
- constructor ( public url : SafeResourceUrl ) { }
67
+ url : SafeResourceUrl | null ;
68
+ svgElement : SVGElement | null ;
69
+
70
+ constructor ( url : SafeResourceUrl ) ;
71
+ constructor ( svgElement : SVGElement ) ;
72
+ constructor ( data : SafeResourceUrl | SVGElement ) {
73
+ if ( data instanceof SVGElement ) {
74
+ this . svgElement = data ;
75
+ } else {
76
+ this . url = data ;
77
+ }
78
+ }
63
79
}
64
80
65
81
/**
@@ -116,16 +132,40 @@ export class MatIconRegistry {
116
132
return this . addSvgIconInNamespace ( '' , iconName , url ) ;
117
133
}
118
134
135
+ /**
136
+ * Registers an icon using an HTML string in the default namespace.
137
+ * @param iconName Name under which the icon should be registered.
138
+ * @param template SVG source of the icon.
139
+ */
140
+ addSvgIconTemplate ( iconName : string , template : SafeHtml ) : this {
141
+ return this . addSvgIconTemplateInNamespace ( '' , iconName , template ) ;
142
+ }
143
+
119
144
/**
120
145
* Registers an icon by URL in the specified namespace.
121
146
* @param namespace Namespace in which the icon should be registered.
122
147
* @param iconName Name under which the icon should be registered.
123
148
* @param url
124
149
*/
125
150
addSvgIconInNamespace ( namespace : string , iconName : string , url : SafeResourceUrl ) : this {
126
- const key = iconKey ( namespace , iconName ) ;
127
- this . _svgIconConfigs . set ( key , new SvgIconConfig ( url ) ) ;
128
- return this ;
151
+ return this . _addSvgIconConfig ( namespace , iconName , new SvgIconConfig ( url ) ) ;
152
+ }
153
+
154
+ /**
155
+ * Registers an icon using an HTML string in the specified namespace.
156
+ * @param namespace Namespace in which the icon should be registered.
157
+ * @param iconName Name under which the icon should be registered.
158
+ * @param template SVG source of the icon.
159
+ */
160
+ addSvgIconTemplateInNamespace ( namespace : string , iconName : string , template : SafeHtml ) : this {
161
+ const sanitizedTemplate = this . _sanitizer . sanitize ( SecurityContext . HTML , template ) ;
162
+
163
+ if ( ! sanitizedTemplate ) {
164
+ throw getMatIconFailedToSanitizeTemplateError ( template ) ;
165
+ }
166
+
167
+ const svgElement = this . _createSvgElementForSingleIcon ( sanitizedTemplate ) ;
168
+ return this . _addSvgIconConfig ( namespace , iconName , new SvgIconConfig ( svgElement ) ) ;
129
169
}
130
170
131
171
/**
@@ -136,21 +176,37 @@ export class MatIconRegistry {
136
176
return this . addSvgIconSetInNamespace ( '' , url ) ;
137
177
}
138
178
179
+ /**
180
+ * Registers an icon set using an HTML string in the default namespace.
181
+ * @param template SVG source of the icon set.
182
+ */
183
+ addSvgIconSetTemplate ( template : SafeHtml ) : this {
184
+ return this . addSvgIconSetTemplateInNamespace ( '' , template ) ;
185
+ }
186
+
139
187
/**
140
188
* Registers an icon set by URL in the specified namespace.
141
189
* @param namespace Namespace in which to register the icon set.
142
190
* @param url
143
191
*/
144
192
addSvgIconSetInNamespace ( namespace : string , url : SafeResourceUrl ) : this {
145
- const config = new SvgIconConfig ( url ) ;
146
- const configNamespace = this . _iconSetConfigs . get ( namespace ) ;
193
+ return this . _addSvgIconSetConfig ( namespace , new SvgIconConfig ( url ) ) ;
194
+ }
147
195
148
- if ( configNamespace ) {
149
- configNamespace . push ( config ) ;
150
- } else {
151
- this . _iconSetConfigs . set ( namespace , [ config ] ) ;
196
+ /**
197
+ * Registers an icon set using an HTML string in the specified namespace.
198
+ * @param namespace Namespace in which to register the icon set.
199
+ * @param template SVG source of the icon set.
200
+ */
201
+ addSvgIconSetTemplateInNamespace ( namespace : string , template : SafeHtml ) : this {
202
+ const sanitizedTemplate = this . _sanitizer . sanitize ( SecurityContext . HTML , template ) ;
203
+
204
+ if ( ! sanitizedTemplate ) {
205
+ throw getMatIconFailedToSanitizeTemplateError ( template ) ;
152
206
}
153
- return this ;
207
+
208
+ const svgElement = this . _svgElementFromString ( sanitizedTemplate ) ;
209
+ return this . _addSvgIconSetConfig ( namespace , new SvgIconConfig ( svgElement ) ) ;
154
210
}
155
211
156
212
/**
@@ -202,13 +258,13 @@ export class MatIconRegistry {
202
258
* @param safeUrl URL from which to fetch the SVG icon.
203
259
*/
204
260
getSvgIconFromUrl ( safeUrl : SafeResourceUrl ) : Observable < SVGElement > {
205
- let url = this . _sanitizer . sanitize ( SecurityContext . RESOURCE_URL , safeUrl ) ;
261
+ const url = this . _sanitizer . sanitize ( SecurityContext . RESOURCE_URL , safeUrl ) ;
206
262
207
263
if ( ! url ) {
208
- throw getMatIconFailedToSanitizeError ( safeUrl ) ;
264
+ throw getMatIconFailedToSanitizeUrlError ( safeUrl ) ;
209
265
}
210
266
211
- let cachedIcon = this . _cachedIconsByUrl . get ( url ) ;
267
+ const cachedIcon = this . _cachedIconsByUrl . get ( url ) ;
212
268
213
269
if ( cachedIcon ) {
214
270
return observableOf ( cloneSvg ( cachedIcon ) ) ;
@@ -461,15 +517,19 @@ export class MatIconRegistry {
461
517
* Returns an Observable which produces the string contents of the given URL. Results may be
462
518
* cached, so future calls with the same URL may not cause another HTTP request.
463
519
*/
464
- private _fetchUrl ( safeUrl : SafeResourceUrl ) : Observable < string > {
520
+ private _fetchUrl ( safeUrl : SafeResourceUrl | null ) : Observable < string > {
465
521
if ( ! this . _httpClient ) {
466
522
throw getMatIconNoHttpProviderError ( ) ;
467
523
}
468
524
525
+ if ( safeUrl == null ) {
526
+ throw Error ( `Cannot fetch icon from URL "${ safeUrl } ".` ) ;
527
+ }
528
+
469
529
const url = this . _sanitizer . sanitize ( SecurityContext . RESOURCE_URL , safeUrl ) ;
470
530
471
531
if ( ! url ) {
472
- throw getMatIconFailedToSanitizeError ( safeUrl ) ;
532
+ throw getMatIconFailedToSanitizeUrlError ( safeUrl ) ;
473
533
}
474
534
475
535
// Store in-progress fetches to avoid sending a duplicate request for a URL when there is
@@ -491,6 +551,34 @@ export class MatIconRegistry {
491
551
this . _inProgressUrlFetches . set ( url , req ) ;
492
552
return req ;
493
553
}
554
+
555
+ /**
556
+ * Registers an icon config by name in the specified namespace.
557
+ * @param namespace Namespace in which to register the icon config.
558
+ * @param iconName Name under which to register the config.
559
+ * @param config Config to be registered.
560
+ */
561
+ private _addSvgIconConfig ( namespace : string , iconName : string , config : SvgIconConfig ) : this {
562
+ this . _svgIconConfigs . set ( iconKey ( namespace , iconName ) , config ) ;
563
+ return this ;
564
+ }
565
+
566
+ /**
567
+ * Registers an icon set config in the specified namespace.
568
+ * @param namespace Namespace in which to register the icon config.
569
+ * @param config Config to be registered.
570
+ */
571
+ private _addSvgIconSetConfig ( namespace : string , config : SvgIconConfig ) : this {
572
+ const configNamespace = this . _iconSetConfigs . get ( namespace ) ;
573
+
574
+ if ( configNamespace ) {
575
+ configNamespace . push ( config ) ;
576
+ } else {
577
+ this . _iconSetConfigs . set ( namespace , [ config ] ) ;
578
+ }
579
+
580
+ return this ;
581
+ }
494
582
}
495
583
496
584
/** @docs -private */
0 commit comments