@pixldocs/canvas-renderer 0.5.129 → 0.5.131
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{index-Cnc7FwzD.cjs → index-Cc5u_TJx.cjs} +15 -6
- package/dist/index-Cc5u_TJx.cjs.map +1 -0
- package/dist/{index-BinoVoB5.js → index-ft7TuZPu.js} +15 -6
- package/dist/index-ft7TuZPu.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/{svgTextToPath-n7TTV6Xv.js → svgTextToPath-DMx9Buca.js} +17 -1
- package/dist/svgTextToPath-DMx9Buca.js.map +1 -0
- package/dist/{svgTextToPath-1WbtFu9C.cjs → svgTextToPath-DcI_oipn.cjs} +17 -1
- package/dist/svgTextToPath-DcI_oipn.cjs.map +1 -0
- package/dist/{vectorPdfExport-DrXSoUpy.js → vectorPdfExport-C96oIwLP.js} +141 -6
- package/dist/vectorPdfExport-C96oIwLP.js.map +1 -0
- package/dist/{vectorPdfExport-Dsh0IaH2.cjs → vectorPdfExport-CA5X2N63.cjs} +141 -6
- package/dist/vectorPdfExport-CA5X2N63.cjs.map +1 -0
- package/package.json +1 -1
- package/dist/index-BinoVoB5.js.map +0 -1
- package/dist/index-Cnc7FwzD.cjs.map +0 -1
- package/dist/svgTextToPath-1WbtFu9C.cjs.map +0 -1
- package/dist/svgTextToPath-n7TTV6Xv.js.map +0 -1
- package/dist/vectorPdfExport-DrXSoUpy.js.map +0 -1
- package/dist/vectorPdfExport-Dsh0IaH2.cjs.map +0 -1
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
const jspdf = require("jspdf");
|
|
4
4
|
const svg2pdf_js = require("svg2pdf.js");
|
|
5
5
|
const fabric = require("fabric");
|
|
6
|
-
const index = require("./index-
|
|
6
|
+
const index = require("./index-Cc5u_TJx.cjs");
|
|
7
7
|
const pdfFonts = require("./pdfFonts-Cr8l-y3z.cjs");
|
|
8
8
|
function _interopNamespaceDefault(e) {
|
|
9
9
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
@@ -1097,6 +1097,112 @@ function stripSuspiciousFullPageOverlayNodes(svg) {
|
|
|
1097
1097
|
}
|
|
1098
1098
|
}
|
|
1099
1099
|
async function convertTextDecorationsToLines(svg) {
|
|
1100
|
+
return _convertTextDecorationsToLines_impl(svg);
|
|
1101
|
+
}
|
|
1102
|
+
async function bakeTextAnchorPositionsFromLiveSvg(svg) {
|
|
1103
|
+
var _a;
|
|
1104
|
+
if (typeof document === "undefined" || typeof window === "undefined") return;
|
|
1105
|
+
if (!svg) return;
|
|
1106
|
+
const _resolveAnchor = (el) => {
|
|
1107
|
+
let cur = el;
|
|
1108
|
+
while (cur) {
|
|
1109
|
+
const a = cur.getAttribute("text-anchor");
|
|
1110
|
+
if (a) return a.trim().toLowerCase();
|
|
1111
|
+
const style = cur.getAttribute("style") || "";
|
|
1112
|
+
const m = style.match(/(?:^|;)\s*text-anchor\s*:\s*([^;]+)/i);
|
|
1113
|
+
if (m) return m[1].trim().toLowerCase();
|
|
1114
|
+
cur = cur.parentElement;
|
|
1115
|
+
}
|
|
1116
|
+
return "start";
|
|
1117
|
+
};
|
|
1118
|
+
const allTextish = Array.from(svg.querySelectorAll("text, tspan"));
|
|
1119
|
+
let needsBake = false;
|
|
1120
|
+
for (const el of allTextish) {
|
|
1121
|
+
const a = _resolveAnchor(el);
|
|
1122
|
+
if (a === "middle" || a === "end") {
|
|
1123
|
+
needsBake = true;
|
|
1124
|
+
break;
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
if (!needsBake) return;
|
|
1128
|
+
try {
|
|
1129
|
+
if ((_a = document.fonts) == null ? void 0 : _a.ready) await document.fonts.ready;
|
|
1130
|
+
} catch {
|
|
1131
|
+
}
|
|
1132
|
+
const tempContainer = document.createElement("div");
|
|
1133
|
+
tempContainer.style.cssText = "position:fixed;left:-9999px;top:-9999px;visibility:hidden;pointer-events:none;";
|
|
1134
|
+
const clone = svg.cloneNode(true);
|
|
1135
|
+
for (const tn of clone.querySelectorAll("text, tspan, textPath")) {
|
|
1136
|
+
const sf = tn.getAttribute("data-source-font-family");
|
|
1137
|
+
const sw = tn.getAttribute("data-source-font-weight");
|
|
1138
|
+
const ss = tn.getAttribute("data-source-font-style");
|
|
1139
|
+
if (sf) tn.setAttribute("font-family", sf);
|
|
1140
|
+
if (sw) tn.setAttribute("font-weight", sw);
|
|
1141
|
+
if (ss) tn.setAttribute("font-style", ss);
|
|
1142
|
+
const inlineStyle = tn.getAttribute("style") || "";
|
|
1143
|
+
if (sf || sw || ss) {
|
|
1144
|
+
const stylePairs = inlineStyle.split(";").map((p) => p.trim()).filter(Boolean).filter((p) => !/^font-(family|weight|style)\s*:/i.test(p));
|
|
1145
|
+
if (sf) stylePairs.push(`font-family: ${sf}`);
|
|
1146
|
+
if (sw) stylePairs.push(`font-weight: ${sw}`);
|
|
1147
|
+
if (ss) stylePairs.push(`font-style: ${ss}`);
|
|
1148
|
+
if (stylePairs.length > 0) tn.setAttribute("style", stylePairs.join("; "));
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
tempContainer.appendChild(clone);
|
|
1152
|
+
document.body.appendChild(tempContainer);
|
|
1153
|
+
let baked = 0;
|
|
1154
|
+
try {
|
|
1155
|
+
const srcTexts = Array.from(svg.querySelectorAll("text"));
|
|
1156
|
+
const liveTexts = Array.from(clone.querySelectorAll("text"));
|
|
1157
|
+
for (let i = 0; i < srcTexts.length; i++) {
|
|
1158
|
+
const srcText = srcTexts[i];
|
|
1159
|
+
const liveText = liveTexts[i];
|
|
1160
|
+
if (!liveText) continue;
|
|
1161
|
+
const srcTspans = Array.from(srcText.querySelectorAll("tspan"));
|
|
1162
|
+
const liveTspans = Array.from(liveText.querySelectorAll("tspan"));
|
|
1163
|
+
const bakeNode = (srcNode, liveNode, isTspan) => {
|
|
1164
|
+
const anchor = _resolveAnchor(srcNode);
|
|
1165
|
+
if (anchor !== "middle" && anchor !== "end") return;
|
|
1166
|
+
try {
|
|
1167
|
+
const n = typeof liveNode.getNumberOfChars === "function" ? liveNode.getNumberOfChars() : 0;
|
|
1168
|
+
if (!n) return;
|
|
1169
|
+
const start = liveNode.getStartPositionOfChar(0);
|
|
1170
|
+
if (!Number.isFinite(start == null ? void 0 : start.x)) return;
|
|
1171
|
+
srcNode.setAttribute("x", String(start.x));
|
|
1172
|
+
srcNode.setAttribute("text-anchor", "start");
|
|
1173
|
+
const style = srcNode.getAttribute("style") || "";
|
|
1174
|
+
if (/text-anchor\s*:/i.test(style)) {
|
|
1175
|
+
const cleaned = style.split(";").map((p) => p.trim()).filter(Boolean).filter((p) => !/^text-anchor\s*:/i.test(p)).join("; ");
|
|
1176
|
+
if (cleaned) srcNode.setAttribute("style", cleaned);
|
|
1177
|
+
else srcNode.removeAttribute("style");
|
|
1178
|
+
}
|
|
1179
|
+
baked++;
|
|
1180
|
+
} catch {
|
|
1181
|
+
}
|
|
1182
|
+
};
|
|
1183
|
+
if (srcTspans.length > 0) {
|
|
1184
|
+
bakeNode(srcText, liveText, false);
|
|
1185
|
+
for (let j = 0; j < srcTspans.length; j++) {
|
|
1186
|
+
if (liveTspans[j]) bakeNode(srcTspans[j], liveTspans[j], true);
|
|
1187
|
+
}
|
|
1188
|
+
} else {
|
|
1189
|
+
bakeNode(srcText, liveText, false);
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
} finally {
|
|
1193
|
+
try {
|
|
1194
|
+
document.body.removeChild(tempContainer);
|
|
1195
|
+
} catch {
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
if (baked > 0) {
|
|
1199
|
+
try {
|
|
1200
|
+
console.log(`[Vector PDF][parity] baked text-anchor → start on ${baked} node(s) using live canvas measurement`);
|
|
1201
|
+
} catch {
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
async function _convertTextDecorationsToLines_impl(svg) {
|
|
1100
1206
|
const doc = svg.ownerDocument;
|
|
1101
1207
|
if (!doc) return;
|
|
1102
1208
|
const resolveInheritedSvgValue = (el, attr, styleProp = attr) => {
|
|
@@ -1514,7 +1620,7 @@ async function collectInlinedFontFaceCss() {
|
|
|
1514
1620
|
return cachedInlinedFontFaceCss;
|
|
1515
1621
|
}
|
|
1516
1622
|
async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey, options) {
|
|
1517
|
-
var _a;
|
|
1623
|
+
var _a, _b;
|
|
1518
1624
|
try {
|
|
1519
1625
|
const parser = new DOMParser();
|
|
1520
1626
|
const processedSvg = inlineNestedSvgImageDataUris(rawSvg, parser);
|
|
@@ -1545,11 +1651,39 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
|
|
|
1545
1651
|
stripRootPageBackgroundFromSvg(svgToDraw);
|
|
1546
1652
|
}
|
|
1547
1653
|
sanitizeSvgTreeForPdf(svgToDraw);
|
|
1654
|
+
try {
|
|
1655
|
+
await bakeTextAnchorPositionsFromLiveSvg(svgToDraw);
|
|
1656
|
+
} catch (e) {
|
|
1657
|
+
console.warn("[Vector PDF] anchor-bake pass failed (continuing):", e);
|
|
1658
|
+
}
|
|
1659
|
+
try {
|
|
1660
|
+
const hasShadowText = !!svgToDraw.querySelector("[data-pd-shadow-blur]") || !!svgToDraw.querySelector("g.__pdShadowRaster text");
|
|
1661
|
+
if (hasShadowText) {
|
|
1662
|
+
const { convertAllTextToPath } = await Promise.resolve().then(() => require("./svgTextToPath-DcI_oipn.cjs"));
|
|
1663
|
+
const serialized = new XMLSerializer().serializeToString(svgToDraw);
|
|
1664
|
+
const outlined = await convertAllTextToPath(serialized, void 0, { mode: "shadow-bound" });
|
|
1665
|
+
const reparsed = parser.parseFromString(outlined, "image/svg+xml");
|
|
1666
|
+
if (!reparsed.querySelector("parsererror") && ((_a = reparsed.documentElement) == null ? void 0 : _a.tagName.toLowerCase()) === "svg") {
|
|
1667
|
+
while (svgToDraw.firstChild) svgToDraw.removeChild(svgToDraw.firstChild);
|
|
1668
|
+
for (const child of Array.from(reparsed.documentElement.childNodes)) {
|
|
1669
|
+
svgToDraw.appendChild(svgToDraw.ownerDocument.importNode(child, true));
|
|
1670
|
+
}
|
|
1671
|
+
for (const attr of Array.from(reparsed.documentElement.attributes)) {
|
|
1672
|
+
try {
|
|
1673
|
+
svgToDraw.setAttribute(attr.name, attr.value);
|
|
1674
|
+
} catch {
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
} catch (e) {
|
|
1680
|
+
console.warn("[Vector PDF] shadow-bound text outlining failed (continuing without parity outlining):", e);
|
|
1681
|
+
}
|
|
1548
1682
|
await rasterizeShadowMarkers(svgToDraw);
|
|
1549
1683
|
await convertTextDecorationsToLines(svgToDraw);
|
|
1550
1684
|
const rewritten = rewriteSvgFontsForJsPDFWithSourceMeta(new XMLSerializer().serializeToString(svgToDraw));
|
|
1551
1685
|
const rewrittenDoc = parser.parseFromString(rewritten, "image/svg+xml");
|
|
1552
|
-
if (!rewrittenDoc.querySelector("parsererror") && ((
|
|
1686
|
+
if (!rewrittenDoc.querySelector("parsererror") && ((_b = rewrittenDoc.documentElement) == null ? void 0 : _b.tagName.toLowerCase()) === "svg") {
|
|
1553
1687
|
return rewrittenDoc.documentElement;
|
|
1554
1688
|
}
|
|
1555
1689
|
return svgToDraw;
|
|
@@ -2131,7 +2265,7 @@ async function fetchSvgAsElement(imageUrl, colorMap) {
|
|
|
2131
2265
|
async function getRecoloredSvgDataUrl(imageUrl, colorMap) {
|
|
2132
2266
|
if (!colorMap || Object.keys(colorMap).length === 0) return null;
|
|
2133
2267
|
try {
|
|
2134
|
-
const { getNormalizedSvgUrl } = await Promise.resolve().then(() => require("./index-
|
|
2268
|
+
const { getNormalizedSvgUrl } = await Promise.resolve().then(() => require("./index-Cc5u_TJx.cjs")).then((n) => n.canvasImageLoader);
|
|
2135
2269
|
return await getNormalizedSvgUrl(imageUrl, colorMap);
|
|
2136
2270
|
} catch {
|
|
2137
2271
|
return null;
|
|
@@ -2912,7 +3046,7 @@ async function fetchImageAsBase64(imageUrl, opts = {}) {
|
|
|
2912
3046
|
}
|
|
2913
3047
|
let fetchUrl = imageUrl;
|
|
2914
3048
|
if (imageUrl.startsWith("http://") || imageUrl.startsWith("https://")) {
|
|
2915
|
-
const { isPrivateUrl } = await Promise.resolve().then(() => require("./index-
|
|
3049
|
+
const { isPrivateUrl } = await Promise.resolve().then(() => require("./index-Cc5u_TJx.cjs")).then((n) => n.canvasImageLoader);
|
|
2916
3050
|
if (isPrivateUrl(imageUrl)) return null;
|
|
2917
3051
|
const proxyUrl = new URL(`${index.API_URL}/image-proxy`);
|
|
2918
3052
|
proxyUrl.searchParams.set("url", imageUrl);
|
|
@@ -4885,6 +5019,7 @@ async function exportMultiPagePdf(pages, options) {
|
|
|
4885
5019
|
}
|
|
4886
5020
|
pdf.save(filename);
|
|
4887
5021
|
}
|
|
5022
|
+
exports.bakeTextAnchorPositionsFromLiveSvg = bakeTextAnchorPositionsFromLiveSvg;
|
|
4888
5023
|
exports.convertSvgTextDecorationsToLinesString = convertSvgTextDecorationsToLinesString;
|
|
4889
5024
|
exports.drawPreparedLiveCanvasSvgPageToPdf = drawPreparedLiveCanvasSvgPageToPdf;
|
|
4890
5025
|
exports.embedFontsForSvg = embedFontsForSvg;
|
|
@@ -4892,4 +5027,4 @@ exports.exportFabricCanvasToVectorPdf = exportFabricCanvasToVectorPdf;
|
|
|
4892
5027
|
exports.exportMultiPagePdf = exportMultiPagePdf;
|
|
4893
5028
|
exports.preparePagesForExport = preparePagesForExport;
|
|
4894
5029
|
exports.rewriteSvgFontsForJsPDFWithSourceMeta = rewriteSvgFontsForJsPDFWithSourceMeta;
|
|
4895
|
-
//# sourceMappingURL=vectorPdfExport-
|
|
5030
|
+
//# sourceMappingURL=vectorPdfExport-CA5X2N63.cjs.map
|