53 lines
1.6 KiB
JavaScript
53 lines
1.6 KiB
JavaScript
const ICONIFY_SELECTOR = '[class*="iconify"]';
|
|
|
|
/**
|
|
* Replaces iconify CSS-mask spans with real <svg> (for html2pdf, html2canvas),
|
|
* returns a restore function to swap them back.
|
|
*/
|
|
export function swapIconsForExport(root) {
|
|
const spans = root.querySelectorAll(ICONIFY_SELECTOR);
|
|
const restoreList = [];
|
|
|
|
spans.forEach((span) => {
|
|
const svgMarkup = extractSvgFromMask(span);
|
|
if (!svgMarkup) return; // not a mask-based icon, skip
|
|
|
|
const computed = getComputedStyle(span);
|
|
const size = computed.fontSize || "1em";
|
|
const color = computed.color;
|
|
|
|
const wrapper = document.createElement("span");
|
|
wrapper.innerHTML = svgMarkup;
|
|
const svgEl = wrapper.firstElementChild;
|
|
|
|
svgEl.setAttribute("width", size);
|
|
svgEl.setAttribute("height", size);
|
|
svgEl.style.display = "inline-block";
|
|
svgEl.style.verticalAlign = "middle";
|
|
// force fill to currentColor's resolved value
|
|
svgEl.querySelectorAll("[fill]").forEach((node) => node.setAttribute("fill", color));
|
|
|
|
span.replaceWith(svgEl);
|
|
restoreList.push({ svgEl, originalSpan: span });
|
|
});
|
|
|
|
return function restoreIcons() {
|
|
restoreList.forEach(({ svgEl, originalSpan }) => {
|
|
svgEl.replaceWith(originalSpan);
|
|
});
|
|
};
|
|
}
|
|
|
|
function extractSvgFromMask(el) {
|
|
const maskVar = getComputedStyle(el).getPropertyValue("--svg").trim();
|
|
// maskVar looks like: url("data:image/svg+xml,...")
|
|
const match = maskVar.match(/url\((['"]?)(.*?)\1\)/);
|
|
if (!match) return null;
|
|
|
|
const dataUri = match[2];
|
|
if (!dataUri.startsWith("data:image/svg+xml,")) return null;
|
|
|
|
const encoded = dataUri.replace("data:image/svg+xml,", "");
|
|
return decodeURIComponent(encoded);
|
|
}
|