postext-pdf 1.49.0 → 1.49.1
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.
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composedEmptyFrame.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/composedEmptyFrame.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { PDFArray, PDFDocument, PDFRawStream, decodePDFRawStream } from 'pdf-lib';
|
|
4
|
+
import fontkit from '@pdf-lib/fontkit';
|
|
5
|
+
import { buildDocument } from 'postext';
|
|
6
|
+
import { renderToPdf } from '../pdf-backend';
|
|
7
|
+
import { parseFontString } from '../fontString';
|
|
8
|
+
// #1084: a `:::frame` fence with nothing in it, for a frame with a callout
|
|
9
|
+
// style, draws the style's fill, border and tab (with its label) in the PDF.
|
|
10
|
+
const fontBytes = fs.readFileSync(new URL('../../../../apps/web/public/fonts/Lora-Regular.ttf', import.meta.url));
|
|
11
|
+
const face = fontkit.create(fontBytes);
|
|
12
|
+
class StubCtx {
|
|
13
|
+
font = '';
|
|
14
|
+
measureText(s) {
|
|
15
|
+
const sizePx = parseFontString(this.font)?.sizePx ?? 16;
|
|
16
|
+
return { width: (face.layout(s).advanceWidth / face.unitsPerEm) * sizePx };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
globalThis.OffscreenCanvas = class {
|
|
20
|
+
getContext() {
|
|
21
|
+
return new StubCtx();
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const mm = (value) => ({ value, unit: 'mm' });
|
|
25
|
+
const hex = (h) => ({ hex: h, model: 'hex' });
|
|
26
|
+
const config = {
|
|
27
|
+
page: { width: mm(200), height: mm(260), dpi: 72, margins: { top: mm(20), bottom: mm(20), left: mm(20), right: mm(20) } },
|
|
28
|
+
header: { elements: [] },
|
|
29
|
+
footer: { elements: [] },
|
|
30
|
+
bodyText: { fontFamily: 'Lora' },
|
|
31
|
+
calloutStyles: [{
|
|
32
|
+
id: 'caja', backgroundEnabled: true, background: hex('#ffeb99'),
|
|
33
|
+
border: { enabled: true, color: hex('#222222') }, padding: { top: mm(3), right: mm(5), bottom: mm(3), left: mm(5) },
|
|
34
|
+
label: { color: hex('#ffffff'), background: hex('#333333'), height: mm(6), paddingX: mm(3), fontFamily: 'Lora' },
|
|
35
|
+
}],
|
|
36
|
+
pageTemplates: [{
|
|
37
|
+
id: 't',
|
|
38
|
+
frames: [{ name: 'caja', style: 'caja', width: mm(100), minHeight: mm(30), placement: { anchor: { to: 'container', edge: 'top-left' } } }],
|
|
39
|
+
}],
|
|
40
|
+
};
|
|
41
|
+
const markdown = (fence) => ['::::page{template="t"}', '', fence, ':::', '', '::::'].join('\n');
|
|
42
|
+
async function contentOf(doc) {
|
|
43
|
+
const pdf = await PDFDocument.load(await renderToPdf(doc, { fontProvider: async () => new Uint8Array(fontBytes), accessible: false }));
|
|
44
|
+
const contents = pdf.getPage(0).node.Contents();
|
|
45
|
+
const refs = contents instanceof PDFArray ? contents.asArray() : [contents];
|
|
46
|
+
return refs
|
|
47
|
+
.map((ref) => {
|
|
48
|
+
const s = pdf.context.lookup(ref);
|
|
49
|
+
return s instanceof PDFRawStream ? new TextDecoder('latin1').decode(decodePDFRawStream(s).decode()) : '';
|
|
50
|
+
})
|
|
51
|
+
.join('\n');
|
|
52
|
+
}
|
|
53
|
+
/** Each fill colour set (`r g b rg`), as hex. */
|
|
54
|
+
const fills = (content) => [...content.matchAll(/([\d.]+) ([\d.]+) ([\d.]+) rg/g)].map((m) => `#${[m[1], m[2], m[3]].map((v) => Math.round(Number(v) * 255).toString(16).padStart(2, '0')).join('')}`);
|
|
55
|
+
const strokes = (content) => [...content.matchAll(/([\d.]+) ([\d.]+) ([\d.]+) RG/g)].map((m) => `#${[m[1], m[2], m[3]].map((v) => Math.round(Number(v) * 255).toString(16).padStart(2, '0')).join('')}`);
|
|
56
|
+
describe('an empty styled frame in the PDF (#1084)', () => {
|
|
57
|
+
it('paints the fill, the border and the tab with its word', async () => {
|
|
58
|
+
const content = await contentOf(buildDocument({ markdown: markdown(':::frame{slot="caja" label="Tab"}') }, config));
|
|
59
|
+
expect(fills(content)).toEqual(expect.arrayContaining(['#ffeb99', '#333333', '#ffffff']));
|
|
60
|
+
expect(strokes(content)).toContain('#222222');
|
|
61
|
+
expect(content).toMatch(/\bTJ|\bTj/);
|
|
62
|
+
});
|
|
63
|
+
it('a fence without a label: the box, no text', async () => {
|
|
64
|
+
const content = await contentOf(buildDocument({ markdown: markdown(':::frame{slot="caja"}') }, config));
|
|
65
|
+
expect(fills(content)).toContain('#ffeb99');
|
|
66
|
+
expect(fills(content)).not.toContain('#333333');
|
|
67
|
+
expect(content).not.toMatch(/\bTJ|\bTj/);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
//# sourceMappingURL=composedEmptyFrame.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composedEmptyFrame.test.js","sourceRoot":"","sources":["../../src/__tests__/composedEmptyFrame.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "postext-pdf",
|
|
3
|
-
"version": "1.49.
|
|
3
|
+
"version": "1.49.1",
|
|
4
4
|
"description": "Browser-native PDF renderer for Postext documents. Consumes the same VDT as the canvas/HTML backends and produces a physical PDF with faithful glyph positioning, justification, crop marks, and baseline grid.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"./package.json": "./package.json"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"postext": "^1.49.
|
|
43
|
+
"postext": "^1.49.1"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@pdf-lib/fontkit": "^1.1.1",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"@types/node": "^26.5.0",
|
|
55
55
|
"eslint": "^9.39.4",
|
|
56
56
|
"harfbuzzjs": "1.6.2",
|
|
57
|
-
"postext": "1.49.
|
|
57
|
+
"postext": "1.49.1",
|
|
58
58
|
"typescript": "^6.0.3",
|
|
59
59
|
"typescript-eslint": "^8.70.0",
|
|
60
60
|
"vitest": "^5.0.0"
|