UNPKG

dom-to-svg

Version:
75 lines 4.15 kB
import * as postcss from 'postcss'; import cssValueParser from 'postcss-value-parser'; import { isCSSFontFaceRule, unescapeStringValue } from './css.js'; import { svgNamespace, xlinkNamespace } from './dom.js'; import { createStackingLayers } from './stacking.js'; import { walkNode } from './traversal.js'; import { createIdGenerator } from './util.js'; export function documentToSVG(document, options) { return elementToSVG(document.documentElement, options); } export function elementToSVG(element, options) { var _a, _b, _c, _d; const svgDocument = element.ownerDocument.implementation.createDocument(svgNamespace, 'svg', null); const svgElement = svgDocument.documentElement; svgElement.setAttribute('xmlns', svgNamespace); svgElement.setAttribute('xmlns:xlink', xlinkNamespace); svgElement.append(svgDocument.createComment( // "--" is invalid in comments, percent-encode. ` Generated by dom-to-svg from ${element.ownerDocument.location.href.replace(/--/g, '%2D%2D')} `)); // Copy @font-face rules const styleElement = svgDocument.createElementNS(svgNamespace, 'style'); for (const styleSheet of element.ownerDocument.styleSheets) { try { // Make font URLs absolute (need to be resolved relative to the stylesheet) for (const rule of (_a = styleSheet.rules) !== null && _a !== void 0 ? _a : []) { if (!isCSSFontFaceRule(rule)) { continue; } const styleSheetHref = (_b = rule.parentStyleSheet) === null || _b === void 0 ? void 0 : _b.href; if (styleSheetHref) { // Note: Firefox does not implement rule.style.src, need to use rule.style.getPropertyValue() const parsedSourceValue = cssValueParser(rule.style.getPropertyValue('src')); parsedSourceValue.walk(node => { if (node.type === 'function' && node.value === 'url' && node.nodes[0]) { const urlArgumentNode = node.nodes[0]; if (urlArgumentNode.type === 'string' || urlArgumentNode.type === 'word') { urlArgumentNode.value = new URL(unescapeStringValue(urlArgumentNode.value), styleSheetHref).href; } } }); // Firefox does not support changing `src` on CSSFontFaceRule declarations, need to use PostCSS. const updatedFontFaceRule = postcss.parse(rule.cssText); updatedFontFaceRule.walkDecls('src', declaration => { declaration.value = cssValueParser.stringify(parsedSourceValue.nodes); }); styleElement.append(updatedFontFaceRule.toString() + '\n'); } } } catch (error) { console.error('Error resolving @font-face src URLs for styleSheet, skipping', styleSheet, error); } } svgElement.append(styleElement); walkNode(element, { svgDocument, currentSvgParent: svgElement, stackingLayers: createStackingLayers(svgElement), parentStackingLayer: svgElement, getUniqueId: createIdGenerator(), labels: new Map(), ancestorMasks: [], options: { captureArea: (_c = options === null || options === void 0 ? void 0 : options.captureArea) !== null && _c !== void 0 ? _c : element.getBoundingClientRect(), keepLinks: (options === null || options === void 0 ? void 0 : options.keepLinks) !== false, }, }); const bounds = (_d = options === null || options === void 0 ? void 0 : options.captureArea) !== null && _d !== void 0 ? _d : element.getBoundingClientRect(); svgElement.setAttribute('width', bounds.width.toString()); svgElement.setAttribute('height', bounds.height.toString()); svgElement.setAttribute('viewBox', `${bounds.x} ${bounds.y} ${bounds.width} ${bounds.height}`); return svgDocument; } export { inlineResources } from './inline.js'; //# sourceMappingURL=index.js.map