postext-pdf 1.4.1 → 1.5.0
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,48 @@
|
|
|
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 face = fontkit.create(fontBytes);
|
|
10
|
+
class StubCtx {
|
|
11
|
+
font = '';
|
|
12
|
+
measureText(s) {
|
|
13
|
+
const sizePx = parseFontString(this.font)?.sizePx ?? 16;
|
|
14
|
+
const run = face.layout(s);
|
|
15
|
+
return { width: (run.advanceWidth / face.unitsPerEm) * sizePx };
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
globalThis.OffscreenCanvas = class {
|
|
19
|
+
getContext() {
|
|
20
|
+
return new StubCtx();
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const pt = (value) => ({ value, unit: 'pt' });
|
|
24
|
+
// EF-13: a CSS font stack in a `fontFamily` sets the text in its first
|
|
25
|
+
// family — the PDF asks the provider for that family, the same one canvas
|
|
26
|
+
// and HTML measure and paint with.
|
|
27
|
+
describe('font stack in fontFamily', () => {
|
|
28
|
+
it('asks the font provider for the first family of the stack only', async () => {
|
|
29
|
+
const asked = new Set();
|
|
30
|
+
const fontProvider = async (family) => {
|
|
31
|
+
asked.add(family);
|
|
32
|
+
if (family.includes(','))
|
|
33
|
+
throw new Error(`no font ${family}`);
|
|
34
|
+
return new Uint8Array(fontBytes);
|
|
35
|
+
};
|
|
36
|
+
const config = {
|
|
37
|
+
page: { width: pt(220), height: pt(300), margins: { top: pt(20), bottom: pt(20), left: pt(20), right: pt(20) } },
|
|
38
|
+
bodyText: { fontFamily: "'Lora', Georgia, serif" },
|
|
39
|
+
headings: { fontFamily: 'Lora, serif', levels: [{ level: 1, breakBefore: { enabled: false } }] },
|
|
40
|
+
orderedLists: { fontFamily: 'Lora,serif' },
|
|
41
|
+
};
|
|
42
|
+
const doc = buildDocument({ markdown: '# Title\n\nSome **bold** and *italic* text.\n\n1. one' }, config);
|
|
43
|
+
const pdf = await PDFDocument.load(await renderToPdf(doc, { fontProvider }));
|
|
44
|
+
expect(pdf.getPageCount()).toBe(1);
|
|
45
|
+
expect([...asked].filter((f) => f.includes('Lora'))).toEqual(['Lora']);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
//# sourceMappingURL=fontStack.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fontStack.test.js","sourceRoot":"","sources":["../../src/__tests__/fontStack.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import {
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { PDFDict, PDFDocument, PDFName, PDFNumber } from 'pdf-lib';
|
|
4
|
+
import fontkit from '@pdf-lib/fontkit';
|
|
3
5
|
import { FontCache } from '../fontCache';
|
|
4
6
|
import { renderHeaderFooterSlot } from '../pdf-backend/headerFooter';
|
|
7
|
+
import { collectFontStrings } from '../pdf-backend/fontHelpers';
|
|
5
8
|
import { makeScale } from '../pdf-backend/primitives';
|
|
6
9
|
/** The page's content stream operators, before pdf-lib deflates them. */
|
|
7
10
|
function pageContent(page) {
|
|
@@ -65,4 +68,83 @@ describe('design boxes in the PDF backend', () => {
|
|
|
65
68
|
expect(content).toContain('50 20 l');
|
|
66
69
|
});
|
|
67
70
|
});
|
|
71
|
+
// Kerned TrueType faces from the demo app's static fonts (OFL).
|
|
72
|
+
const REGULAR = readFileSync(new URL('../../../../apps/web/public/fonts/Fraunces-Regular.ttf', import.meta.url));
|
|
73
|
+
const BOLD = readFileSync(new URL('../../../../apps/web/public/fonts/Fraunces-Bold.ttf', import.meta.url));
|
|
74
|
+
describe('design text runs and outlines in the PDF backend (EF-25)', () => {
|
|
75
|
+
const block = (extra) => ({
|
|
76
|
+
kind: 'text',
|
|
77
|
+
bbox: { x: 72, y: 72, width: 300, height: 30 },
|
|
78
|
+
fontString: '20px Fraunces',
|
|
79
|
+
color: '#111111',
|
|
80
|
+
lines: [{
|
|
81
|
+
text: 'Ana bold2', xOffset: 0, baselineY: 96, width: 120,
|
|
82
|
+
runs: [
|
|
83
|
+
{ text: 'Ana ', fontString: '20px Fraunces', width: 40 },
|
|
84
|
+
{ text: 'bold', fontString: '700 20px Fraunces', width: 50 },
|
|
85
|
+
{ text: '2', fontString: '11.66px Fraunces', width: 7, baselineShift: -6.66 },
|
|
86
|
+
],
|
|
87
|
+
}],
|
|
88
|
+
clip: false,
|
|
89
|
+
...extra,
|
|
90
|
+
});
|
|
91
|
+
async function render(slot) {
|
|
92
|
+
const pdfDoc = await PDFDocument.create();
|
|
93
|
+
pdfDoc.registerFontkit(fontkit);
|
|
94
|
+
const page = pdfDoc.addPage([612, 792]);
|
|
95
|
+
const ctx = { page, pageHeightPt: 792, scale: makeScale(72), colorSpace: 'rgb' };
|
|
96
|
+
const fontCache = new FontCache(pdfDoc, async (_family, weight) => new Uint8Array(weight >= 700 ? BOLD : REGULAR));
|
|
97
|
+
const doc = { blocks: [], pages: [{ columns: [], header: slot }] };
|
|
98
|
+
const fonts = collectFontStrings(doc);
|
|
99
|
+
await fontCache.preloadFontStrings(fonts);
|
|
100
|
+
renderHeaderFooterSlot(ctx, slot, fontCache);
|
|
101
|
+
return { content: pageContent(page), fonts };
|
|
102
|
+
}
|
|
103
|
+
it('asks for the fonts of every run and draws each run in its font, size and shift', async () => {
|
|
104
|
+
const { content, fonts } = await render({ bbox: { x: 0, y: 0, width: 612, height: 792 }, blocks: [block({})] });
|
|
105
|
+
expect(fonts).toEqual(expect.arrayContaining(['20px Fraunces', '700 20px Fraunces', '11.66px Fraunces']));
|
|
106
|
+
const tf = [...content.matchAll(/\/(\S+) ([\d.]+) Tf/g)].map((m) => [m[1], m[2]]);
|
|
107
|
+
expect(tf).toHaveLength(3);
|
|
108
|
+
expect(tf[0][0]).not.toBe(tf[1][0]); // bold is its own face
|
|
109
|
+
expect(tf.map((t) => t[1])).toEqual(['20', '20', '11.66']);
|
|
110
|
+
// Runs follow one another on the baseline (792 - 96 = 696); the script
|
|
111
|
+
// is raised by its shift.
|
|
112
|
+
const tm = [...content.matchAll(/1 0 0 1 ([\d.]+) ([\d.]+) Tm/g)].map((m) => [Number(m[1]), Number(m[2])]);
|
|
113
|
+
expect(tm).toEqual([[72, 696], [112, 696], [162, 702.66]]);
|
|
114
|
+
expect(content).not.toMatch(/ Tr\n/);
|
|
115
|
+
});
|
|
116
|
+
it('strokes the glyphs over the fill (render mode 2), or alone for hollow letters (mode 1)', async () => {
|
|
117
|
+
const stroke = { widthPx: 2, color: '#aa0000' };
|
|
118
|
+
const filled = await render({ bbox: { x: 0, y: 0, width: 612, height: 792 }, blocks: [block({ stroke, lines: [{ text: '1863', xOffset: 0, baselineY: 96, width: 60 }] })] });
|
|
119
|
+
expect(filled.content).toMatch(/0\.6\d+ 0 0 RG\n2 w\n2 Tr\n/);
|
|
120
|
+
const hollow = await render({ bbox: { x: 0, y: 0, width: 612, height: 792 }, blocks: [block({ stroke: { ...stroke, hollow: true } })] });
|
|
121
|
+
expect(hollow.content.match(/1 Tr\n/g)).toHaveLength(3);
|
|
122
|
+
});
|
|
123
|
+
it('paints a negative tracking (a tightened display title) with its character spacing, and resets it (EF-82)', async () => {
|
|
124
|
+
const plain = { text: 'Title', xOffset: 0, baselineY: 96, width: 60 };
|
|
125
|
+
const tight = await render({ bbox: { x: 0, y: 0, width: 612, height: 792 }, blocks: [block({ letterSpacingPx: -0.3, lines: [plain] })] });
|
|
126
|
+
const spacings = [...tight.content.matchAll(/(-?[\d.]+) Tc/g)].map((m) => Number(m[1]));
|
|
127
|
+
expect(spacings).toEqual([-0.3, 0]);
|
|
128
|
+
const untracked = await render({ bbox: { x: 0, y: 0, width: 612, height: 792 }, blocks: [block({ lines: [plain] })] });
|
|
129
|
+
expect(untracked.content).not.toMatch(/ Tc\n/);
|
|
130
|
+
});
|
|
131
|
+
it('strokes with the outline colour\'s own alpha, the fill with the text\'s (EF-30 with EF-25)', async () => {
|
|
132
|
+
const pdfDoc = await PDFDocument.create();
|
|
133
|
+
pdfDoc.registerFontkit(fontkit);
|
|
134
|
+
const page = pdfDoc.addPage([612, 792]);
|
|
135
|
+
const ctx = { page, pageHeightPt: 792, scale: makeScale(72), colorSpace: 'rgb' };
|
|
136
|
+
const fontCache = new FontCache(pdfDoc, async () => new Uint8Array(REGULAR));
|
|
137
|
+
const slot = { bbox: { x: 0, y: 0, width: 612, height: 792 }, blocks: [block({ stroke: { widthPx: 2, color: '#aa000080' }, lines: [{ text: '1863', xOffset: 0, baselineY: 96, width: 60 }] })] };
|
|
138
|
+
await fontCache.preloadFontStrings(collectFontStrings({ blocks: [], pages: [{ columns: [], header: slot }] }));
|
|
139
|
+
renderHeaderFooterSlot(ctx, slot, fontCache);
|
|
140
|
+
// One graphics state, set right before the outline operators.
|
|
141
|
+
const name = /\/(\S+) gs\n[^\n]*RG\n2 w\n2 Tr\n/.exec(pageContent(page))?.[1];
|
|
142
|
+
expect(name).toBeDefined();
|
|
143
|
+
const states = page.node.Resources().lookup(PDFName.of('ExtGState'), PDFDict);
|
|
144
|
+
const state = states.lookup(PDFName.of(name), PDFDict);
|
|
145
|
+
// Fill opaque (no `ca`, or 1), stroke at the outline's alpha.
|
|
146
|
+
expect(state.lookup(PDFName.of('ca'), PDFNumber).asNumber()).toBe(1);
|
|
147
|
+
expect(state.lookup(PDFName.of('CA'), PDFNumber).asNumber()).toBeCloseTo(0x80 / 255, 2);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
68
150
|
//# sourceMappingURL=headerFooter.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headerFooter.test.js","sourceRoot":"","sources":["../../src/__tests__/headerFooter.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAgB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"headerFooter.test.js","sourceRoot":"","sources":["../../src/__tests__/headerFooter.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headingAlign.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/headingAlign.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,66 @@
|
|
|
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
|
+
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 = (textAlign) => ({
|
|
26
|
+
page: { width: pt(300), height: pt(200), dpi: 72, margins: { top: pt(20), bottom: pt(20), left: pt(20), right: pt(20) } },
|
|
27
|
+
layout: { layoutType: 'single' },
|
|
28
|
+
headings: { textAlign, levels: [{ level: 1, breakBefore: { enabled: false } }] },
|
|
29
|
+
});
|
|
30
|
+
async function contentOf(doc) {
|
|
31
|
+
const pdf = await PDFDocument.load(await renderToPdf(doc, { fontProvider, accessible: false }));
|
|
32
|
+
const contents = pdf.getPage(0).node.Contents();
|
|
33
|
+
const refs = contents instanceof PDFArray ? contents.asArray() : [contents];
|
|
34
|
+
return refs
|
|
35
|
+
.map((ref) => {
|
|
36
|
+
const s = pdf.context.lookup(ref);
|
|
37
|
+
return s instanceof PDFRawStream ? new TextDecoder('latin1').decode(decodePDFRawStream(s).decode()) : '';
|
|
38
|
+
})
|
|
39
|
+
.join('\n');
|
|
40
|
+
}
|
|
41
|
+
/** The x (pt) of the first text object on the heading's baseline. */
|
|
42
|
+
async function headingX(doc) {
|
|
43
|
+
const heading = doc.blocks.find((b) => b.type === 'heading');
|
|
44
|
+
const y = doc.pages[0].height - heading.lines[0].baseline; // 72 dpi: px = pt
|
|
45
|
+
const content = await contentOf(doc);
|
|
46
|
+
for (const m of content.matchAll(/1 0 0 1 ([\d.-]+) ([\d.-]+) Tm/g)) {
|
|
47
|
+
if (Math.abs(Number(m[2]) - y) < 0.01)
|
|
48
|
+
return Number(m[1]);
|
|
49
|
+
}
|
|
50
|
+
throw new Error('heading text not found');
|
|
51
|
+
}
|
|
52
|
+
describe('headings.textAlign in the PDF (EF-47)', () => {
|
|
53
|
+
it('centres and right-aligns heading lines within the heading box', async () => {
|
|
54
|
+
for (const [align, share] of [['left', 0], ['center', 0.5], ['right', 1]]) {
|
|
55
|
+
const doc = buildDocument({ markdown: '# Title\n\nText.' }, config(align));
|
|
56
|
+
const heading = doc.blocks.find((b) => b.type === 'heading');
|
|
57
|
+
const slack = heading.bbox.width - heading.lines[0].bbox.width;
|
|
58
|
+
expect(await headingX(doc)).toBeCloseTo(heading.bbox.x + slack * share, 1);
|
|
59
|
+
// A line without segments takes the same position.
|
|
60
|
+
for (const line of heading.lines)
|
|
61
|
+
delete line.segments;
|
|
62
|
+
expect(await headingX(doc)).toBeCloseTo(heading.bbox.x + slack * share, 1);
|
|
63
|
+
}
|
|
64
|
+
}, 60_000);
|
|
65
|
+
});
|
|
66
|
+
//# sourceMappingURL=headingAlign.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headingAlign.test.js","sourceRoot":"","sources":["../../src/__tests__/headingAlign.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hiddenHeadings.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/hiddenHeadings.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { describe, it, expect, beforeAll } from 'vitest';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { execFileSync } from 'node:child_process';
|
|
6
|
+
import { PDFDict, PDFDocument, PDFHexString, PDFName, PDFString } from 'pdf-lib';
|
|
7
|
+
import fontkit from '@pdf-lib/fontkit';
|
|
8
|
+
import { buildDocument } from 'postext';
|
|
9
|
+
import { renderToPdf } from '../pdf-backend';
|
|
10
|
+
import { parseFontString } from '../fontString';
|
|
11
|
+
const fontBytes = fs.readFileSync(new URL('../../../../apps/web/public/fonts/Lora-Regular.ttf', import.meta.url));
|
|
12
|
+
const fontProvider = async () => new Uint8Array(fontBytes);
|
|
13
|
+
const face = fontkit.create(fontBytes);
|
|
14
|
+
class StubCtx {
|
|
15
|
+
font = '';
|
|
16
|
+
measureText(s) {
|
|
17
|
+
const sizePx = parseFontString(this.font)?.sizePx ?? 16;
|
|
18
|
+
const run = face.layout(s);
|
|
19
|
+
return { width: (run.advanceWidth / face.unitsPerEm) * sizePx };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
globalThis.OffscreenCanvas = class {
|
|
23
|
+
getContext() {
|
|
24
|
+
return new StubCtx();
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const pt = (value) => ({ value, unit: 'pt' });
|
|
28
|
+
// EF-26: a structural heading prints nothing but still structures the book.
|
|
29
|
+
const config = {
|
|
30
|
+
page: { width: pt(300), height: pt(240), margins: { top: pt(20), bottom: pt(20), left: pt(20), right: pt(20) } },
|
|
31
|
+
locale: 'en-us',
|
|
32
|
+
headings: { levels: [{ level: 1, span: 'page', breakBefore: { enabled: true, parity: 'any' } }] },
|
|
33
|
+
headingStyles: [{ id: 'silent', hidden: true, numbered: false }],
|
|
34
|
+
// No running heads: they would print the chapter title.
|
|
35
|
+
header: { elements: [] },
|
|
36
|
+
footer: { elements: [] },
|
|
37
|
+
};
|
|
38
|
+
const markdown = '# Opening\n\nFirst chapter text.\n\n# Dedication {style="silent"}\n\nTo the lantern keepers.';
|
|
39
|
+
// The same inside a callout box.
|
|
40
|
+
const calloutMarkdown = ':::callout{type="note"}\n## Secret {hidden="true"}\n\nInside the box.\n:::\n\nAfter the box.';
|
|
41
|
+
let bytes;
|
|
42
|
+
let calloutBytes;
|
|
43
|
+
let pdf;
|
|
44
|
+
beforeAll(async () => {
|
|
45
|
+
const doc = buildDocument({ markdown, metadata: { title: 'Hidden headings' } }, config);
|
|
46
|
+
bytes = await renderToPdf(doc, { fontProvider });
|
|
47
|
+
pdf = await PDFDocument.load(bytes);
|
|
48
|
+
const boxed = buildDocument({ markdown: calloutMarkdown, metadata: { title: 'Hidden headings' } }, { ...config, calloutStyles: [{ id: 'note', span: 'column' }] });
|
|
49
|
+
calloutBytes = await renderToPdf(boxed, { fontProvider });
|
|
50
|
+
}, 60_000);
|
|
51
|
+
function outlineTitles() {
|
|
52
|
+
const outlines = pdf.catalog.lookup(PDFName.of('Outlines'), PDFDict);
|
|
53
|
+
const titles = [];
|
|
54
|
+
let item = outlines.lookupMaybe(PDFName.of('First'), PDFDict);
|
|
55
|
+
while (item) {
|
|
56
|
+
const title = item.get(PDFName.of('Title'));
|
|
57
|
+
if (title instanceof PDFHexString || title instanceof PDFString)
|
|
58
|
+
titles.push(title.decodeText());
|
|
59
|
+
item = item.lookupMaybe(PDFName.of('Next'), PDFDict);
|
|
60
|
+
}
|
|
61
|
+
return titles;
|
|
62
|
+
}
|
|
63
|
+
function pdfText(data) {
|
|
64
|
+
const file = path.join(os.tmpdir(), `postext-hidden-${process.pid}.pdf`);
|
|
65
|
+
fs.writeFileSync(file, data);
|
|
66
|
+
const text = execFileSync('pdftotext', ['-raw', file, '-'], { encoding: 'utf8' });
|
|
67
|
+
fs.unlinkSync(file);
|
|
68
|
+
return text;
|
|
69
|
+
}
|
|
70
|
+
const hasPdftotext = (() => {
|
|
71
|
+
try {
|
|
72
|
+
execFileSync('pdftotext', ['-v'], { stdio: 'ignore' });
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
})();
|
|
79
|
+
describe('hidden headings in the PDF', () => {
|
|
80
|
+
it('keep their bookmark', () => {
|
|
81
|
+
expect(outlineTitles()).toEqual(['Opening', 'Dedication']);
|
|
82
|
+
});
|
|
83
|
+
it.skipIf(!hasPdftotext)('print no text of their own', () => {
|
|
84
|
+
const text = pdfText(bytes);
|
|
85
|
+
expect(text).toContain('Opening');
|
|
86
|
+
expect(text).toContain('To the lantern keepers.');
|
|
87
|
+
expect(text).not.toContain('Dedication');
|
|
88
|
+
});
|
|
89
|
+
it.skipIf(!hasPdftotext)('print no text inside a callout either', () => {
|
|
90
|
+
const text = pdfText(calloutBytes);
|
|
91
|
+
expect(text).toContain('Inside the box.');
|
|
92
|
+
expect(text).toContain('After the box.');
|
|
93
|
+
expect(text).not.toContain('Secret');
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
//# sourceMappingURL=hiddenHeadings.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hiddenHeadings.test.js","sourceRoot":"","sources":["../../src/__tests__/hiddenHeadings.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lineTracking.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/lineTracking.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { PDFArray, PDFDocument, PDFRawStream, decodePDFRawStream } from 'pdf-lib';
|
|
4
|
+
import { buildDocument } from 'postext';
|
|
5
|
+
import { renderToPdf } from '../pdf-backend';
|
|
6
|
+
// Tracking the engine measured a line with is painted with the matching
|
|
7
|
+
// character spacing (`Tc`): a line's own justification tracking
|
|
8
|
+
// (`bodyText.maxJustifyTracking`, EF-65) on top of its block's, and a block
|
|
9
|
+
// tracked negative (a runt set short) as well as positive.
|
|
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
|
+
// Every character, the space included, is 7 px wide.
|
|
13
|
+
class StubCtx {
|
|
14
|
+
font = '';
|
|
15
|
+
measureText(s) {
|
|
16
|
+
return { width: s.length * 7 };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
globalThis.OffscreenCanvas = class {
|
|
20
|
+
getContext() {
|
|
21
|
+
return new StubCtx();
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const pt = (value) => ({ value, unit: 'pt' });
|
|
25
|
+
const config = (maxJustifyTracking) => ({
|
|
26
|
+
page: { width: pt(112), height: pt(200), dpi: 72, margins: { top: pt(10), bottom: pt(10), left: pt(10), right: pt(10) } },
|
|
27
|
+
layout: { layoutType: 'single' },
|
|
28
|
+
header: { elements: [] },
|
|
29
|
+
footer: { elements: [] },
|
|
30
|
+
bodyText: { fontFamily: 'Lora', fontSize: pt(16), lineHeight: pt(20), firstLineIndent: pt(0), hyphenation: { enabled: false }, ...(maxJustifyTracking !== undefined ? { maxJustifyTracking } : {}) },
|
|
31
|
+
});
|
|
32
|
+
async function contentOf(doc) {
|
|
33
|
+
const pdf = await PDFDocument.load(await renderToPdf(doc, { fontProvider, accessible: false }));
|
|
34
|
+
const contents = pdf.getPage(0).node.Contents();
|
|
35
|
+
const refs = contents instanceof PDFArray ? contents.asArray() : [contents];
|
|
36
|
+
return refs
|
|
37
|
+
.map((ref) => {
|
|
38
|
+
const s = pdf.context.lookup(ref);
|
|
39
|
+
return s instanceof PDFRawStream ? new TextDecoder('latin1').decode(decodePDFRawStream(s).decode()) : '';
|
|
40
|
+
})
|
|
41
|
+
.join('\n');
|
|
42
|
+
}
|
|
43
|
+
const spacings = (content) => [...content.matchAll(/(-?[\d.]+) Tc/g)].map((m) => Number(m[1]));
|
|
44
|
+
describe('line tracking in the PDF', () => {
|
|
45
|
+
it('paints a tracked line with its character spacing, and resets it', async () => {
|
|
46
|
+
// 72 dpi: 1 px = 1 pt. 50‰ of 16 px is 0.8 px a letter.
|
|
47
|
+
const doc = buildDocument({ markdown: 'aaaaa bbbbb cccccccccc' }, config(50));
|
|
48
|
+
expect(doc.blocks.find((b) => b.type === 'paragraph').lines[0].letterSpacing).toBeCloseTo(0.8, 5);
|
|
49
|
+
expect(spacings(await contentOf(doc))).toEqual([0.8, 0]);
|
|
50
|
+
// Off by default: no character spacing at all.
|
|
51
|
+
expect(spacings(await contentOf(buildDocument({ markdown: 'aaaaa bbbbb cccccccccc' }, config())))).toEqual([]);
|
|
52
|
+
}, 60_000);
|
|
53
|
+
it('paints a heading level\'s letterSpacing, measured into its lines (EF-83)', async () => {
|
|
54
|
+
const doc = buildDocument({ markdown: '## Methods\n\nText.' }, { ...config(), headings: { levels: [{ level: 1, breakBefore: { enabled: false } }, { level: 2, letterSpacing: pt(2) }] } });
|
|
55
|
+
expect(doc.blocks.find((b) => b.type === 'heading').letterSpacing).toBeCloseTo(2, 5);
|
|
56
|
+
expect(spacings(await contentOf(doc))).toEqual([2, 0]);
|
|
57
|
+
}, 60_000);
|
|
58
|
+
it('adds a line\'s tracking to its block\'s, and paints a negative block tracking', async () => {
|
|
59
|
+
const doc = buildDocument({ markdown: 'aaaaa bbbbb cccccccccc' }, config(50));
|
|
60
|
+
const block = doc.blocks.find((b) => b.type === 'paragraph');
|
|
61
|
+
block.letterSpacing = -0.2;
|
|
62
|
+
const [first, second] = spacings(await contentOf(doc)).filter((v) => v !== 0);
|
|
63
|
+
expect(first).toBeCloseTo(0.6, 5);
|
|
64
|
+
expect(second).toBeCloseTo(-0.2, 5);
|
|
65
|
+
}, 60_000);
|
|
66
|
+
it('paints a table\'s tracked header cells with their spacing and the body without (EF-174)', async () => {
|
|
67
|
+
const table = {
|
|
68
|
+
id: 't', typeId: 'table', kind: 'table', createdAt: 0, updatedAt: 0,
|
|
69
|
+
placement: { position: 'here' },
|
|
70
|
+
table: { model: { headerRowCount: 1, rows: [[{ content: 'Dish' }, { content: 'Cost' }], [{ content: 'Soup' }, { content: '4' }]] } },
|
|
71
|
+
};
|
|
72
|
+
const wide = { ...config(), page: { ...config().page, width: pt(300) } };
|
|
73
|
+
const tracked = buildDocument({ markdown: '::resource{id="t"}\n', resources: [table] }, { ...wide, tableStyle: { headerLetterSpacing: pt(1.5) } });
|
|
74
|
+
// Two header cells: each painted at 1.5 pt, then reset.
|
|
75
|
+
expect(spacings(await contentOf(tracked))).toEqual([1.5, 0, 1.5, 0]);
|
|
76
|
+
const plain = buildDocument({ markdown: '::resource{id="t"}\n', resources: [table] }, wide);
|
|
77
|
+
expect(spacings(await contentOf(plain))).toEqual([]);
|
|
78
|
+
}, 60_000);
|
|
79
|
+
});
|
|
80
|
+
//# sourceMappingURL=lineTracking.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lineTracking.test.js","sourceRoot":"","sources":["../../src/__tests__/lineTracking.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAExC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,wEAAwE;AACxE,gEAAgE;AAChE,4EAA4E;AAC5E,2DAA2D;AAE3D,MAAM,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,oDAAoD,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAClH,MAAM,YAAY,GAAG,KAAK,IAAI,EAAE,CAAC,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC;AAE3D,qDAAqD;AACrD,MAAM,OAAO;IACX,IAAI,GAAG,EAAE,CAAC;IACV,WAAW,CAAC,CAAS;QACnB,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;IACjC,CAAC;CACF;AACA,UAAsD,CAAC,eAAe,GAAG;IACxE,UAAU;QACR,OAAO,IAAI,OAAO,EAAE,CAAC;IACvB,CAAC;CACF,CAAC;AAEF,MAAM,EAAE,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAa,EAAE,CAAC,CAAC;AAC/D,MAAM,MAAM,GAAG,CAAC,kBAA2B,EAAiB,EAAE,CAAC,CAAC;IAC9D,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;IACzH,MAAM,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE;IAChC,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;IACxB,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;IACxB,QAAQ,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,eAAe,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,GAAG,CAAC,kBAAkB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE;CACrM,CAAC,CAAC;AAEH,KAAK,UAAU,SAAS,CAAC,GAAgB;IACvC,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,MAAM,WAAW,CAAC,GAAG,EAAE,EAAE,YAAY,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAChG,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;IAChD,MAAM,IAAI,GAAG,QAAQ,YAAY,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC5E,OAAO,IAAI;SACR,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACX,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAClC,OAAO,CAAC,YAAY,YAAY,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3G,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,MAAM,QAAQ,GAAG,CAAC,OAAe,EAAY,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEjH,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QAC/E,wDAAwD;QACxD,MAAM,GAAG,GAAG,aAAa,CAAC,EAAE,QAAQ,EAAE,wBAAwB,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9E,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAE,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,aAAa,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACpG,MAAM,CAAC,QAAQ,CAAC,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QACzD,+CAA+C;QAC/C,MAAM,CAAC,QAAQ,CAAC,MAAM,SAAS,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,wBAAwB,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACjH,CAAC,EAAE,MAAM,CAAC,CAAC;IAEX,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;QACxF,MAAM,GAAG,GAAG,aAAa,CACvB,EAAE,QAAQ,EAAE,qBAAqB,EAAE,EACnC,EAAE,GAAG,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,WAAW,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAC3H,CAAC;QACF,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAE,CAAC,aAAa,CAAC,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACtF,MAAM,CAAC,QAAQ,CAAC,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACzD,CAAC,EAAE,MAAM,CAAC,CAAC;IAEX,EAAE,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;QAC7F,MAAM,GAAG,GAAG,aAAa,CAAC,EAAE,QAAQ,EAAE,wBAAwB,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9E,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAE,CAAC;QAC9D,KAAK,CAAC,aAAa,GAAG,CAAC,GAAG,CAAC;QAC3B,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9E,MAAM,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACtC,CAAC,EAAE,MAAM,CAAC,CAAC;IAEX,EAAE,CAAC,yFAAyF,EAAE,KAAK,IAAI,EAAE;QACvG,MAAM,KAAK,GAAG;YACZ,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAgB,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC;YAC5E,SAAS,EAAE,EAAE,QAAQ,EAAE,MAAe,EAAE;YACxC,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,cAAc,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE;SACrI,CAAC;QACF,MAAM,IAAI,GAAkB,EAAE,GAAG,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACxF,MAAM,OAAO,GAAG,aAAa,CAAC,EAAE,QAAQ,EAAE,sBAAsB,EAAE,SAAS,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,EAAE,mBAAmB,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QACnJ,wDAAwD;QACxD,MAAM,CAAC,QAAQ,CAAC,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QACrE,MAAM,KAAK,GAAG,aAAa,CAAC,EAAE,QAAQ,EAAE,sBAAsB,EAAE,SAAS,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC5F,MAAM,CAAC,QAAQ,CAAC,MAAM,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACvD,CAAC,EAAE,MAAM,CAAC,CAAC;AACb,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"measuredLines.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/measuredLines.test.ts"],"names":[],"mappings":""}
|