@polotno/pdf-export 0.1.31 → 0.1.32
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/lib/svg.js +2 -2
- package/lib/text.js +31 -8
- package/lib/utils.js +2 -2
- package/package.json +10 -10
package/lib/svg.js
CHANGED
|
@@ -87,8 +87,8 @@ export async function urlToBase64(url, cache = null) {
|
|
|
87
87
|
}
|
|
88
88
|
const req = await fetchWithTimeout(url);
|
|
89
89
|
let result;
|
|
90
|
-
if (req.
|
|
91
|
-
const buffer = await req.
|
|
90
|
+
if (req.arrayBuffer) {
|
|
91
|
+
const buffer = Buffer.from(await req.arrayBuffer());
|
|
92
92
|
result = `data:image/svg+xml;base64,${buffer.toString('base64')}`;
|
|
93
93
|
}
|
|
94
94
|
else {
|
package/lib/text.js
CHANGED
|
@@ -1083,7 +1083,10 @@ async function renderStandardStroke(doc, element, textLines, yOffset, lineHeight
|
|
|
1083
1083
|
await drawListMarker(doc, element, line, markerXOffset, lineYOffset, fonts, strokeParsedColor.hex, element.opacity, 'stroke', textOptions);
|
|
1084
1084
|
doc.strokeColor(strokeParsedColor.hex, element.opacity);
|
|
1085
1085
|
}
|
|
1086
|
-
|
|
1086
|
+
// Position cursor at line start
|
|
1087
|
+
// Use moveTo to set position directly without corrupting text rendering state
|
|
1088
|
+
doc.x = contentStartX;
|
|
1089
|
+
doc.y = lineYOffset;
|
|
1087
1090
|
const segments = parseHTMLToSegments(line.text, element);
|
|
1088
1091
|
for (let segmentIndex = 0; segmentIndex < segments.length; segmentIndex++) {
|
|
1089
1092
|
const segment = segments[segmentIndex];
|
|
@@ -1091,15 +1094,23 @@ async function renderStandardStroke(doc, element, textLines, yOffset, lineHeight
|
|
|
1091
1094
|
doc.font(fontKey);
|
|
1092
1095
|
doc.fontSize(element.fontSize);
|
|
1093
1096
|
doc.strokeColor(strokeParsedColor.hex, element.opacity);
|
|
1097
|
+
const hasUnderline = segment.underline || textOptions.underline || false;
|
|
1098
|
+
// When underline is enabled, we need lineBreak: true to avoid NaN errors in PDFKit
|
|
1099
|
+
// But we must preserve the width constraint to prevent unwanted text wrapping
|
|
1100
|
+
const effectiveWidth = widthOption !== undefined
|
|
1101
|
+
? widthOption
|
|
1102
|
+
: hasUnderline
|
|
1103
|
+
? element.width
|
|
1104
|
+
: widthOption;
|
|
1094
1105
|
doc.text(segment.text, {
|
|
1095
1106
|
...textOptions,
|
|
1096
|
-
width:
|
|
1107
|
+
width: effectiveWidth,
|
|
1097
1108
|
height: heightOfLine,
|
|
1098
1109
|
continued: segmentIndex !== segments.length - 1,
|
|
1099
1110
|
stroke: true,
|
|
1100
1111
|
fill: false,
|
|
1101
|
-
underline:
|
|
1102
|
-
lineBreak:
|
|
1112
|
+
underline: hasUnderline,
|
|
1113
|
+
lineBreak: hasUnderline, // Workaround for pdfkit bug - enable lineBreak when underline is used
|
|
1103
1114
|
});
|
|
1104
1115
|
}
|
|
1105
1116
|
}
|
|
@@ -1135,7 +1146,9 @@ async function renderTextFill(doc, element, textLines, yOffset, lineHeightPx, te
|
|
|
1135
1146
|
doc.fillColor(baseParsedColor.hex, baseOpacity);
|
|
1136
1147
|
}
|
|
1137
1148
|
// Position cursor at line start
|
|
1138
|
-
|
|
1149
|
+
// Use direct assignment to set position without corrupting text rendering state
|
|
1150
|
+
doc.x = contentStartX;
|
|
1151
|
+
doc.y = lineYOffset;
|
|
1139
1152
|
// Parse line into styled segments
|
|
1140
1153
|
const segments = parseHTMLToSegments(line.text, element);
|
|
1141
1154
|
// Expand tabs in segments while tracking actual width across segments
|
|
@@ -1187,13 +1200,23 @@ async function renderTextFill(doc, element, textLines, yOffset, lineHeightPx, te
|
|
|
1187
1200
|
const segmentOpacity = Math.min(segmentParsedColor.rgba[3] ?? 1, element.opacity, 1);
|
|
1188
1201
|
doc.fillColor(segmentColor, segmentOpacity);
|
|
1189
1202
|
// Render segment text
|
|
1203
|
+
const hasUnderline = segment.underline || textOptions.underline || false;
|
|
1204
|
+
// When underline is enabled, we need lineBreak: true to avoid NaN errors in PDFKit
|
|
1205
|
+
// But we must preserve the width constraint to prevent unwanted text wrapping
|
|
1206
|
+
// For non-justified text, widthOption is undefined, which would remove the width constraint
|
|
1207
|
+
// So we use widthOption when available (for justify), otherwise use element.width for underlines
|
|
1208
|
+
const effectiveWidth = widthOption !== undefined
|
|
1209
|
+
? widthOption
|
|
1210
|
+
: hasUnderline
|
|
1211
|
+
? element.width
|
|
1212
|
+
: widthOption;
|
|
1190
1213
|
doc.text(segment.text, {
|
|
1191
1214
|
...textOptions,
|
|
1192
|
-
width:
|
|
1215
|
+
width: effectiveWidth,
|
|
1193
1216
|
height: heightOfLine,
|
|
1194
1217
|
continued: !isLastSegment,
|
|
1195
|
-
underline:
|
|
1196
|
-
lineBreak:
|
|
1218
|
+
underline: hasUnderline,
|
|
1219
|
+
lineBreak: hasUnderline, // Workaround for pdfkit bug - enable lineBreak when underline is used
|
|
1197
1220
|
stroke: false,
|
|
1198
1221
|
fill: true,
|
|
1199
1222
|
});
|
package/lib/utils.js
CHANGED
|
@@ -62,7 +62,7 @@ export async function loadImage(src, cache = null) {
|
|
|
62
62
|
else {
|
|
63
63
|
try {
|
|
64
64
|
const response = await fetchWithTimeout(src);
|
|
65
|
-
buffer = await response.
|
|
65
|
+
buffer = Buffer.from(await response.arrayBuffer());
|
|
66
66
|
const { fileTypeFromBuffer } = await import('file-type');
|
|
67
67
|
const typeData = await fileTypeFromBuffer(buffer);
|
|
68
68
|
if (typeData) {
|
|
@@ -99,7 +99,7 @@ export async function srcToBase64(src, cache = null) {
|
|
|
99
99
|
}
|
|
100
100
|
else {
|
|
101
101
|
const res = await fetchWithTimeout(src);
|
|
102
|
-
const data = await res.
|
|
102
|
+
const data = Buffer.from(await res.arrayBuffer());
|
|
103
103
|
base64 = data.toString('base64');
|
|
104
104
|
}
|
|
105
105
|
// Store in cache
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@polotno/pdf-export",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.32",
|
|
4
4
|
"description": "Convert Polotno JSON into vector PDF",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -28,15 +28,15 @@
|
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"canvas": "^3.2.0",
|
|
31
|
-
"file-type": "^21.
|
|
31
|
+
"file-type": "^21.1.0",
|
|
32
32
|
"get-urls": "^12.1.0",
|
|
33
|
-
"konva": "^10.0.
|
|
33
|
+
"konva": "^10.0.9",
|
|
34
34
|
"node-fetch": "^3.3.2",
|
|
35
35
|
"parse-color": "^1.0.0",
|
|
36
36
|
"pdf2pic": "^3.2.0",
|
|
37
37
|
"pdfkit": "^0.17.2",
|
|
38
|
-
"polotno": "^2.
|
|
39
|
-
"sharp": "^0.34.
|
|
38
|
+
"polotno": "^2.32.4",
|
|
39
|
+
"sharp": "^0.34.5",
|
|
40
40
|
"string-strip-html": "^13.5.0",
|
|
41
41
|
"svg-to-pdfkit": "^0.1.8",
|
|
42
42
|
"xmldom": "^0.6.0",
|
|
@@ -45,18 +45,18 @@
|
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/react": "18.3.12",
|
|
47
47
|
"@types/react-dom": "18.3.2",
|
|
48
|
-
"@types/node": "^24.10.
|
|
48
|
+
"@types/node": "^24.10.1",
|
|
49
49
|
"@types/parse-color": "^1.0.3",
|
|
50
50
|
"@types/pdfkit": "^0.17.3",
|
|
51
51
|
"jest-image-snapshot": "^6.5.1",
|
|
52
52
|
"pdf-img-convert": "^2.0.0",
|
|
53
|
-
"pdf-to-png-converter": "^3.
|
|
53
|
+
"pdf-to-png-converter": "^3.11.0",
|
|
54
54
|
"pixelmatch": "^7.1.0",
|
|
55
55
|
"pngjs": "^7.0.0",
|
|
56
56
|
"polotno-node": "^2.12.30",
|
|
57
57
|
"typescript": "~5.9.3",
|
|
58
|
-
"@vitejs/plugin-react": "^5.1.
|
|
59
|
-
"vite": "^7.2.
|
|
60
|
-
"vitest": "^4.0.
|
|
58
|
+
"@vitejs/plugin-react": "^5.1.1",
|
|
59
|
+
"vite": "^7.2.2",
|
|
60
|
+
"vitest": "^4.0.10"
|
|
61
61
|
}
|
|
62
62
|
}
|