@polotno/pdf-export 0.1.25 → 0.1.27
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/text.js +37 -12
- package/package.json +2 -1
package/lib/text.js
CHANGED
|
@@ -27,6 +27,8 @@ function normalizeRichText(text) {
|
|
|
27
27
|
normalized = normalized.replace(/\n{3,}/g, '\n\n');
|
|
28
28
|
// Trim stray leading/trailing newlines introduced by paragraph conversion
|
|
29
29
|
normalized = normalized.replace(/^\n+/, '').replace(/\n+$/, '');
|
|
30
|
+
// Decode common HTML non-breaking space entities into their unicode counterpart
|
|
31
|
+
normalized = normalized.replace(/&(nbsp|#160|#xA0);/gi, '\u00A0');
|
|
30
32
|
return normalized;
|
|
31
33
|
}
|
|
32
34
|
/**
|
|
@@ -277,11 +279,23 @@ function serializeAttributes(attributes) {
|
|
|
277
279
|
.map(([key, value]) => value === '' ? key : `${key}="${value.replace(/"/g, '"')}"`)
|
|
278
280
|
.join(' '));
|
|
279
281
|
}
|
|
282
|
+
function shouldSkipNode(node) {
|
|
283
|
+
if (node.type === 'element' && node.tagName === 'span') {
|
|
284
|
+
const classAttr = node.attributes['class'] || node.attributes['className'] || '';
|
|
285
|
+
if (/\bql-cursor\b/.test(classAttr)) {
|
|
286
|
+
return true;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
280
291
|
function serializeNodes(nodes) {
|
|
281
292
|
return nodes
|
|
282
293
|
.map((node) => {
|
|
294
|
+
if (shouldSkipNode(node)) {
|
|
295
|
+
return '';
|
|
296
|
+
}
|
|
283
297
|
if (node.type === 'text') {
|
|
284
|
-
return node.content;
|
|
298
|
+
return node.content.replace(/\uFEFF/g, '');
|
|
285
299
|
}
|
|
286
300
|
const attrs = serializeAttributes(node.attributes);
|
|
287
301
|
if (VOID_ELEMENTS.has(node.tagName)) {
|
|
@@ -325,23 +339,34 @@ function nodesToParagraphs(nodes, baseIndentLevel = 0) {
|
|
|
325
339
|
pendingInline = [];
|
|
326
340
|
};
|
|
327
341
|
for (const node of nodes) {
|
|
342
|
+
if (shouldSkipNode(node)) {
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
328
345
|
if (node.type === 'text') {
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
346
|
+
const newlineRegex = /\n+/g;
|
|
347
|
+
let lastIndex = 0;
|
|
348
|
+
let match;
|
|
349
|
+
while ((match = newlineRegex.exec(node.content)) !== null) {
|
|
350
|
+
const chunk = node.content.slice(lastIndex, match.index);
|
|
351
|
+
if (chunk.length > 0) {
|
|
334
352
|
pendingInline.push({
|
|
335
353
|
type: 'text',
|
|
336
|
-
content:
|
|
354
|
+
content: chunk,
|
|
337
355
|
});
|
|
338
356
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
}
|
|
357
|
+
flushInline();
|
|
358
|
+
const extraBreaks = match[0].length - 1;
|
|
359
|
+
for (let extra = 0; extra < extraBreaks; extra++) {
|
|
360
|
+
paragraphs.push({ html: '' });
|
|
344
361
|
}
|
|
362
|
+
lastIndex = newlineRegex.lastIndex;
|
|
363
|
+
}
|
|
364
|
+
const rest = node.content.slice(lastIndex);
|
|
365
|
+
if (rest.length > 0) {
|
|
366
|
+
pendingInline.push({
|
|
367
|
+
type: 'text',
|
|
368
|
+
content: rest,
|
|
369
|
+
});
|
|
345
370
|
}
|
|
346
371
|
continue;
|
|
347
372
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@polotno/pdf-export",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.27",
|
|
4
4
|
"description": "Convert Polotno JSON into vector PDF",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
15
|
"build": "tsc",
|
|
16
|
+
"prepublishOnly": "npm run build",
|
|
16
17
|
"test": "vitest",
|
|
17
18
|
"test:update-snapshots": "vitest -u",
|
|
18
19
|
"dev": "vite client",
|