postext-pdf 1.4.2 → 1.5.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.
- package/README.md +3 -3
- package/dist/__tests__/accessibility.test.js +66 -0
- package/dist/__tests__/accessibility.test.js.map +1 -1
- package/dist/__tests__/alpha.test.d.ts +2 -0
- package/dist/__tests__/alpha.test.d.ts.map +1 -0
- package/dist/__tests__/alpha.test.js +164 -0
- package/dist/__tests__/alpha.test.js.map +1 -0
- package/dist/__tests__/bleedClip.test.d.ts +2 -0
- package/dist/__tests__/bleedClip.test.d.ts.map +1 -0
- package/dist/__tests__/bleedClip.test.js +83 -0
- package/dist/__tests__/bleedClip.test.js.map +1 -0
- package/dist/__tests__/boxBorderInside.test.d.ts +2 -0
- package/dist/__tests__/boxBorderInside.test.d.ts.map +1 -0
- package/dist/__tests__/boxBorderInside.test.js +63 -0
- package/dist/__tests__/boxBorderInside.test.js.map +1 -0
- package/dist/__tests__/calloutRuntTracking.test.d.ts +2 -0
- package/dist/__tests__/calloutRuntTracking.test.d.ts.map +1 -0
- package/dist/__tests__/calloutRuntTracking.test.js +72 -0
- package/dist/__tests__/calloutRuntTracking.test.js.map +1 -0
- package/dist/__tests__/calloutStripeRadius.test.d.ts +2 -0
- package/dist/__tests__/calloutStripeRadius.test.d.ts.map +1 -0
- package/dist/__tests__/calloutStripeRadius.test.js +90 -0
- package/dist/__tests__/calloutStripeRadius.test.js.map +1 -0
- package/dist/__tests__/chipVerticalPadding.test.d.ts +2 -0
- package/dist/__tests__/chipVerticalPadding.test.d.ts.map +1 -0
- package/dist/__tests__/chipVerticalPadding.test.js +71 -0
- package/dist/__tests__/chipVerticalPadding.test.js.map +1 -0
- package/dist/__tests__/chips.test.js +20 -3
- package/dist/__tests__/chips.test.js.map +1 -1
- package/dist/__tests__/documentLanguage.test.d.ts +2 -0
- package/dist/__tests__/documentLanguage.test.d.ts.map +1 -0
- package/dist/__tests__/documentLanguage.test.js +44 -0
- package/dist/__tests__/documentLanguage.test.js.map +1 -0
- package/dist/__tests__/fallbackSpaces.test.d.ts +2 -0
- package/dist/__tests__/fallbackSpaces.test.d.ts.map +1 -0
- package/dist/__tests__/fallbackSpaces.test.js +156 -0
- package/dist/__tests__/fallbackSpaces.test.js.map +1 -0
- package/dist/__tests__/floatReadingOrder.test.d.ts +2 -0
- package/dist/__tests__/floatReadingOrder.test.d.ts.map +1 -0
- package/dist/__tests__/floatReadingOrder.test.js +208 -0
- package/dist/__tests__/floatReadingOrder.test.js.map +1 -0
- package/dist/__tests__/fontEmbedding.test.d.ts +2 -0
- package/dist/__tests__/fontEmbedding.test.d.ts.map +1 -0
- package/dist/__tests__/fontEmbedding.test.js +118 -0
- package/dist/__tests__/fontEmbedding.test.js.map +1 -0
- package/dist/__tests__/fontFaces.test.d.ts +2 -0
- package/dist/__tests__/fontFaces.test.d.ts.map +1 -0
- package/dist/__tests__/fontFaces.test.js +193 -0
- package/dist/__tests__/fontFaces.test.js.map +1 -0
- package/dist/__tests__/fontStack.test.d.ts +2 -0
- package/dist/__tests__/fontStack.test.d.ts.map +1 -0
- package/dist/__tests__/fontStack.test.js +48 -0
- package/dist/__tests__/fontStack.test.js.map +1 -0
- package/dist/__tests__/headerFooter.test.js +83 -1
- package/dist/__tests__/headerFooter.test.js.map +1 -1
- package/dist/__tests__/headingAlign.test.d.ts +2 -0
- package/dist/__tests__/headingAlign.test.d.ts.map +1 -0
- package/dist/__tests__/headingAlign.test.js +66 -0
- package/dist/__tests__/headingAlign.test.js.map +1 -0
- package/dist/__tests__/hiddenHeadings.test.d.ts +2 -0
- package/dist/__tests__/hiddenHeadings.test.d.ts.map +1 -0
- package/dist/__tests__/hiddenHeadings.test.js +96 -0
- package/dist/__tests__/hiddenHeadings.test.js.map +1 -0
- package/dist/__tests__/lineTracking.test.d.ts +2 -0
- package/dist/__tests__/lineTracking.test.d.ts.map +1 -0
- package/dist/__tests__/lineTracking.test.js +80 -0
- package/dist/__tests__/lineTracking.test.js.map +1 -0
- package/dist/__tests__/measuredLines.test.d.ts +2 -0
- package/dist/__tests__/measuredLines.test.d.ts.map +1 -0
- package/dist/__tests__/measuredLines.test.js +255 -0
- package/dist/__tests__/measuredLines.test.js.map +1 -0
- package/dist/__tests__/metadata.test.d.ts +2 -0
- package/dist/__tests__/metadata.test.d.ts.map +1 -0
- package/dist/__tests__/metadata.test.js +51 -0
- package/dist/__tests__/metadata.test.js.map +1 -0
- package/dist/__tests__/outlineTitles.test.d.ts +2 -0
- package/dist/__tests__/outlineTitles.test.d.ts.map +1 -0
- package/dist/__tests__/outlineTitles.test.js +59 -0
- package/dist/__tests__/outlineTitles.test.js.map +1 -0
- package/dist/__tests__/pdfGenerationConfig.test.d.ts +2 -0
- package/dist/__tests__/pdfGenerationConfig.test.d.ts.map +1 -0
- package/dist/__tests__/pdfGenerationConfig.test.js +76 -0
- package/dist/__tests__/pdfGenerationConfig.test.js.map +1 -0
- package/dist/__tests__/pdfWorker.test.d.ts +2 -0
- package/dist/__tests__/pdfWorker.test.d.ts.map +1 -0
- package/dist/__tests__/pdfWorker.test.js +123 -0
- package/dist/__tests__/pdfWorker.test.js.map +1 -0
- package/dist/__tests__/printMarks.test.d.ts +2 -0
- package/dist/__tests__/printMarks.test.d.ts.map +1 -0
- package/dist/__tests__/printMarks.test.js +170 -0
- package/dist/__tests__/printMarks.test.js.map +1 -0
- package/dist/__tests__/printMaster.test.d.ts +2 -0
- package/dist/__tests__/printMaster.test.d.ts.map +1 -0
- package/dist/__tests__/printMaster.test.js +161 -0
- package/dist/__tests__/printMaster.test.js.map +1 -0
- package/dist/__tests__/renderWarnings.test.d.ts +2 -0
- package/dist/__tests__/renderWarnings.test.d.ts.map +1 -0
- package/dist/__tests__/renderWarnings.test.js +89 -0
- package/dist/__tests__/renderWarnings.test.js.map +1 -0
- package/dist/__tests__/repeatedHyphen.test.d.ts +2 -0
- package/dist/__tests__/repeatedHyphen.test.d.ts.map +1 -0
- package/dist/__tests__/repeatedHyphen.test.js +125 -0
- package/dist/__tests__/repeatedHyphen.test.js.map +1 -0
- package/dist/__tests__/scriptStacking.test.d.ts +2 -0
- package/dist/__tests__/scriptStacking.test.d.ts.map +1 -0
- package/dist/__tests__/scriptStacking.test.js +66 -0
- package/dist/__tests__/scriptStacking.test.js.map +1 -0
- package/dist/__tests__/sectionColumnRule.test.d.ts +2 -0
- package/dist/__tests__/sectionColumnRule.test.d.ts.map +1 -0
- package/dist/__tests__/sectionColumnRule.test.js +144 -0
- package/dist/__tests__/sectionColumnRule.test.js.map +1 -0
- package/dist/__tests__/svgFormReuse.test.d.ts +2 -0
- package/dist/__tests__/svgFormReuse.test.d.ts.map +1 -0
- package/dist/__tests__/svgFormReuse.test.js +102 -0
- package/dist/__tests__/svgFormReuse.test.js.map +1 -0
- package/dist/__tests__/svgVector.test.js +85 -11
- package/dist/__tests__/svgVector.test.js.map +1 -1
- package/dist/__tests__/tableFillSeams.test.d.ts +2 -0
- package/dist/__tests__/tableFillSeams.test.d.ts.map +1 -0
- package/dist/__tests__/tableFillSeams.test.js +72 -0
- package/dist/__tests__/tableFillSeams.test.js.map +1 -0
- package/dist/__tests__/tocLeaderKerning.test.d.ts +2 -0
- package/dist/__tests__/tocLeaderKerning.test.d.ts.map +1 -0
- package/dist/__tests__/tocLeaderKerning.test.js +84 -0
- package/dist/__tests__/tocLeaderKerning.test.js.map +1 -0
- package/dist/__tests__/tocNumberBaseline.test.d.ts +2 -0
- package/dist/__tests__/tocNumberBaseline.test.d.ts.map +1 -0
- package/dist/__tests__/tocNumberBaseline.test.js +72 -0
- package/dist/__tests__/tocNumberBaseline.test.js.map +1 -0
- package/dist/__tests__/tocTagging.test.d.ts +2 -0
- package/dist/__tests__/tocTagging.test.d.ts.map +1 -0
- package/dist/__tests__/tocTagging.test.js +120 -0
- package/dist/__tests__/tocTagging.test.js.map +1 -0
- package/dist/__tests__/trackedLineAlign.test.d.ts +2 -0
- package/dist/__tests__/trackedLineAlign.test.d.ts.map +1 -0
- package/dist/__tests__/trackedLineAlign.test.js +73 -0
- package/dist/__tests__/trackedLineAlign.test.js.map +1 -0
- package/dist/__tests__/uriLinks.test.d.ts +2 -0
- package/dist/__tests__/uriLinks.test.d.ts.map +1 -0
- package/dist/__tests__/uriLinks.test.js +103 -0
- package/dist/__tests__/uriLinks.test.js.map +1 -0
- package/dist/colors.d.ts +18 -3
- package/dist/colors.d.ts.map +1 -1
- package/dist/colors.js +77 -25
- package/dist/colors.js.map +1 -1
- package/dist/fontCache.d.ts +67 -4
- package/dist/fontCache.d.ts.map +1 -1
- package/dist/fontCache.js +200 -23
- package/dist/fontCache.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/pdf-backend/blockRender.d.ts.map +1 -1
- package/dist/pdf-backend/blockRender.js +127 -28
- package/dist/pdf-backend/blockRender.js.map +1 -1
- package/dist/pdf-backend/fallbackSpaces.d.ts +37 -0
- package/dist/pdf-backend/fallbackSpaces.d.ts.map +1 -0
- package/dist/pdf-backend/fallbackSpaces.js +119 -0
- package/dist/pdf-backend/fallbackSpaces.js.map +1 -0
- package/dist/pdf-backend/fontHelpers.d.ts +10 -1
- package/dist/pdf-backend/fontHelpers.d.ts.map +1 -1
- package/dist/pdf-backend/fontHelpers.js +111 -65
- package/dist/pdf-backend/fontHelpers.js.map +1 -1
- package/dist/pdf-backend/headerFooter.d.ts +4 -2
- package/dist/pdf-backend/headerFooter.d.ts.map +1 -1
- package/dist/pdf-backend/headerFooter.js +105 -48
- package/dist/pdf-backend/headerFooter.js.map +1 -1
- package/dist/pdf-backend/index.d.ts +55 -6
- package/dist/pdf-backend/index.d.ts.map +1 -1
- package/dist/pdf-backend/index.js +135 -35
- package/dist/pdf-backend/index.js.map +1 -1
- package/dist/pdf-backend/links.d.ts +82 -1
- package/dist/pdf-backend/links.d.ts.map +1 -1
- package/dist/pdf-backend/links.js +141 -3
- package/dist/pdf-backend/links.js.map +1 -1
- package/dist/pdf-backend/outlines.d.ts.map +1 -1
- package/dist/pdf-backend/outlines.js +7 -0
- package/dist/pdf-backend/outlines.js.map +1 -1
- package/dist/pdf-backend/pageDecorations.d.ts.map +1 -1
- package/dist/pdf-backend/pageDecorations.js +42 -26
- package/dist/pdf-backend/pageDecorations.js.map +1 -1
- package/dist/pdf-backend/primitives.d.ts +61 -1
- package/dist/pdf-backend/primitives.d.ts.map +1 -1
- package/dist/pdf-backend/primitives.js +318 -18
- package/dist/pdf-backend/primitives.js.map +1 -1
- package/dist/pdf-backend/renderResourceBlock.d.ts +3 -1
- package/dist/pdf-backend/renderResourceBlock.d.ts.map +1 -1
- package/dist/pdf-backend/renderResourceBlock.js +97 -19
- package/dist/pdf-backend/renderResourceBlock.js.map +1 -1
- package/dist/pdf-backend/structureFlow.d.ts +70 -3
- package/dist/pdf-backend/structureFlow.d.ts.map +1 -1
- package/dist/pdf-backend/structureFlow.js +209 -27
- package/dist/pdf-backend/structureFlow.js.map +1 -1
- package/dist/pdf-backend/svgVector.d.ts +7 -2
- package/dist/pdf-backend/svgVector.d.ts.map +1 -1
- package/dist/pdf-backend/svgVector.js +157 -72
- package/dist/pdf-backend/svgVector.js.map +1 -1
- package/dist/pdf-backend/tagging.d.ts +1 -1
- package/dist/pdf-backend/tagging.d.ts.map +1 -1
- package/dist/pdf-backend/tagging.js.map +1 -1
- package/dist/worker/client.d.ts +1 -1
- package/dist/worker/client.d.ts.map +1 -1
- package/dist/worker/client.js +8 -0
- package/dist/worker/client.js.map +1 -1
- package/dist/worker/pdf.worker.js +1 -0
- package/dist/worker/pdf.worker.js.map +1 -1
- package/dist/worker/protocol.d.ts +8 -1
- package/dist/worker/protocol.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { PDFArray, PDFDict, PDFDocument, PDFName, PDFNumber, decodePDFRawStream, } from 'pdf-lib';
|
|
4
|
+
import fontkit from '@pdf-lib/fontkit';
|
|
5
|
+
import { buildDocument } from 'postext';
|
|
6
|
+
import { renderToPdf } from '../pdf-backend';
|
|
7
|
+
import { measuredTextOperator } from '../pdf-backend/primitives';
|
|
8
|
+
import { parseFontString } from '../fontString';
|
|
9
|
+
// EF-137: a ragged line with no styled run was painted with one show-text
|
|
10
|
+
// call of its whole text, so the PDF advanced by the embedded face's own
|
|
11
|
+
// widths. A character the face has no glyph for, which the browser had
|
|
12
|
+
// measured in a fallback font, got the width of the face's notdef glyph
|
|
13
|
+
// instead, and every word after it moved. Lines with a bold or italic run
|
|
14
|
+
// were already placed word by word at their measured positions.
|
|
15
|
+
const LORA = fs.readFileSync(new URL('../../../../apps/web/public/fonts/Lora-Regular.ttf', import.meta.url));
|
|
16
|
+
const face = fontkit.create(LORA);
|
|
17
|
+
/** Measures like the browser: a character Lora lacks is set in a fallback
|
|
18
|
+
* font, 0.8 em wide (U+2192 here), while the PDF's notdef glyph advances a
|
|
19
|
+
* full em; the word joiner has no width and the em space is one em
|
|
20
|
+
* (HarfBuzz's fallback spaces). */
|
|
21
|
+
class ChromeLikeCtx {
|
|
22
|
+
font = '';
|
|
23
|
+
measureText(s) {
|
|
24
|
+
const size = parseFontString(this.font)?.sizePx ?? 16;
|
|
25
|
+
let width = 0;
|
|
26
|
+
let run = '';
|
|
27
|
+
const flush = () => {
|
|
28
|
+
if (run)
|
|
29
|
+
width += (face.layout(run).advanceWidth / face.unitsPerEm) * size;
|
|
30
|
+
run = '';
|
|
31
|
+
};
|
|
32
|
+
for (const ch of s) {
|
|
33
|
+
const cp = ch.codePointAt(0);
|
|
34
|
+
if (cp === 0x2060) {
|
|
35
|
+
flush();
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (cp === 0x2003) {
|
|
39
|
+
flush();
|
|
40
|
+
width += size;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (cp > 0x7f && cp !== 0xa0 && !face.hasGlyphForCodePoint(cp)) {
|
|
44
|
+
flush();
|
|
45
|
+
width += size * 0.8;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
run += ch;
|
|
49
|
+
}
|
|
50
|
+
flush();
|
|
51
|
+
return { width };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
globalThis.OffscreenCanvas = class {
|
|
55
|
+
getContext() {
|
|
56
|
+
return new ChromeLikeCtx();
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const pt = (value) => ({ value, unit: 'pt' });
|
|
60
|
+
const config = {
|
|
61
|
+
// 72 dpi: a layout pixel is a PDF point.
|
|
62
|
+
page: { width: pt(400), height: pt(200), dpi: 72, margins: { top: pt(20), bottom: pt(20), left: pt(20), right: pt(20) } },
|
|
63
|
+
layout: { layoutType: 'single' },
|
|
64
|
+
bodyText: { fontFamily: 'Lora', fontSize: pt(10), lineHeight: pt(12), textAlign: 'left', firstLineIndent: pt(0) },
|
|
65
|
+
header: { elements: [] },
|
|
66
|
+
footer: { elements: [] },
|
|
67
|
+
};
|
|
68
|
+
const fontProvider = async () => new Uint8Array(LORA);
|
|
69
|
+
/** The glyphs a viewer paints from the page's text objects, with the pen x
|
|
70
|
+
* each starts at: `Tm` sets the origin, a glyph advances by its `W` width
|
|
71
|
+
* (`DW`, 1000 by default, when `W` does not list it) plus `Tc`, and a `TJ`
|
|
72
|
+
* number moves the pen back by thousandths of the size. */
|
|
73
|
+
function paintedGlyphs(pdf, pageIndex) {
|
|
74
|
+
const page = pdf.getPage(pageIndex);
|
|
75
|
+
const fonts = page.node.Resources().lookup(PDFName.of('Font'), PDFDict);
|
|
76
|
+
const widthsOf = new Map();
|
|
77
|
+
for (const [name, ref] of fonts.entries()) {
|
|
78
|
+
const type0 = pdf.context.lookup(ref, PDFDict);
|
|
79
|
+
const cid = pdf.context.lookup(type0.lookup(PDFName.of('DescendantFonts'), PDFArray).get(0), PDFDict);
|
|
80
|
+
const w = cid.lookup(PDFName.of('W'), PDFArray).asArray();
|
|
81
|
+
const map = new Map();
|
|
82
|
+
for (let i = 0; i < w.length; i += 2) {
|
|
83
|
+
const first = w[i].asNumber();
|
|
84
|
+
const list = pdf.context.lookup(w[i + 1], PDFArray).asArray();
|
|
85
|
+
list.forEach((n, k) => map.set(first + k, n.asNumber()));
|
|
86
|
+
}
|
|
87
|
+
const dw = cid.get(PDFName.of('DW'));
|
|
88
|
+
widthsOf.set(name.decodeText(), { w: map, dw: dw instanceof PDFNumber ? dw.asNumber() : 1000 });
|
|
89
|
+
}
|
|
90
|
+
const contents = page.node.Contents();
|
|
91
|
+
const refs = contents instanceof PDFArray ? contents.asArray() : [contents];
|
|
92
|
+
let content = '';
|
|
93
|
+
for (const ref of refs)
|
|
94
|
+
content += new TextDecoder('latin1').decode(decodePDFRawStream(pdf.context.lookup(ref)).decode());
|
|
95
|
+
const glyphs = [];
|
|
96
|
+
let widths = { w: new Map(), dw: 1000 };
|
|
97
|
+
let size = 0;
|
|
98
|
+
let tc = 0;
|
|
99
|
+
let x = 0;
|
|
100
|
+
const show = (hex) => {
|
|
101
|
+
for (let i = 0; i < hex.length; i += 4) {
|
|
102
|
+
const cid = parseInt(hex.slice(i, i + 4), 16);
|
|
103
|
+
glyphs.push({ cid, x });
|
|
104
|
+
x += ((widths.w.get(cid) ?? widths.dw) / 1000) * size + tc;
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
for (const line of content.split('\n')) {
|
|
108
|
+
let m;
|
|
109
|
+
if ((m = /^\/(\S+) ([\d.]+) Tf$/.exec(line))) {
|
|
110
|
+
widths = widthsOf.get(m[1]);
|
|
111
|
+
size = Number(m[2]);
|
|
112
|
+
}
|
|
113
|
+
else if ((m = /^(-?[\d.]+) Tc$/.exec(line)))
|
|
114
|
+
tc = Number(m[1]);
|
|
115
|
+
else if ((m = /^1 0 0 1 (-?[\d.]+) (-?[\d.]+) Tm$/.exec(line)))
|
|
116
|
+
x = Number(m[1]);
|
|
117
|
+
else if ((m = /^<([0-9A-Fa-f]*)> Tj$/.exec(line)))
|
|
118
|
+
show(m[1]);
|
|
119
|
+
else if ((m = /^\[ (.*) \] TJ$/.exec(line))) {
|
|
120
|
+
for (const part of m[1].split(' ')) {
|
|
121
|
+
if (part.startsWith('<'))
|
|
122
|
+
show(part.slice(1, -1));
|
|
123
|
+
else
|
|
124
|
+
x -= (Number(part) / 1000) * size;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return glyphs;
|
|
129
|
+
}
|
|
130
|
+
/** Where each text segment of `line` starts, as the layout measured it. */
|
|
131
|
+
function measuredStarts(line) {
|
|
132
|
+
const out = [];
|
|
133
|
+
let x = line.bbox.x;
|
|
134
|
+
let index = 0;
|
|
135
|
+
for (const seg of line.segments ?? []) {
|
|
136
|
+
if (seg.kind === 'text')
|
|
137
|
+
out.push({ text: seg.text, x, index });
|
|
138
|
+
x += seg.width;
|
|
139
|
+
index += [...seg.text].length;
|
|
140
|
+
}
|
|
141
|
+
return out;
|
|
142
|
+
}
|
|
143
|
+
async function render(markdown, accessible) {
|
|
144
|
+
const doc = buildDocument({ markdown }, config);
|
|
145
|
+
const line = doc.pages[0].columns[0].blocks[0].lines[0];
|
|
146
|
+
const pdf = await PDFDocument.load(await renderToPdf(doc, { fontProvider, accessible }));
|
|
147
|
+
return { line, glyphs: paintedGlyphs(pdf, 0) };
|
|
148
|
+
}
|
|
149
|
+
describe('a plain ragged line keeps its measured word positions (EF-137)', () => {
|
|
150
|
+
for (const accessible of [false, true]) {
|
|
151
|
+
it(`starts every word where the layout put it after a glyph the face lacks (tagged: ${accessible})`, async () => {
|
|
152
|
+
const { line, glyphs } = await render('From A → B via the long road home', accessible);
|
|
153
|
+
expect(line.segments.every((s) => !s.bold && !s.italic && s.fontString === undefined)).toBe(true);
|
|
154
|
+
// One glyph per character, spaces included (text extraction reads them).
|
|
155
|
+
expect(glyphs).toHaveLength([...line.segments.map((s) => s.text).join('')].length);
|
|
156
|
+
for (const start of measuredStarts(line)) {
|
|
157
|
+
expect(glyphs[start.index].x, start.text).toBeCloseTo(start.x, 2);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
it('still paints the space that ends a ragged line, as one run of the whole text did', async () => {
|
|
162
|
+
const markdown = Array.from({ length: 30 }, (_, i) => `word${i}`).join(' ');
|
|
163
|
+
// The line-by-line breaker keeps the space in the line's text. A ragged
|
|
164
|
+
// paragraph set by Knuth–Plass (`optimalRagged`, the default since
|
|
165
|
+
// rules 7) ends its lines without one, as justified lines always did.
|
|
166
|
+
const doc = buildDocument({ markdown }, { ...config, bodyText: { ...config.bodyText, optimalRagged: false } });
|
|
167
|
+
const lines = doc.pages[0].columns[0].blocks[0].lines;
|
|
168
|
+
expect(lines.length).toBeGreaterThan(1);
|
|
169
|
+
// The segments leave the line-end space out; the line's text keeps it.
|
|
170
|
+
expect(lines[0].text.endsWith(' ')).toBe(true);
|
|
171
|
+
expect(lines[0].segments.map((s) => s.text).join('').endsWith(' ')).toBe(false);
|
|
172
|
+
const pdf = await PDFDocument.load(await renderToPdf(doc, { fontProvider, accessible: true }));
|
|
173
|
+
const glyphs = paintedGlyphs(pdf, 0);
|
|
174
|
+
expect(glyphs).toHaveLength(lines.reduce((n, l) => n + [...l.text].length, 0));
|
|
175
|
+
// And every word still starts where the layout put it.
|
|
176
|
+
let offset = 0;
|
|
177
|
+
for (const line of lines) {
|
|
178
|
+
for (const start of measuredStarts(line))
|
|
179
|
+
expect(glyphs[offset + start.index].x, start.text).toBeCloseTo(start.x, 2);
|
|
180
|
+
offset += [...line.text].length;
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
it('indents a line opened by a word joiner and an em space by one em (the original report)', async () => {
|
|
184
|
+
// Fixed by EF-66 already (spaces the face lacks, invisible characters);
|
|
185
|
+
// kept here as the report's own case.
|
|
186
|
+
const { line, glyphs } = await render('\u2060\u2003prompts in, 173', false);
|
|
187
|
+
const prompts = measuredStarts(line).find((s) => s.text === 'prompts');
|
|
188
|
+
expect(prompts.x).toBeCloseTo(line.bbox.x + 10, 2);
|
|
189
|
+
// The word joiner paints nothing; the em space is the face's space
|
|
190
|
+
// glyph at the line's start, and `prompts` begins one em in.
|
|
191
|
+
expect(glyphs[0].x).toBeCloseTo(line.bbox.x, 2);
|
|
192
|
+
expect(glyphs[1].x).toBeCloseTo(prompts.x, 2);
|
|
193
|
+
expect(glyphs).toHaveLength(1 + 'prompts in, 173'.length);
|
|
194
|
+
expect(glyphs.some((g) => g.cid === 0)).toBe(false);
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
describe('a line with right-to-left letters', () => {
|
|
198
|
+
it('stays one run, which the shaper sets right to left', async () => {
|
|
199
|
+
// Lora has no Hebrew: the browser measured the letters in another font
|
|
200
|
+
// (0.8 em each), the PDF paints notdef glyphs. Word by word, the pieces
|
|
201
|
+
// would be set left to right in logical order, reversing the words.
|
|
202
|
+
const doc = buildDocument({ markdown: 'שלום עולם' }, config);
|
|
203
|
+
const line = doc.pages[0].columns[0].blocks[0].lines[0];
|
|
204
|
+
expect(line.segments.length).toBeGreaterThan(1);
|
|
205
|
+
const pdf = await PDFDocument.load(await renderToPdf(doc, { fontProvider, accessible: false }));
|
|
206
|
+
const page = pdf.getPage(0);
|
|
207
|
+
const contents = page.node.Contents();
|
|
208
|
+
const refs = contents instanceof PDFArray ? contents.asArray() : [contents];
|
|
209
|
+
let content = '';
|
|
210
|
+
for (const ref of refs)
|
|
211
|
+
content += new TextDecoder('latin1').decode(decodePDFRawStream(pdf.context.lookup(ref)).decode());
|
|
212
|
+
const shows = content.split('\n').filter((l) => /T[jJ]$/.test(l));
|
|
213
|
+
expect(shows).toHaveLength(1);
|
|
214
|
+
// One run of glyphs, no pen adjustments between the words.
|
|
215
|
+
expect(shows[0]).toMatch(/^<[0-9A-Fa-f]+> Tj$/);
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
describe('measuredTextOperator', () => {
|
|
219
|
+
it('lands each piece on its measured start, with character spacing counted', async () => {
|
|
220
|
+
const pdf = await PDFDocument.create();
|
|
221
|
+
pdf.registerFontkit(fontkit);
|
|
222
|
+
const font = await pdf.embedFont(LORA, { subset: true });
|
|
223
|
+
const pieces = [
|
|
224
|
+
{ text: 'Two', width: 30 },
|
|
225
|
+
{ text: ' ', width: 5 },
|
|
226
|
+
{ text: 'words', width: 40 },
|
|
227
|
+
];
|
|
228
|
+
const size = 10;
|
|
229
|
+
const tracking = 0.5;
|
|
230
|
+
const op = measuredTextOperator(font, pieces, size, tracking);
|
|
231
|
+
const arg = op.args[0];
|
|
232
|
+
// Walk the array as a viewer does, with the glyphs' own widths.
|
|
233
|
+
const lora = fontkit.create(LORA);
|
|
234
|
+
const widths = [...'Two words'].map((ch) => (lora.layout(ch).glyphs[0].advanceWidth * 1000) / lora.unitsPerEm);
|
|
235
|
+
let x = 0;
|
|
236
|
+
let g = 0;
|
|
237
|
+
const starts = [];
|
|
238
|
+
for (const item of arg.asArray()) {
|
|
239
|
+
if (item instanceof PDFNumber) {
|
|
240
|
+
x -= (item.asNumber() / 1000) * size;
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
const hex = item.asString();
|
|
244
|
+
for (let i = 0; i < hex.length; i += 4) {
|
|
245
|
+
starts.push(x);
|
|
246
|
+
x += (widths[g++] / 1000) * size + tracking;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
expect(starts).toHaveLength(9);
|
|
250
|
+
expect(starts[0]).toBeCloseTo(0, 2);
|
|
251
|
+
expect(starts[3]).toBeCloseTo(30, 2); // the space
|
|
252
|
+
expect(starts[4]).toBeCloseTo(35, 2); // "words"
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
//# sourceMappingURL=measuredLines.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"measuredLines.test.js","sourceRoot":"","sources":["../../src/__tests__/measuredLines.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/metadata.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { PDFDocument } 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
|
+
const fontBytes = fs.readFileSync(new URL('../../../../apps/web/public/fonts/Lora-Regular.ttf', import.meta.url));
|
|
9
|
+
const fontProvider = async () => new Uint8Array(fontBytes);
|
|
10
|
+
const face = fontkit.create(fontBytes);
|
|
11
|
+
class StubCtx {
|
|
12
|
+
font = '';
|
|
13
|
+
measureText(s) {
|
|
14
|
+
const sizePx = parseFontString(this.font)?.sizePx ?? 16;
|
|
15
|
+
const run = face.layout(s);
|
|
16
|
+
return { width: (run.advanceWidth / face.unitsPerEm) * sizePx };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
globalThis.OffscreenCanvas = class {
|
|
20
|
+
getContext() {
|
|
21
|
+
return new StubCtx();
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const pt = (value) => ({ value, unit: 'pt' });
|
|
25
|
+
const config = {
|
|
26
|
+
page: { width: pt(220), height: pt(300), margins: { top: pt(20), bottom: pt(20), left: pt(20), right: pt(20) } },
|
|
27
|
+
headings: { levels: [{ level: 1, breakBefore: { enabled: false } }] },
|
|
28
|
+
};
|
|
29
|
+
// EF-11: YAML frontmatter is typed — `title: 1984` is a number. The PDF
|
|
30
|
+
// title and author must still be set (and the render must not throw).
|
|
31
|
+
describe('PDF metadata from typed frontmatter', () => {
|
|
32
|
+
it('sets the title and author of numeric frontmatter values', async () => {
|
|
33
|
+
const doc = buildDocument({ markdown: '---\ntitle: 1984\nauthor: 2001\n---\n\n# One\n\nText.' }, config);
|
|
34
|
+
for (const accessible of [true, false]) {
|
|
35
|
+
const pdf = await PDFDocument.load(await renderToPdf(doc, { fontProvider, accessible }));
|
|
36
|
+
expect(pdf.getTitle()).toBe('1984');
|
|
37
|
+
expect(pdf.getAuthor()).toBe('2001');
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
it('coerces a non-string title handed straight to the renderer', async () => {
|
|
41
|
+
const doc = buildDocument({ markdown: '# One\n\nText.' }, config);
|
|
42
|
+
const raw = { ...doc, metadata: { title: 1984, author: ['Ana', 'Luis'] } };
|
|
43
|
+
const pdf = await PDFDocument.load(await renderToPdf(raw, { fontProvider }));
|
|
44
|
+
expect(pdf.getTitle()).toBe('1984');
|
|
45
|
+
expect(pdf.getAuthor()).toBe('Ana, Luis');
|
|
46
|
+
// An object has no text form: the first heading titles the PDF instead.
|
|
47
|
+
const odd = { ...doc, metadata: { title: { a: 1 } } };
|
|
48
|
+
expect((await PDFDocument.load(await renderToPdf(odd, { fontProvider }))).getTitle()).toBe('One');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
//# sourceMappingURL=metadata.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.test.js","sourceRoot":"","sources":["../../src/__tests__/metadata.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outlineTitles.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/outlineTitles.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { PDFDict, PDFDocument, PDFHexString, PDFName, PDFString } from 'pdf-lib';
|
|
4
|
+
import { buildDocument } from 'postext';
|
|
5
|
+
import { renderToPdf } from '../pdf-backend';
|
|
6
|
+
// EF-81: a heading set in capitals (`textTransform: 'uppercase'`) is named
|
|
7
|
+
// in the bookmarks as it was written, the way CSS `text-transform` leaves
|
|
8
|
+
// the text itself alone: the case is how the page prints it.
|
|
9
|
+
const fontBytes = fs.readFileSync(new URL('../../../../apps/web/public/fonts/Lora-Regular.ttf', import.meta.url));
|
|
10
|
+
const fontProvider = async () => new Uint8Array(fontBytes);
|
|
11
|
+
class StubCtx {
|
|
12
|
+
font = '';
|
|
13
|
+
measureText(s) {
|
|
14
|
+
return { width: s.length * 7 };
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
globalThis.OffscreenCanvas = class {
|
|
18
|
+
getContext() {
|
|
19
|
+
return new StubCtx();
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
const pt = (value) => ({ value, unit: 'pt' });
|
|
23
|
+
const config = {
|
|
24
|
+
page: { dpi: 72, width: pt(300), height: pt(300), margins: { top: pt(20), bottom: pt(20), left: pt(20), right: pt(20) } },
|
|
25
|
+
layout: { layoutType: 'single' },
|
|
26
|
+
header: { elements: [] },
|
|
27
|
+
footer: { elements: [] },
|
|
28
|
+
headings: { levels: [{ level: 1, breakBefore: { enabled: false } }, { level: 2, numberingTemplate: '{1}.{2}' }] },
|
|
29
|
+
headingStyles: [{ id: 'back', textTransform: 'uppercase', numberingTemplate: '' }],
|
|
30
|
+
};
|
|
31
|
+
async function outlineTitles(markdown, cfg = config) {
|
|
32
|
+
const doc = buildDocument({ markdown }, cfg);
|
|
33
|
+
const pdf = await PDFDocument.load(await renderToPdf(doc, { fontProvider, accessible: false }));
|
|
34
|
+
const titles = [];
|
|
35
|
+
const walk = (first) => {
|
|
36
|
+
for (let item = first; item; item = item.lookupMaybe(PDFName.of('Next'), PDFDict)) {
|
|
37
|
+
const title = item.get(PDFName.of('Title'));
|
|
38
|
+
if (title instanceof PDFHexString || title instanceof PDFString)
|
|
39
|
+
titles.push(title.decodeText());
|
|
40
|
+
walk(item.lookupMaybe(PDFName.of('First'), PDFDict));
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
walk(pdf.catalog.lookup(PDFName.of('Outlines'), PDFDict).lookupMaybe(PDFName.of('First'), PDFDict));
|
|
44
|
+
return titles;
|
|
45
|
+
}
|
|
46
|
+
describe('bookmarks of headings set in capitals (EF-81)', () => {
|
|
47
|
+
it('name the heading as written, while the page prints it in capitals', async () => {
|
|
48
|
+
const markdown = '# Pendulum\n\n## Methods\n\nText.\n\n## Author contributions {style="back"}\n\nText.';
|
|
49
|
+
const doc = buildDocument({ markdown }, config);
|
|
50
|
+
const printed = doc.blocks.filter((b) => b.type === 'heading').map((b) => b.lines.map((l) => l.text).join(' '));
|
|
51
|
+
expect(printed).toContain('AUTHOR CONTRIBUTIONS');
|
|
52
|
+
expect(await outlineTitles(markdown)).toEqual(['Pendulum', '1.1 Methods', 'Author contributions']);
|
|
53
|
+
}, 60_000);
|
|
54
|
+
it('keep the number, which the transform never touched', async () => {
|
|
55
|
+
const cfg = { ...config, headings: { levels: [{ level: 1, breakBefore: { enabled: false }, numberingTemplate: 'Part {1:I}', textTransform: 'uppercase' }] } };
|
|
56
|
+
expect(await outlineTitles('# The sea\n\nText.', cfg)).toEqual(['Part I The sea']);
|
|
57
|
+
}, 60_000);
|
|
58
|
+
});
|
|
59
|
+
//# sourceMappingURL=outlineTitles.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outlineTitles.test.js","sourceRoot":"","sources":["../../src/__tests__/outlineTitles.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdfGenerationConfig.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/pdfGenerationConfig.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { PDFArray, PDFDocument, PDFName, PDFRawStream, decodePDFRawStream } from 'pdf-lib';
|
|
4
|
+
import { buildDocument } from 'postext';
|
|
5
|
+
import { renderToPdf } from '../pdf-backend';
|
|
6
|
+
// EF-124. `config.pdfGeneration` was documented as read by postext-pdf, but
|
|
7
|
+
// only the Sandbox mapped it onto `renderToPdf`'s options. `renderToPdf`
|
|
8
|
+
// now takes each setting from its options first, then from the first
|
|
9
|
+
// document's `pdfGeneration`, then from the defaults.
|
|
10
|
+
const fontBytes = fs.readFileSync(new URL('../../../../apps/web/public/fonts/Lora-Regular.ttf', import.meta.url));
|
|
11
|
+
const fontProvider = async () => new Uint8Array(fontBytes);
|
|
12
|
+
class StubCtx {
|
|
13
|
+
font = '';
|
|
14
|
+
measureText(s) {
|
|
15
|
+
return { width: s.length * 7 };
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
globalThis.OffscreenCanvas = class {
|
|
19
|
+
getContext() {
|
|
20
|
+
return new StubCtx();
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const pt = (value) => ({ value, unit: 'pt' });
|
|
24
|
+
function config(pdfGeneration) {
|
|
25
|
+
return {
|
|
26
|
+
page: { dpi: 72, width: pt(300), height: pt(300), margins: { top: pt(20), bottom: pt(20), left: pt(20), right: pt(20) } },
|
|
27
|
+
layout: { layoutType: 'single' },
|
|
28
|
+
header: { elements: [] },
|
|
29
|
+
footer: { elements: [] },
|
|
30
|
+
headings: { levels: [{ level: 1, breakBefore: { enabled: false } }] },
|
|
31
|
+
...(pdfGeneration ? { pdfGeneration } : {}),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const MARKDOWN = '# Title\n\nSome body text.';
|
|
35
|
+
async function facts(input, options = {}) {
|
|
36
|
+
const pdf = await PDFDocument.load(await renderToPdf(input, { fontProvider, ...options }));
|
|
37
|
+
const contents = pdf.getPage(0).node.Contents();
|
|
38
|
+
const streams = contents instanceof PDFArray ? contents.asArray().map((r) => pdf.context.lookup(r)) : [contents];
|
|
39
|
+
const content = streams
|
|
40
|
+
.map((s) => (s instanceof PDFRawStream ? Buffer.from(decodePDFRawStream(s).decode()).toString('latin1') : ''))
|
|
41
|
+
.join('\n');
|
|
42
|
+
// The fill colour set inside the first text object.
|
|
43
|
+
const text = /BT\s[\s\S]*?\s(rg|k|g)\s/.exec(content);
|
|
44
|
+
return {
|
|
45
|
+
outlines: pdf.catalog.has(PDFName.of('Outlines')),
|
|
46
|
+
tagged: pdf.catalog.has(PDFName.of('StructTreeRoot')),
|
|
47
|
+
textColor: text?.[1],
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
describe('renderToPdf and config.pdfGeneration (EF-124)', () => {
|
|
51
|
+
it('uses the defaults when neither the options nor the config say anything', async () => {
|
|
52
|
+
const doc = buildDocument({ markdown: MARKDOWN }, config());
|
|
53
|
+
expect(doc.config.pdfGeneration).toBeUndefined();
|
|
54
|
+
expect(await facts(doc)).toEqual({ outlines: true, tagged: true, textColor: 'rg' });
|
|
55
|
+
}, 60_000);
|
|
56
|
+
it('reads the settings the options leave out from the document config', async () => {
|
|
57
|
+
const doc = buildDocument({ markdown: MARKDOWN }, config({ forceColorSpace: true, colorSpace: 'cmyk', outlines: false, accessible: false }));
|
|
58
|
+
expect(await facts(doc)).toEqual({ outlines: false, tagged: false, textColor: 'k' });
|
|
59
|
+
}, 60_000);
|
|
60
|
+
it('lets an explicit option win over the config, setting by setting', async () => {
|
|
61
|
+
const doc = buildDocument({ markdown: MARKDOWN }, config({ forceColorSpace: true, colorSpace: 'grayscale', outlines: false, accessible: false }));
|
|
62
|
+
expect(await facts(doc, { colorSpace: 'rgb', outlines: true })).toEqual({ outlines: true, tagged: false, textColor: 'rg' });
|
|
63
|
+
expect(await facts(doc, { accessible: true })).toEqual({ outlines: false, tagged: true, textColor: 'g' });
|
|
64
|
+
}, 60_000);
|
|
65
|
+
it('ignores colorSpace while forceColorSpace is off, as the Sandbox does', async () => {
|
|
66
|
+
const doc = buildDocument({ markdown: MARKDOWN }, config({ colorSpace: 'cmyk' }));
|
|
67
|
+
expect((await facts(doc)).textColor).toBe('rg');
|
|
68
|
+
}, 60_000);
|
|
69
|
+
it('takes a book\'s settings from its first document', async () => {
|
|
70
|
+
const first = buildDocument({ markdown: MARKDOWN }, config({ outlines: false }));
|
|
71
|
+
const second = buildDocument({ markdown: '# Next\n\nMore text.' }, config());
|
|
72
|
+
expect((await facts([first, second])).outlines).toBe(false);
|
|
73
|
+
expect((await facts([second, first])).outlines).toBe(true);
|
|
74
|
+
}, 60_000);
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=pdfGenerationConfig.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdfGenerationConfig.test.js","sourceRoot":"","sources":["../../src/__tests__/pdfGenerationConfig.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdfWorker.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/pdfWorker.test.ts"],"names":[],"mappings":""}
|