@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 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.buffer) {
91
- const buffer = await req.buffer();
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
- doc.text('', contentStartX, lineYOffset, { height: 0, width: 0 });
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: widthOption,
1107
+ width: effectiveWidth,
1097
1108
  height: heightOfLine,
1098
1109
  continued: segmentIndex !== segments.length - 1,
1099
1110
  stroke: true,
1100
1111
  fill: false,
1101
- underline: segment.underline || textOptions.underline || false,
1102
- lineBreak: !!segment.underline,
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
- doc.text('', contentStartX, lineYOffset, { height: 0, width: 0 });
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: widthOption,
1215
+ width: effectiveWidth,
1193
1216
  height: heightOfLine,
1194
1217
  continued: !isLastSegment,
1195
- underline: segment.underline || textOptions.underline || false,
1196
- lineBreak: !!segment.underline, // Workaround for pdfkit bug
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.buffer();
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.buffer();
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.31",
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.0.0",
31
+ "file-type": "^21.1.0",
32
32
  "get-urls": "^12.1.0",
33
- "konva": "^10.0.8",
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.29.5",
39
- "sharp": "^0.34.4",
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.0",
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.10.0",
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.0",
59
- "vite": "^7.2.0",
60
- "vitest": "^4.0.7"
58
+ "@vitejs/plugin-react": "^5.1.1",
59
+ "vite": "^7.2.2",
60
+ "vitest": "^4.0.10"
61
61
  }
62
62
  }