UNPKG

html-to-image

Version:

Generates an image from a DOM node using HTML5 canvas and SVG.

66 lines 2.52 kB
import { resolveUrl } from './util'; import { getMimeType } from './mimes'; import { isDataUrl, makeDataUrl, resourceToDataURL } from './dataurl'; const URL_REGEX = /url\((['"]?)([^'"]+?)\1\)/g; const URL_WITH_FORMAT_REGEX = /url\([^)]+\)\s*format\((["']?)([^"']+)\1\)/g; const FONT_SRC_REGEX = /src:\s*(?:url\([^)]+\)\s*format\([^)]+\)[,;]\s*)+/g; function toRegex(url) { // eslint-disable-next-line no-useless-escape const escaped = url.replace(/([.*+?^${}()|\[\]\/\\])/g, '\\$1'); return new RegExp(`(url\\(['"]?)(${escaped})(['"]?\\))`, 'g'); } export function parseURLs(cssText) { const urls = []; cssText.replace(URL_REGEX, (raw, quotation, url) => { urls.push(url); return raw; }); return urls.filter((url) => !isDataUrl(url)); } export async function embed(cssText, resourceURL, baseURL, options, getContentFromUrl) { try { const resolvedURL = baseURL ? resolveUrl(resourceURL, baseURL) : resourceURL; const contentType = getMimeType(resourceURL); let dataURL; if (getContentFromUrl) { const content = await getContentFromUrl(resolvedURL); dataURL = makeDataUrl(content, contentType); } else { dataURL = await resourceToDataURL(resolvedURL, contentType, options); } return cssText.replace(toRegex(resourceURL), `$1${dataURL}$3`); } catch (error) { // pass } return cssText; } function filterPreferredFontFormat(str, { preferredFontFormat }) { return !preferredFontFormat ? str : str.replace(FONT_SRC_REGEX, (match) => { // eslint-disable-next-line no-constant-condition while (true) { const [src, , format] = URL_WITH_FORMAT_REGEX.exec(match) || []; if (!format) { return ''; } if (format === preferredFontFormat) { return `src: ${src};`; } } }); } export function shouldEmbed(url) { return url.search(URL_REGEX) !== -1; } export async function embedResources(cssText, baseUrl, options) { if (!shouldEmbed(cssText)) { return cssText; } const filteredCSSText = filterPreferredFontFormat(cssText, options); const urls = parseURLs(filteredCSSText); return urls.reduce((deferred, url) => deferred.then((css) => embed(css, url, baseUrl, options)), Promise.resolve(filteredCSSText)); } //# sourceMappingURL=embed-resources.js.map