ionicons
Version:
Premium icons for Ionic.
79 lines (78 loc) • 2.34 kB
JavaScript
import { isEncodedDataUrl, isSvgDataUrl, validateContent } from "./validate";
export const ioniconContent = new Map();
const requests = new Map();
let parser;
/**
* Safely fallback to an empty svg
*/
function safeFallback(url) {
const svg = '';
ioniconContent.set(url, svg);
return svg;
}
export const getSvgContent = (url, sanitize) => {
/**
* See if we already have a request for this url
*/
const req = requests.get(url);
if (req) {
return req;
}
if (typeof fetch !== 'undefined' && typeof document !== 'undefined') {
/**
* If the url is a data url of an svg, then try to parse it
* with the DOMParser. This works with content security policies enabled.
*/
if (isSvgDataUrl(url) && isEncodedDataUrl(url)) {
return Promise.resolve(getSvgByUrl(url));
}
return fetchSvg(url, sanitize);
}
return Promise.resolve(safeFallback(url));
};
function getSvgByUrl(url) {
if (!parser) {
/**
* Create an instance of the DOM parser. This creates a single
* parser instance for the entire app, which is more efficient.
*/
parser = new DOMParser();
}
const doc = parser.parseFromString(url, 'text/html');
const svg = doc.querySelector('svg');
if (svg) {
ioniconContent.set(url, svg.outerHTML);
return svg.outerHTML;
}
throw new Error(`Could not parse svg from ${url}`);
}
function fetchSvg(url, sanitize) {
/**
* We don't already have a request
*/
const req = fetch(url)
.then((rsp) => {
/**
* When fetching from a file:// URL, some browsers return
* a 0 status code even when the request succeeds so don't
* rely on rsp.ok as the only signal of success.
*/
return rsp
.text()
.then((svgContent) => {
if (svgContent && sanitize !== false) {
svgContent = validateContent(svgContent);
}
const svg = svgContent || '';
ioniconContent.set(url, svg);
return svg;
})
.catch(() => safeFallback(url));
})
.catch(() => safeFallback(url));
/**
* Cache for the same requests
*/
requests.set(url, req);
return req;
}