|
1 | | -import { validateContent } from './validate'; |
| 1 | +import { isEncodedDataUrl, isSvgDataUrl, validateContent } from './validate'; |
2 | 2 |
|
3 | 3 | export const ioniconContent = new Map<string, string>(); |
4 | 4 | const requests = new Map<string, Promise<any>>(); |
5 | 5 |
|
| 6 | +let parser: DOMParser; |
| 7 | + |
6 | 8 | export const getSvgContent = (url: string, sanitize: boolean) => { |
7 | 9 | // see if we already have a request for this url |
8 | 10 | let req = requests.get(url); |
9 | 11 |
|
10 | 12 | if (!req) { |
11 | 13 | if (typeof fetch !== 'undefined' && typeof document !== 'undefined') { |
12 | | - // we don't already have a request |
13 | | - req = fetch(url).then((rsp) => { |
14 | | - if (rsp.ok) { |
15 | | - return rsp.text().then((svgContent) => { |
16 | | - if (svgContent && sanitize !== false) { |
17 | | - svgContent = validateContent(svgContent); |
18 | | - } |
19 | | - ioniconContent.set(url, svgContent || ''); |
20 | | - }); |
| 14 | + /** |
| 15 | + * If the url is a data url of an svg, then try to parse it |
| 16 | + * with the DOMParser. This works with content security policies enabled. |
| 17 | + */ |
| 18 | + if (isSvgDataUrl(url) && isEncodedDataUrl(url)) { |
| 19 | + if (!parser) { |
| 20 | + /** |
| 21 | + * Create an instance of the DOM parser. This creates a single |
| 22 | + * parser instance for the entire app, which is more efficient. |
| 23 | + */ |
| 24 | + parser = new DOMParser(); |
| 25 | + } |
| 26 | + const doc = parser.parseFromString(url, 'text/html'); |
| 27 | + const svg = doc.querySelector('svg'); |
| 28 | + if (svg) { |
| 29 | + ioniconContent.set(url, svg.outerHTML); |
21 | 30 | } |
22 | | - ioniconContent.set(url, ''); |
23 | | - }); |
| 31 | + return Promise.resolve(); |
| 32 | + } else { |
| 33 | + // we don't already have a request |
| 34 | + req = fetch(url).then((rsp) => { |
| 35 | + if (rsp.ok) { |
| 36 | + return rsp.text().then((svgContent) => { |
| 37 | + if (svgContent && sanitize !== false) { |
| 38 | + svgContent = validateContent(svgContent); |
| 39 | + } |
| 40 | + ioniconContent.set(url, svgContent || ''); |
| 41 | + }); |
| 42 | + } |
| 43 | + ioniconContent.set(url, ''); |
| 44 | + }); |
| 45 | + // cache for the same requests |
| 46 | + requests.set(url, req); |
| 47 | + } |
24 | 48 |
|
25 | | - // cache for the same requests |
26 | | - requests.set(url, req); |
27 | 49 | } else { |
28 | 50 | // set to empty for ssr scenarios and resolve promise |
29 | 51 | ioniconContent.set(url, ''); |
|
0 commit comments