pdfdancer-client-typescript 1.0.7 → 1.0.8
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.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/models.d.ts +34 -0
- package/dist/models.d.ts.map +1 -1
- package/dist/models.js +51 -1
- package/dist/models.js.map +1 -1
- package/dist/paragraph-builder.d.ts +2 -2
- package/dist/paragraph-builder.d.ts.map +1 -1
- package/dist/paragraph-builder.js +12 -5
- package/dist/paragraph-builder.js.map +1 -1
- package/dist/pdfdancer_v1.d.ts +2 -0
- package/dist/pdfdancer_v1.d.ts.map +1 -1
- package/dist/pdfdancer_v1.js +26 -1
- package/dist/pdfdancer_v1.js.map +1 -1
- package/dist/types.d.ts +25 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +46 -2
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/e2e/paragraph.test.ts +190 -1
- package/src/__tests__/standard-fonts.test.ts +87 -0
- package/src/index.ts +3 -1
- package/src/models.ts +71 -0
- package/src/paragraph-builder.ts +15 -8
- package/src/pdfdancer_v1.ts +49 -8
- package/src/types.ts +74 -7
package/dist/types.js
CHANGED
|
@@ -59,20 +59,64 @@ class FormFieldObject extends BaseObject {
|
|
|
59
59
|
exports.FormFieldObject = FormFieldObject;
|
|
60
60
|
class ParagraphObject extends BaseObject {
|
|
61
61
|
static fromRef(_client, objectRef) {
|
|
62
|
-
|
|
62
|
+
let paragraphObject = new ParagraphObject(_client, objectRef.internalId, objectRef.type, objectRef.position);
|
|
63
|
+
paragraphObject.setFontName(objectRef.fontName);
|
|
64
|
+
paragraphObject.setFontSize(objectRef.fontSize);
|
|
65
|
+
paragraphObject.setLineSpacings(objectRef.lineSpacings);
|
|
66
|
+
paragraphObject.setText(objectRef.text);
|
|
67
|
+
paragraphObject.setChildren(objectRef.children);
|
|
68
|
+
paragraphObject.ref = () => objectRef;
|
|
69
|
+
return paragraphObject;
|
|
63
70
|
}
|
|
64
71
|
edit() {
|
|
65
72
|
return new paragraph_builder_1.ParagraphBuilder(this._client, this.ref());
|
|
66
73
|
}
|
|
74
|
+
setFontName(fontName) {
|
|
75
|
+
this.fontName = fontName;
|
|
76
|
+
}
|
|
77
|
+
setFontSize(fontSize) {
|
|
78
|
+
this.fontSize = fontSize;
|
|
79
|
+
}
|
|
80
|
+
setLineSpacings(lineSpacings) {
|
|
81
|
+
this.lineSpacings = lineSpacings;
|
|
82
|
+
}
|
|
83
|
+
setText(text) {
|
|
84
|
+
this.text = text;
|
|
85
|
+
}
|
|
86
|
+
setChildren(children) {
|
|
87
|
+
this.children = children;
|
|
88
|
+
}
|
|
67
89
|
}
|
|
68
90
|
exports.ParagraphObject = ParagraphObject;
|
|
69
91
|
class TextLineObject extends BaseObject {
|
|
70
92
|
static fromRef(_client, objectRef) {
|
|
71
|
-
|
|
93
|
+
let textLineObject = new TextLineObject(_client, objectRef.internalId, objectRef.type, objectRef.position);
|
|
94
|
+
textLineObject.setFontName(objectRef.fontName);
|
|
95
|
+
textLineObject.setFontSize(objectRef.fontSize);
|
|
96
|
+
textLineObject.setLineSpacings(objectRef.lineSpacings);
|
|
97
|
+
textLineObject.setText(objectRef.text);
|
|
98
|
+
textLineObject.setChildren(objectRef.children);
|
|
99
|
+
textLineObject.ref = () => objectRef;
|
|
100
|
+
return textLineObject;
|
|
72
101
|
}
|
|
73
102
|
edit() {
|
|
74
103
|
return new TextLineBuilder(this._client, this.ref());
|
|
75
104
|
}
|
|
105
|
+
setFontName(fontName) {
|
|
106
|
+
this.fontName = fontName;
|
|
107
|
+
}
|
|
108
|
+
setFontSize(fontSize) {
|
|
109
|
+
this.fontSize = fontSize;
|
|
110
|
+
}
|
|
111
|
+
setLineSpacings(lineSpacings) {
|
|
112
|
+
this.lineSpacings = lineSpacings;
|
|
113
|
+
}
|
|
114
|
+
setText(text) {
|
|
115
|
+
this.text = text;
|
|
116
|
+
}
|
|
117
|
+
setChildren(children) {
|
|
118
|
+
this.children = children;
|
|
119
|
+
}
|
|
76
120
|
}
|
|
77
121
|
exports.TextLineObject = TextLineObject;
|
|
78
122
|
class TextLineBuilder {
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* E2E tests for paragraph operations — new PDFDancer API
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {Color, PDFDancer} from '../../index';
|
|
5
|
+
import {Color, PDFDancer, StandardFonts} from '../../index';
|
|
6
6
|
import {getFontPath, readFontFixture, requireEnvAndFixture} from './test-helpers';
|
|
7
7
|
import {expectWithin} from '../assertions';
|
|
8
8
|
|
|
@@ -214,4 +214,193 @@ describe('Paragraph E2E Tests (v2 API)', () => {
|
|
|
214
214
|
expect(success).toBe(true);
|
|
215
215
|
await assertNewParagraphExists(pdf);
|
|
216
216
|
});
|
|
217
|
+
|
|
218
|
+
test('add paragraph with standard font - Helvetica', async () => {
|
|
219
|
+
const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
220
|
+
const pdf = await PDFDancer.open(pdfData, token, baseUrl);
|
|
221
|
+
|
|
222
|
+
const success = await pdf.page(0).newParagraph()
|
|
223
|
+
.text('Standard Font Test\nHelvetica')
|
|
224
|
+
.font(StandardFonts.HELVETICA, 14)
|
|
225
|
+
.lineSpacing(1.2)
|
|
226
|
+
.at(100, 600)
|
|
227
|
+
.apply();
|
|
228
|
+
|
|
229
|
+
expect(success).toBe(true);
|
|
230
|
+
const lines = await pdf.page(0).selectTextLinesStartingWith('Standard Font Test');
|
|
231
|
+
expect(lines.length).toBeGreaterThanOrEqual(1);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
test('add paragraph with standard font - Times Bold', async () => {
|
|
235
|
+
const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
236
|
+
const pdf = await PDFDancer.open(pdfData, token, baseUrl);
|
|
237
|
+
|
|
238
|
+
const success = await pdf.page(0).newParagraph()
|
|
239
|
+
.text('Times Bold Test')
|
|
240
|
+
.font(StandardFonts.TIMES_BOLD, 16)
|
|
241
|
+
.color(new Color(255, 0, 0))
|
|
242
|
+
.at(100, 550)
|
|
243
|
+
.apply();
|
|
244
|
+
|
|
245
|
+
expect(success).toBe(true);
|
|
246
|
+
const lines = await pdf.page(0).selectTextLinesStartingWith('Times Bold Test');
|
|
247
|
+
expect(lines.length).toBeGreaterThanOrEqual(1);
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
test('add paragraph with standard font - Courier', async () => {
|
|
251
|
+
const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
252
|
+
const pdf = await PDFDancer.open(pdfData, token, baseUrl);
|
|
253
|
+
|
|
254
|
+
const success = await pdf.page(0).newParagraph()
|
|
255
|
+
.text('Courier Monospace\nCode Example')
|
|
256
|
+
.font(StandardFonts.COURIER, 12)
|
|
257
|
+
.lineSpacing(1.5)
|
|
258
|
+
.at(100, 500)
|
|
259
|
+
.apply();
|
|
260
|
+
|
|
261
|
+
expect(success).toBe(true);
|
|
262
|
+
const lines = await pdf.page(0).selectTextLinesStartingWith('Courier Monospace');
|
|
263
|
+
expect(lines.length).toBeGreaterThanOrEqual(1);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
test('modify paragraph without position', async () => {
|
|
268
|
+
const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
269
|
+
const pdf = await PDFDancer.open(pdfData, token, baseUrl);
|
|
270
|
+
|
|
271
|
+
const [para] = await pdf.page(0).selectParagraphsStartingWith('The Complete');
|
|
272
|
+
let originalX = para.position.getX();
|
|
273
|
+
let originalY = para.position.getY();
|
|
274
|
+
|
|
275
|
+
await para.edit()
|
|
276
|
+
.replace('Modified with\nStandard Font')
|
|
277
|
+
.font(StandardFonts.HELVETICA_BOLD, 14)
|
|
278
|
+
.lineSpacing(1.3)
|
|
279
|
+
.apply();
|
|
280
|
+
|
|
281
|
+
const [newPara] = await pdf.page(0).selectParagraphsStartingWith('Modified with');
|
|
282
|
+
// TODO should be at the original position
|
|
283
|
+
expect(newPara.position.getX()).toBe(originalX);
|
|
284
|
+
expect(newPara.position.getY()).toBe(originalY);
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
test('modify paragraph without position and lineSpacing', async () => {
|
|
288
|
+
const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
289
|
+
const pdf = await PDFDancer.open(pdfData, token, baseUrl);
|
|
290
|
+
|
|
291
|
+
const [para] = await pdf.page(0).selectParagraphsStartingWith('The Complete');
|
|
292
|
+
let originalX = para.position.getX();
|
|
293
|
+
let originalY = para.position.getY();
|
|
294
|
+
|
|
295
|
+
await para.edit()
|
|
296
|
+
.replace('Modified with\nStandard Font')
|
|
297
|
+
.font(StandardFonts.HELVETICA_BOLD, 14)
|
|
298
|
+
.apply();
|
|
299
|
+
|
|
300
|
+
const [newPara] = await pdf.page(0).selectParagraphsStartingWith('Modified with');
|
|
301
|
+
// TODO should be at the original position
|
|
302
|
+
expect(newPara.position.getX()).toBe(originalX);
|
|
303
|
+
expect(newPara.position.getY()).toBe(originalY);
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
test('modify paragraph only change font', async () => {
|
|
307
|
+
const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
308
|
+
const pdf = await PDFDancer.open(pdfData, token, baseUrl);
|
|
309
|
+
|
|
310
|
+
const [para] = await pdf.page(0).selectParagraphsStartingWith('The Complete');
|
|
311
|
+
let originalX = para.position.getX();
|
|
312
|
+
let originalY = para.position.getY();
|
|
313
|
+
|
|
314
|
+
await para.edit()
|
|
315
|
+
.font(StandardFonts.HELVETICA_BOLD, 28)
|
|
316
|
+
.apply();
|
|
317
|
+
|
|
318
|
+
const [newPara] = await pdf.page(0).selectParagraphsStartingWith('The Complete');
|
|
319
|
+
// TODO should be at the original position
|
|
320
|
+
expect(newPara.position.getX()).toBe(originalX);
|
|
321
|
+
expect(newPara.position.getY()).toBe(originalY);
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
test('add paragraph without position', async () => {
|
|
325
|
+
const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
326
|
+
const pdf = await PDFDancer.open(pdfData, token, baseUrl);
|
|
327
|
+
|
|
328
|
+
await expect(pdf.page(0).newParagraph()
|
|
329
|
+
.text('Courier Monospace\nCode Example')
|
|
330
|
+
.font(StandardFonts.COURIER, 12)
|
|
331
|
+
.lineSpacing(1.5)
|
|
332
|
+
.apply())
|
|
333
|
+
.rejects
|
|
334
|
+
.toThrow("Paragraph position is null, you need to specify a position for the new paragraph, using .at(x,y)");
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
test('modify paragraph to use standard font', async () => {
|
|
338
|
+
const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
339
|
+
const pdf = await PDFDancer.open(pdfData, token, baseUrl);
|
|
340
|
+
|
|
341
|
+
const [para] = await pdf.page(0).selectParagraphsStartingWith('The Complete');
|
|
342
|
+
|
|
343
|
+
await para.edit()
|
|
344
|
+
.replace('Modified with\nStandard Font')
|
|
345
|
+
.font(StandardFonts.HELVETICA_BOLD, 14)
|
|
346
|
+
.lineSpacing(1.3)
|
|
347
|
+
.moveTo(100, 400)
|
|
348
|
+
.apply();
|
|
349
|
+
|
|
350
|
+
const lines = await pdf.page(0).selectTextLinesStartingWith('Modified with');
|
|
351
|
+
expect(lines.length).toBeGreaterThanOrEqual(1);
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
test('use all Times family standard fonts', async () => {
|
|
355
|
+
const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
356
|
+
const pdf = await PDFDancer.open(pdfData, token, baseUrl);
|
|
357
|
+
|
|
358
|
+
const timesFonts = [
|
|
359
|
+
StandardFonts.TIMES_ROMAN,
|
|
360
|
+
StandardFonts.TIMES_BOLD,
|
|
361
|
+
StandardFonts.TIMES_ITALIC,
|
|
362
|
+
StandardFonts.TIMES_BOLD_ITALIC
|
|
363
|
+
];
|
|
364
|
+
|
|
365
|
+
for (let i = 0; i < timesFonts.length; i++) {
|
|
366
|
+
const success = await pdf.page(0).newParagraph()
|
|
367
|
+
.text(`Times Font ${i}`)
|
|
368
|
+
.font(timesFonts[i], 12)
|
|
369
|
+
.at(50, 700 - (i * 30))
|
|
370
|
+
.apply();
|
|
371
|
+
expect(success).toBe(true);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const lines = await pdf.page(0).selectTextLinesStartingWith('Times Font');
|
|
375
|
+
expect(lines.length).toBe(4);
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
test('use all Helvetica family standard fonts', async () => {
|
|
379
|
+
const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
380
|
+
const pdf = await PDFDancer.open(pdfData, token, baseUrl);
|
|
381
|
+
|
|
382
|
+
const helveticaFonts = [
|
|
383
|
+
StandardFonts.HELVETICA,
|
|
384
|
+
StandardFonts.HELVETICA_BOLD,
|
|
385
|
+
StandardFonts.HELVETICA_OBLIQUE,
|
|
386
|
+
StandardFonts.HELVETICA_BOLD_OBLIQUE
|
|
387
|
+
];
|
|
388
|
+
|
|
389
|
+
for (let i = 0; i < helveticaFonts.length; i++) {
|
|
390
|
+
const success = await pdf.page(0).newParagraph()
|
|
391
|
+
.text(`Helvetica Font ${i}`)
|
|
392
|
+
.font(helveticaFonts[i], 12)
|
|
393
|
+
.at(200, 700 - (i * 30))
|
|
394
|
+
.apply();
|
|
395
|
+
expect(success).toBe(true);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
const lines = await pdf.page(0).selectTextLinesStartingWith('Helvetica Font');
|
|
399
|
+
expect(lines.length).toBe(4);
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
test('Symbol and ZapfDingbats fonts are available as standard fonts', () => {
|
|
403
|
+
expect(StandardFonts.SYMBOL).toBe('Symbol');
|
|
404
|
+
expect(StandardFonts.ZAPF_DINGBATS).toBe('ZapfDingbats');
|
|
405
|
+
});
|
|
217
406
|
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for StandardFonts enum.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { StandardFonts, Font } from '../models';
|
|
6
|
+
|
|
7
|
+
describe('StandardFonts', () => {
|
|
8
|
+
test('should have all 14 standard PDF fonts', () => {
|
|
9
|
+
const standardFonts = Object.values(StandardFonts);
|
|
10
|
+
expect(standardFonts).toHaveLength(14);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test('should have Times family fonts', () => {
|
|
14
|
+
expect(StandardFonts.TIMES_ROMAN).toBe('Times-Roman');
|
|
15
|
+
expect(StandardFonts.TIMES_BOLD).toBe('Times-Bold');
|
|
16
|
+
expect(StandardFonts.TIMES_ITALIC).toBe('Times-Italic');
|
|
17
|
+
expect(StandardFonts.TIMES_BOLD_ITALIC).toBe('Times-BoldItalic');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('should have Helvetica family fonts', () => {
|
|
21
|
+
expect(StandardFonts.HELVETICA).toBe('Helvetica');
|
|
22
|
+
expect(StandardFonts.HELVETICA_BOLD).toBe('Helvetica-Bold');
|
|
23
|
+
expect(StandardFonts.HELVETICA_OBLIQUE).toBe('Helvetica-Oblique');
|
|
24
|
+
expect(StandardFonts.HELVETICA_BOLD_OBLIQUE).toBe('Helvetica-BoldOblique');
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test('should have Courier family fonts', () => {
|
|
28
|
+
expect(StandardFonts.COURIER).toBe('Courier');
|
|
29
|
+
expect(StandardFonts.COURIER_BOLD).toBe('Courier-Bold');
|
|
30
|
+
expect(StandardFonts.COURIER_OBLIQUE).toBe('Courier-Oblique');
|
|
31
|
+
expect(StandardFonts.COURIER_BOLD_OBLIQUE).toBe('Courier-BoldOblique');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('should have Symbol font', () => {
|
|
35
|
+
expect(StandardFonts.SYMBOL).toBe('Symbol');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test('should have ZapfDingbats font', () => {
|
|
39
|
+
expect(StandardFonts.ZAPF_DINGBATS).toBe('ZapfDingbats');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('should work with Font class', () => {
|
|
43
|
+
const font = new Font(StandardFonts.HELVETICA, 12);
|
|
44
|
+
expect(font.name).toBe('Helvetica');
|
|
45
|
+
expect(font.size).toBe(12);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('should work with all standard fonts in Font class', () => {
|
|
49
|
+
for (const standardFont of Object.values(StandardFonts)) {
|
|
50
|
+
const font = new Font(standardFont, 10);
|
|
51
|
+
expect(font.name).toBe(standardFont);
|
|
52
|
+
expect(font.size).toBe(10);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('should have correct font name formats', () => {
|
|
57
|
+
expect(StandardFonts.TIMES_BOLD_ITALIC).toMatch(/^Times-[A-Za-z]+$/);
|
|
58
|
+
expect(StandardFonts.HELVETICA_BOLD_OBLIQUE).toMatch(/^Helvetica-[A-Za-z]+$/);
|
|
59
|
+
expect(StandardFonts.COURIER_BOLD_OBLIQUE).toMatch(/^Courier-[A-Za-z]+$/);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('should have unique font names', () => {
|
|
63
|
+
const fontNames = Object.values(StandardFonts);
|
|
64
|
+
const uniqueFontNames = new Set(fontNames);
|
|
65
|
+
expect(uniqueFontNames.size).toBe(fontNames.length);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('enum keys should match convention', () => {
|
|
69
|
+
expect(Object.keys(StandardFonts)).toContain('TIMES_ROMAN');
|
|
70
|
+
expect(Object.keys(StandardFonts)).toContain('HELVETICA');
|
|
71
|
+
expect(Object.keys(StandardFonts)).toContain('COURIER');
|
|
72
|
+
expect(Object.keys(StandardFonts)).toContain('SYMBOL');
|
|
73
|
+
expect(Object.keys(StandardFonts)).toContain('ZAPF_DINGBATS');
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test('should be compatible with string type', () => {
|
|
77
|
+
const fontName: string = StandardFonts.HELVETICA;
|
|
78
|
+
expect(typeof fontName).toBe('string');
|
|
79
|
+
expect(fontName).toBe('Helvetica');
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test('standard fonts should not have spaces', () => {
|
|
83
|
+
for (const standardFont of Object.values(StandardFonts)) {
|
|
84
|
+
expect(standardFont).not.toContain(' ');
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -18,6 +18,7 @@ export {
|
|
|
18
18
|
export {
|
|
19
19
|
ObjectRef,
|
|
20
20
|
FormFieldRef,
|
|
21
|
+
TextObjectRef,
|
|
21
22
|
Position,
|
|
22
23
|
ObjectType,
|
|
23
24
|
Font,
|
|
@@ -27,7 +28,8 @@ export {
|
|
|
27
28
|
Paragraph,
|
|
28
29
|
PositionMode,
|
|
29
30
|
ShapeType,
|
|
30
|
-
Point
|
|
31
|
+
Point,
|
|
32
|
+
StandardFonts
|
|
31
33
|
} from './models';
|
|
32
34
|
|
|
33
35
|
export const VERSION = "1.0.0";
|
package/src/models.ts
CHANGED
|
@@ -234,6 +234,56 @@ export class FormFieldRef extends ObjectRef {
|
|
|
234
234
|
}
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
+
export class TextObjectRef extends ObjectRef {
|
|
238
|
+
private _text?: string;
|
|
239
|
+
private _fontName?: string;
|
|
240
|
+
private _fontSize?: number;
|
|
241
|
+
private _lineSpacings?: number[] | null;
|
|
242
|
+
private _children?: TextObjectRef[];
|
|
243
|
+
|
|
244
|
+
constructor(
|
|
245
|
+
internalId: string,
|
|
246
|
+
position: Position,
|
|
247
|
+
type: ObjectType,
|
|
248
|
+
text?: string,
|
|
249
|
+
fontName?: string,
|
|
250
|
+
fontSize?: number,
|
|
251
|
+
lineSpacings?: number[] | null,
|
|
252
|
+
children?: TextObjectRef[]
|
|
253
|
+
) {
|
|
254
|
+
super(internalId, position, type);
|
|
255
|
+
this._text = text;
|
|
256
|
+
this._fontName = fontName;
|
|
257
|
+
this._fontSize = fontSize;
|
|
258
|
+
this._lineSpacings = lineSpacings;
|
|
259
|
+
this._children = children;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
get text(): string | undefined {
|
|
263
|
+
return this._text;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
get fontName(): string | undefined {
|
|
267
|
+
return this._fontName;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
get fontSize(): number | undefined {
|
|
271
|
+
return this._fontSize;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
get lineSpacings(): number[] | null | undefined {
|
|
275
|
+
return this._lineSpacings;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
get children(): TextObjectRef[] | undefined {
|
|
279
|
+
return this._children;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
set children(value: TextObjectRef[] | undefined) {
|
|
283
|
+
this._children = value;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
237
287
|
/**
|
|
238
288
|
* Represents an RGB color with optional alpha channel, values from 0-255.
|
|
239
289
|
*/
|
|
@@ -252,6 +302,27 @@ export class Color {
|
|
|
252
302
|
}
|
|
253
303
|
}
|
|
254
304
|
|
|
305
|
+
/**
|
|
306
|
+
* Standard PDF fonts that are available in all PDF readers.
|
|
307
|
+
* These 14 fonts are guaranteed to be available without embedding.
|
|
308
|
+
*/
|
|
309
|
+
export enum StandardFonts {
|
|
310
|
+
TIMES_ROMAN = "Times-Roman",
|
|
311
|
+
TIMES_BOLD = "Times-Bold",
|
|
312
|
+
TIMES_ITALIC = "Times-Italic",
|
|
313
|
+
TIMES_BOLD_ITALIC = "Times-BoldItalic",
|
|
314
|
+
HELVETICA = "Helvetica",
|
|
315
|
+
HELVETICA_BOLD = "Helvetica-Bold",
|
|
316
|
+
HELVETICA_OBLIQUE = "Helvetica-Oblique",
|
|
317
|
+
HELVETICA_BOLD_OBLIQUE = "Helvetica-BoldOblique",
|
|
318
|
+
COURIER = "Courier",
|
|
319
|
+
COURIER_BOLD = "Courier-Bold",
|
|
320
|
+
COURIER_OBLIQUE = "Courier-Oblique",
|
|
321
|
+
COURIER_BOLD_OBLIQUE = "Courier-BoldOblique",
|
|
322
|
+
SYMBOL = "Symbol",
|
|
323
|
+
ZAPF_DINGBATS = "ZapfDingbats"
|
|
324
|
+
}
|
|
325
|
+
|
|
255
326
|
/**
|
|
256
327
|
* Represents a font with name and size.
|
|
257
328
|
*/
|
package/src/paragraph-builder.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import {ValidationException} from './exceptions';
|
|
6
|
-
import {Color, Font, ObjectRef, Paragraph, Position} from './models';
|
|
6
|
+
import {Color, Font, ObjectRef, Paragraph, Position, TextObjectRef} from './models';
|
|
7
7
|
import {PDFDancer} from "./pdfdancer_v1";
|
|
8
8
|
|
|
9
9
|
// 👇 Internal view of PDFDancer methods, not exported
|
|
@@ -27,7 +27,7 @@ export class ParagraphBuilder {
|
|
|
27
27
|
private _pageIndex: number;
|
|
28
28
|
private _internals: PDFDancerInternals;
|
|
29
29
|
|
|
30
|
-
constructor(private _client: PDFDancer, private objectRefOrPageIndex?:
|
|
30
|
+
constructor(private _client: PDFDancer, private objectRefOrPageIndex?: TextObjectRef | number) {
|
|
31
31
|
if (!_client) {
|
|
32
32
|
throw new ValidationException("Client cannot be null");
|
|
33
33
|
}
|
|
@@ -192,9 +192,6 @@ export class ParagraphBuilder {
|
|
|
192
192
|
}
|
|
193
193
|
|
|
194
194
|
async apply() {
|
|
195
|
-
if (!this._text) {
|
|
196
|
-
throw new ValidationException("Text must be set before building paragraph");
|
|
197
|
-
}
|
|
198
195
|
// Wait for all deferred operations (e.g., fontFile, images, etc.)
|
|
199
196
|
if (this._pending.length) {
|
|
200
197
|
await Promise.all(this._pending);
|
|
@@ -205,14 +202,24 @@ export class ParagraphBuilder {
|
|
|
205
202
|
throw new ValidationException("Font registration is not complete");
|
|
206
203
|
}
|
|
207
204
|
|
|
208
|
-
|
|
209
|
-
if (this.objectRefOrPageIndex instanceof ObjectRef) {
|
|
205
|
+
if (this.objectRefOrPageIndex instanceof TextObjectRef) {
|
|
210
206
|
if (!this._font || !this._textColor) {
|
|
211
|
-
return await this._internals.modifyParagraph(this.objectRefOrPageIndex, this._text);
|
|
207
|
+
return await this._internals.modifyParagraph(this.objectRefOrPageIndex, this._text!);
|
|
212
208
|
} else {
|
|
209
|
+
if (!this._text && !this.objectRefOrPageIndex?.text) {
|
|
210
|
+
throw new ValidationException("A paragraph must have text. Set the text using .text()");
|
|
211
|
+
}
|
|
212
|
+
if (!this._text) {
|
|
213
|
+
this._text = this.objectRefOrPageIndex.text;
|
|
214
|
+
}
|
|
215
|
+
let paragraph = this.build();
|
|
216
|
+
if (!paragraph.position) {
|
|
217
|
+
paragraph.position = this.objectRefOrPageIndex.position;
|
|
218
|
+
}
|
|
213
219
|
return await this._internals.modifyParagraph(this.objectRefOrPageIndex, paragraph);
|
|
214
220
|
}
|
|
215
221
|
} else {
|
|
222
|
+
let paragraph = this.build();
|
|
216
223
|
return await this._internals.addParagraph(paragraph);
|
|
217
224
|
}
|
|
218
225
|
}
|
package/src/pdfdancer_v1.ts
CHANGED
|
@@ -28,7 +28,8 @@ import {
|
|
|
28
28
|
Paragraph,
|
|
29
29
|
Position,
|
|
30
30
|
PositionMode,
|
|
31
|
-
ShapeType
|
|
31
|
+
ShapeType,
|
|
32
|
+
TextObjectRef
|
|
32
33
|
} from './models';
|
|
33
34
|
import {ParagraphBuilder} from './paragraph-builder';
|
|
34
35
|
import {FormFieldObject, FormXObject, ImageObject, ParagraphObject, PathObject, TextLineObject} from "./types";
|
|
@@ -441,8 +442,8 @@ export class PDFDancer {
|
|
|
441
442
|
/**
|
|
442
443
|
* Searches for paragraph objects at the specified position.
|
|
443
444
|
*/
|
|
444
|
-
private async findParagraphs(position?: Position): Promise<
|
|
445
|
-
return this.find(ObjectType.PARAGRAPH, position)
|
|
445
|
+
private async findParagraphs(position?: Position): Promise<TextObjectRef[]> {
|
|
446
|
+
return this.find(ObjectType.PARAGRAPH, position) as Promise<TextObjectRef[]>;
|
|
446
447
|
}
|
|
447
448
|
|
|
448
449
|
/**
|
|
@@ -489,8 +490,8 @@ export class PDFDancer {
|
|
|
489
490
|
/**
|
|
490
491
|
* Searches for text line objects at the specified position.
|
|
491
492
|
*/
|
|
492
|
-
private async findTextLines(position?: Position): Promise<
|
|
493
|
-
return this.find(ObjectType.TEXT_LINE, position)
|
|
493
|
+
private async findTextLines(position?: Position): Promise<TextObjectRef[]> {
|
|
494
|
+
return this.find(ObjectType.TEXT_LINE, position) as Promise<TextObjectRef[]>;
|
|
494
495
|
}
|
|
495
496
|
|
|
496
497
|
/**
|
|
@@ -621,7 +622,7 @@ export class PDFDancer {
|
|
|
621
622
|
throw new ValidationException("Paragraph cannot be null");
|
|
622
623
|
}
|
|
623
624
|
if (!paragraph.getPosition()) {
|
|
624
|
-
throw new ValidationException("Paragraph position is null");
|
|
625
|
+
throw new ValidationException("Paragraph position is null, you need to specify a position for the new paragraph, using .at(x,y)");
|
|
625
626
|
}
|
|
626
627
|
if (paragraph.getPosition()!.pageIndex === undefined) {
|
|
627
628
|
throw new ValidationException("Paragraph position page index is null");
|
|
@@ -807,6 +808,10 @@ export class PDFDancer {
|
|
|
807
808
|
|
|
808
809
|
const objectType = objData.type as ObjectType;
|
|
809
810
|
|
|
811
|
+
if (this._isTextObjectData(objData, objectType)) {
|
|
812
|
+
return this._parseTextObjectRef(objData);
|
|
813
|
+
}
|
|
814
|
+
|
|
810
815
|
return new ObjectRef(
|
|
811
816
|
objData.internalId,
|
|
812
817
|
position,
|
|
@@ -814,6 +819,42 @@ export class PDFDancer {
|
|
|
814
819
|
);
|
|
815
820
|
}
|
|
816
821
|
|
|
822
|
+
private _isTextObjectData(objData: any, objectType: ObjectType): boolean {
|
|
823
|
+
return objectType === ObjectType.PARAGRAPH ||
|
|
824
|
+
objectType === ObjectType.TEXT_LINE ||
|
|
825
|
+
typeof objData.text === 'string' ||
|
|
826
|
+
typeof objData.fontName === 'string' ||
|
|
827
|
+
Array.isArray(objData.children);
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
private _parseTextObjectRef(objData: any, fallbackId?: string): TextObjectRef {
|
|
831
|
+
const positionData = objData.position || {};
|
|
832
|
+
const position = positionData ? this._parsePosition(positionData) : new Position();
|
|
833
|
+
|
|
834
|
+
const objectType = (objData.type as ObjectType) ?? ObjectType.TEXT_LINE;
|
|
835
|
+
const lineSpacings = Array.isArray(objData.lineSpacings) ? objData.lineSpacings : null;
|
|
836
|
+
const internalId = objData.internalId ?? fallbackId ?? '';
|
|
837
|
+
|
|
838
|
+
const textObject = new TextObjectRef(
|
|
839
|
+
internalId,
|
|
840
|
+
position,
|
|
841
|
+
objectType,
|
|
842
|
+
typeof objData.text === 'string' ? objData.text : undefined,
|
|
843
|
+
typeof objData.fontName === 'string' ? objData.fontName : undefined,
|
|
844
|
+
typeof objData.fontSize === 'number' ? objData.fontSize : undefined,
|
|
845
|
+
lineSpacings
|
|
846
|
+
);
|
|
847
|
+
|
|
848
|
+
if (Array.isArray(objData.children) && objData.children.length > 0) {
|
|
849
|
+
textObject.children = objData.children.map((childData: any, index: number) => {
|
|
850
|
+
const childFallbackId = `${internalId || 'child'}-${index}`;
|
|
851
|
+
return this._parseTextObjectRef(childData, childFallbackId);
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
return textObject;
|
|
856
|
+
}
|
|
857
|
+
|
|
817
858
|
private _parseFormFieldRef(objData: any): FormFieldRef {
|
|
818
859
|
const positionData = objData.position || {};
|
|
819
860
|
const position = positionData ? this._parsePosition(positionData) : new Position();
|
|
@@ -896,11 +937,11 @@ export class PDFDancer {
|
|
|
896
937
|
return this.toParagraphObjects(await this.findParagraphs());
|
|
897
938
|
}
|
|
898
939
|
|
|
899
|
-
private toParagraphObjects(objectRefs:
|
|
940
|
+
private toParagraphObjects(objectRefs: TextObjectRef[]) {
|
|
900
941
|
return objectRefs.map(ref => ParagraphObject.fromRef(this, ref));
|
|
901
942
|
}
|
|
902
943
|
|
|
903
|
-
private toTextLineObjects(objectRefs:
|
|
944
|
+
private toTextLineObjects(objectRefs: TextObjectRef[]) {
|
|
904
945
|
return objectRefs.map(ref => TextLineObject.fromRef(this, ref));
|
|
905
946
|
}
|
|
906
947
|
|