@reportwright/engine 0.11.0 → 0.12.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,38 @@
1
+ // @ts-check
2
+ // A paint worker of a streaming PDF (pdfstream.js, opts.parallel): it lays out the windows of rows it is sent
3
+ // (engine/paged.js jobs, with the pages already counted) and paints their pages with the same painter and names as the
4
+ // writer, then sends back each page's compressed content stream and what it used (fonts, glyphs, opacities). Node only.
5
+ import { render, FontStore, __streamPaint } from './index.js';
6
+ const { createPdfStream, paintPage, paintEnv, latin1 } = __streamPaint;
7
+
8
+ const proc = /** @type {any} */ (globalThis).process;
9
+ const { parentPort, workerData } = proc.getBuiltinModule('node:worker_threads');
10
+ const zlib = proc.getBuiltinModule('node:zlib');
11
+ const bytes = new Map(workerData.fonts);
12
+ const fontStore = new FontStore(async (k) => {
13
+ const b = bytes.get(k);
14
+ if (!b) throw new Error(`The font "${k}" was not sent to the paint worker`);
15
+ return b;
16
+ });
17
+
18
+ parentPort.on('message', async (/** @type {any} */ job) => {
19
+ try {
20
+ const t0 = Date.now();
21
+ const m = await render(job.def, { ...job.opts, fontStore, sources: { __rows: { rows: job.rows } }, pageWindow: job.pageWindow });
22
+ // a writer of its own for the names and glyphs (nothing is written): the pages' links name pages by placeholder
23
+ const rec = createPdfStream({ write() {} }, { fontStore });
24
+ const env = paintEnv(rec, fontStore, { drillBase: job.drillBase, pageRef: (i) => `@@P${i}@@` });
25
+ const pages = [], transfer = [];
26
+ for (let k = 0; k < Math.min(job.keep, m.pages.length); k++) {
27
+ const pg = m.pages[k];
28
+ const { content, annots } = paintPage(pg, pg.height ?? job.height, env);
29
+ const z = new Uint8Array(zlib.deflateSync(latin1(content), { level: 9 })); // as pdfpaint.js's deflate
30
+ transfer.push(z.buffer);
31
+ pages.push({ deflated: z, annots, width: pg.width, height: pg.height, firstRow: pg.firstRow, rowHead: pg.rowHead, headLevel: pg.headLevel });
32
+ }
33
+ parentPort.postMessage({ id: job.id, count: m.pages.length, nextFirst: m.pages[job.keep]?.firstRow, pages, used: rec.used(),
34
+ shaped: [...env.shaped].map(([k, g]) => [k, [...g]]), bookmarks: m.bookmarks, headings: m.headings, warnings: m.warnings, ms: Date.now() - t0 }, transfer);
35
+ } catch (e) {
36
+ parentPort.postMessage({ id: job.id, error: { message: String(/** @type {any} */ (e)?.message || e), status: /** @type {any} */ (e)?.status, timeout: /** @type {any} */ (e)?.timeout } });
37
+ }
38
+ });
@@ -48,11 +48,47 @@ export function exportDocx(model: any, options?: NonNullable<Parameters<typeof e
48
48
  export function exportPptx(model: any, options?: NonNullable<Parameters<typeof exportPptxFull>[1]> & {
49
49
  fonts?: FontStore;
50
50
  }, ...args: any[]): Promise<Uint8Array>;
51
+ /**
52
+ * @typedef {RenderOptions & Omit<PdfOptions, 'fonts'> & { fonts?: FontStore, tagged?: { lang?: string, maxElements?: number },
53
+ * window?: number, parallel?: number, maxRows?: number, id?: string, presorted?: boolean,
54
+ * spill?: false | { dir?: string, maxMB?: number }, sorter?: (cmp: (a: any, b: any) => number) => any }} PdfStreamOptions
55
+ * render()'s options and exportPdf's, plus: window (rows laid out at once, 1000), parallel (Node: worker threads
56
+ * that lay out and paint pages, opt-in; the file is the same, each thread costs memory), maxRows (rows read,
57
+ * 5,000,000), id (the file ID). presorted: the rows come in the report's order (its sort, its groups together), so
58
+ * they are not sorted, only checked as they pass (a row out of order stops the export). spill: where a sort's runs go
59
+ * (Node: the system temp folder, 2 GB at most; false sorts in memory); in a browser a sort is in memory.
60
+ */
61
+ /**
62
+ * Report definition → PDF written to a sink as it is made, for reports too large to hold as a page model: a flowing
63
+ * table (and its groups) is laid out a window of rows at a time and each page leaves memory once written. Other
64
+ * reports are rendered whole and written by exportPdf in one piece (the result says why). sink: a Node Writable
65
+ * (fs.createWriteStream) or anything with write(bytes) that may return a promise (back-pressure); it is not closed.
66
+ * @param {any} def the report definition
67
+ * @param {PdfStreamOptions} options
68
+ * @param {{ write(bytes: Uint8Array): any, once?: (ev: string, cb: () => void) => any }} sink
69
+ * @returns {Promise<{ streamed: boolean, pages: number, warnings: string[], why?: string }>}
70
+ */
71
+ export function exportPdfStream(def: any, options: PdfStreamOptions, sink: {
72
+ write(bytes: Uint8Array): any;
73
+ once?: (ev: string, cb: () => void) => any;
74
+ }): Promise<{
75
+ streamed: boolean;
76
+ pages: number;
77
+ warnings: string[];
78
+ why?: string;
79
+ }>;
51
80
  export { validate } from "../../src/engine/schema/validate.js";
52
81
  export { exportHtml } from "../../src/exporters/html.js";
53
82
  export { exportCsv } from "../../src/exporters/csv.js";
54
83
  export { needsExportData } from "../../src/exporters/regions.js";
55
84
  export { pageToSvg } from "../../src/exporters/svg.js";
85
+ export namespace __streamPaint {
86
+ export { createPdfStream };
87
+ export { paintPage };
88
+ export { paintEnv };
89
+ export { latin1 };
90
+ }
91
+ export { planPaged } from "../../src/engine/paged.js";
56
92
  export type PdfOptions = Omit<NonNullable<Parameters<typeof exportPdfFull>[2]>, "subset" | "pdfa"> & {
57
93
  fonts?: FontStore;
58
94
  subset?: false | NonNullable<Parameters<typeof exportPdfFull>[2]>["subset"];
@@ -61,6 +97,30 @@ export type PdfOptions = Omit<NonNullable<Parameters<typeof exportPdfFull>[2]>,
61
97
  [k: string]: unknown;
62
98
  };
63
99
  };
100
+ /**
101
+ * render()'s options and exportPdf's, plus: window (rows laid out at once, 1000), parallel (Node: worker threads
102
+ * that lay out and paint pages, opt-in; the file is the same, each thread costs memory), maxRows (rows read,
103
+ * 5,000,000), id (the file ID). presorted: the rows come in the report's order (its sort, its groups together), so
104
+ * they are not sorted, only checked as they pass (a row out of order stops the export). spill: where a sort's runs go
105
+ * (Node: the system temp folder, 2 GB at most; false sorts in memory); in a browser a sort is in memory.
106
+ */
107
+ export type PdfStreamOptions = RenderOptions & Omit<PdfOptions, "fonts"> & {
108
+ fonts?: FontStore;
109
+ tagged?: {
110
+ lang?: string;
111
+ maxElements?: number;
112
+ };
113
+ window?: number;
114
+ parallel?: number;
115
+ maxRows?: number;
116
+ id?: string;
117
+ presorted?: boolean;
118
+ spill?: false | {
119
+ dir?: string;
120
+ maxMB?: number;
121
+ };
122
+ sorter?: (cmp: (a: any, b: any) => number) => any;
123
+ };
64
124
  export type RenderOptions = import("../../src/engine/index.js").RenderOptions;
65
125
  import { FontStore } from '../../src/engine/index.js';
66
126
  import { exportXlsx as exportXlsxFull } from '../../src/exporters/xlsx.js';
@@ -68,6 +128,10 @@ import { exportDocx as exportDocxFull } from '../../src/exporters/docx.js';
68
128
  import { exportPptx as exportPptxFull } from '../../src/exporters/pptx.js';
69
129
  import { fontFile } from '../../src/engine/text/fonts.js';
70
130
  import { createSubsetter } from '../../src/exporters/subset.js';
131
+ import { createPdfStream } from '../../src/exporters/pdfstream.js';
132
+ import { paintPage } from '../../src/exporters/pdfstream.js';
133
+ import { paintEnv } from '../../src/exporters/pdfstream.js';
134
+ import { latin1 } from '../../src/exporters/pdfpaint.js';
71
135
  import { exportPdf as exportPdfFull } from '../../src/exporters/pdf.js';
72
136
  export { fontFile, createSubsetter };
73
137
  export { render, FontStore, ITEMS, parameterOptions, resolveParameters } from "../../src/engine/index.js";
@@ -16,11 +16,14 @@ export function redirectRequest(from: URL, to: URL, req: any, status: number): a
16
16
  /**
17
17
  * The guarded default fetch (see the top of this file). In Node every hop goes through nodeRequest (address pinned);
18
18
  * in a browser through `base` with redirects by hand (literal addresses checked; a browser has no DNS to ask).
19
- * @param {{ allowHosts?: string[] }} opt @param {typeof fetch} base
19
+ * @param {{ allowHosts?: string[], viaBase?: boolean }} opt viaBase: every hop through `base`, in Node too (the browser
20
+ * viewer's fetch, which its tests run in Node)
21
+ * @param {typeof fetch} base
20
22
  * @returns {typeof fetch}
21
23
  */
22
24
  export function guardedFetch(opt: {
23
25
  allowHosts?: string[];
26
+ viaBase?: boolean;
24
27
  }, base: typeof fetch): typeof fetch;
25
28
  /**
26
29
  * Any fetch with the engine's time limit and byte cap.
@@ -0,0 +1,48 @@
1
+ /**
2
+ * The keys a JSONPath walks to reach the rows, when the splitter can follow it: $, $.a.b, $['a b'], with a [*] at the
3
+ * end at most. Null for any other path (indexes, spreads in the middle): read the whole body instead.
4
+ * @param {string} [path] @returns {string[]|null}
5
+ */
6
+ export function splitPath(path?: string): string[] | null;
7
+ /**
8
+ * The rows of a JSON body at a path, in batches, without holding the body: the bytes are scanned for the array the
9
+ * path names, and its elements are parsed (JSON.parse, a batch at a time) as they complete. A body whose shape the path
10
+ * does not meet that way (an object where the rows should be, a path with indexes) is read whole and taken through
11
+ * jsonPathRows, exactly as a whole-body read would: maxWholeBytes caps that case. Every cap counts the text actually read
12
+ * (characters), not a declared length: the body before the rows (maxWholeBytes), one row (maxElementBytes, so one huge
13
+ * string or a row that never ends cannot grow without bound) and the nesting (maxDepth).
14
+ * @param {any} body @param {string|undefined} path
15
+ * @param {{ maxElementBytes?: number, maxWholeBytes?: number, maxDepth?: number, batch?: number }} [o]
16
+ * @returns {AsyncGenerator<any[]>}
17
+ */
18
+ export function jsonRows(body: any, path: string | undefined, { maxElementBytes, maxWholeBytes, maxDepth, batch }?: {
19
+ maxElementBytes?: number;
20
+ maxWholeBytes?: number;
21
+ maxDepth?: number;
22
+ batch?: number;
23
+ }): AsyncGenerator<any[]>;
24
+ /**
25
+ * CSV records as they arrive: the same reading as parseCsv (a quote opens a quoted field only at the start of a field;
26
+ * inside, a doubled quote is a quote and separators and line breaks are data; text after the closing quote is kept;
27
+ * \n, \r\n and \r end a record), across chunk boundaries.
28
+ * @param {any} body @param {{ sep: string, quote: string, maxFieldBytes?: number }} o @returns {AsyncGenerator<string[][]>}
29
+ */
30
+ export function csvRecords(body: any, { sep, quote, maxFieldBytes }: {
31
+ sep: string;
32
+ quote: string;
33
+ maxFieldBytes?: number;
34
+ }, batch?: number): AsyncGenerator<string[][]>;
35
+ /**
36
+ * CSV rows as objects, as parseCsv gives them (startRow, the header row's names, blank lines dropped), in batches.
37
+ * headerRow: false needs every row's width first: not read this way (null).
38
+ * @param {any} body @param {{ separator?: string, quote?: string, headerRow?: boolean, startRow?: number }} src
39
+ * @param {(v: any, d: string, what: string) => string} csvChar @param {number} [maxFieldBytes]
40
+ */
41
+ export function csvRows(body: any, src: {
42
+ separator?: string;
43
+ quote?: string;
44
+ headerRow?: boolean;
45
+ startRow?: number;
46
+ }, csvChar: (v: any, d: string, what: string) => string, maxFieldBytes?: number): AsyncGenerator<{
47
+ [k: string]: string;
48
+ }[], void, unknown>;
@@ -71,7 +71,7 @@ export class ReportError extends Error {
71
71
  }
72
72
  export const BAND_ITEMS: 250000;
73
73
  /** The start of the warning for CJK text without the optional CJK fonts (the viewer opens its warnings for it). */
74
- export const NO_CJK_FONTS: "Text in Japanese/Chinese/Korean needs the optional CJK fonts: npm run fonts:cjk";
74
+ export const NO_CJK_FONTS: "Text in Japanese/Chinese/Korean needs the optional CJK fonts: npm i @reportwright/fonts-cjk, then npx reportwright-fonts-cjk (npm); in the app, npm run fonts:cjk";
75
75
  /**
76
76
  * Options for render(). All optional.
77
77
  */
@@ -216,6 +216,21 @@ export type RenderOptions = {
216
216
  * internal: the images drawn so far, shared with subreports
217
217
  */
218
218
  imageBudget?: any;
219
+ /**
220
+ * internal (paged.js): these pages are a window of a longer report: numbered from offset + 1 of total ('…' when not known
221
+ * yet); final: the window holds the report's last page; first: the report's first row; rowOffset: the rows before this
222
+ * window; cont: per group level, the group the window's first row continues (its first row), or null
223
+ */
224
+ pageWindow?: {
225
+ offset: number;
226
+ total?: number | null;
227
+ final: boolean;
228
+ first?: any;
229
+ rowOffset?: number;
230
+ cont?: ({
231
+ first: any;
232
+ } | null)[];
233
+ };
219
234
  };
220
235
  import { FontStore } from './text/fonts.js';
221
236
  import { TextMeasurer } from './text/measure.js';
@@ -10,6 +10,12 @@ export function niceScale(min: any, max: any, ticks?: number): {
10
10
  hi: number;
11
11
  step: number;
12
12
  };
13
+ /** A nice scale whose step is the span over the ticks: niceScale rounds the span first, which can add a whole step. */
14
+ export function niceScaleSpan(min: any, max: any, ticks?: number): {
15
+ lo: number;
16
+ hi: number;
17
+ step: number;
18
+ };
13
19
  /** Ticks from lo to hi by step, rounded so 0.1 + 0.2 reads 0.3. At most 200 (a bad min/max cannot loop for ever). */
14
20
  export function linearTicks(lo: any, hi: any, step: any): any[];
15
21
  /** Powers of ten covering [min, max] (both > 0); at least two. */
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @param {any} def0 @param {any} opts render() options, and maxRows/sorter/sqlRows as planStream takes them;
3
+ * window: rows per window (tests)
4
+ * @returns {Promise<{ why: string } | { why?: undefined, pages: () => AsyncGenerator<any>, info: { width: number, height: number, bookmarks: any[], headings: any[], warnings: string[], pages: number } }>}
5
+ */
6
+ export function planPaged(def0: any, opts?: any): Promise<{
7
+ why: string;
8
+ } | {
9
+ why?: undefined;
10
+ pages: () => AsyncGenerator<any>;
11
+ info: {
12
+ width: number;
13
+ height: number;
14
+ bookmarks: any[];
15
+ headings: any[];
16
+ warnings: string[];
17
+ pages: number;
18
+ };
19
+ }>;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * An in-memory sorter (the browser, the CLI): the server passes one that spills runs to disk (exporters/spill.js; exportPdfStream's default in Node).
3
+ * @param {(a: any, b: any) => number} cmp
4
+ */
5
+ export function memorySorter(cmp: (a: any, b: any) => number): {
6
+ push(r: any): void;
7
+ drain(): AsyncGenerator<any, void, unknown>;
8
+ close(): Promise<void>;
9
+ };
10
+ /**
11
+ * @param {any} def0 the report definition
12
+ * @param {{ format: 'csv'|'xlsx', parameters?: object, timeZone?: string, now?: Date, state?: any, loadReport?: (id: string) => Promise<any>,
13
+ * reportId?: string, fetch?: typeof fetch, baseUrl?: string, sql?: (src: any, p: any) => Promise<object[]>,
14
+ * sqlRows?: (src: any, p: any) => AsyncIterable<object[]>, sources?: Record<string, any>, sorter?: (cmp: (a: any, b: any) => number) => any, presorted?: boolean,
15
+ * deadline?: number, timeoutMs?: number, maxRows?: number, maxJsonRowBytes?: number, maxJsonWholeBytes?: number }} opts
16
+ * @returns {Promise<{ why: string } | { why?: undefined, name: string, columns: number[], title: string, timeZone: string|null, locale: string|null, currency: string|null, warnings: string[], rows: () => AsyncGenerator<any>, records: () => AsyncGenerator<any>, grouped: () => AsyncGenerator<any>, fieldList: () => Promise<any[]>, stats: { rows: number } }>}
17
+ */
18
+ export function planStream(def0: any, opts: {
19
+ format: "csv" | "xlsx";
20
+ parameters?: object;
21
+ timeZone?: string;
22
+ now?: Date;
23
+ state?: any;
24
+ loadReport?: (id: string) => Promise<any>;
25
+ reportId?: string;
26
+ fetch?: typeof fetch;
27
+ baseUrl?: string;
28
+ sql?: (src: any, p: any) => Promise<object[]>;
29
+ sqlRows?: (src: any, p: any) => AsyncIterable<object[]>;
30
+ sources?: Record<string, any>;
31
+ sorter?: (cmp: (a: any, b: any) => number) => any;
32
+ presorted?: boolean;
33
+ deadline?: number;
34
+ timeoutMs?: number;
35
+ maxRows?: number;
36
+ maxJsonRowBytes?: number;
37
+ maxJsonWholeBytes?: number;
38
+ }): Promise<{
39
+ why: string;
40
+ } | {
41
+ why?: undefined;
42
+ name: string;
43
+ columns: number[];
44
+ title: string;
45
+ timeZone: string | null;
46
+ locale: string | null;
47
+ currency: string | null;
48
+ warnings: string[];
49
+ rows: () => AsyncGenerator<any>;
50
+ records: () => AsyncGenerator<any>;
51
+ grouped: () => AsyncGenerator<any>;
52
+ fieldList: () => Promise<any[]>;
53
+ stats: {
54
+ rows: number;
55
+ };
56
+ }>;
@@ -19,6 +19,8 @@ export function saBreaks(text: string, segmenter?: Intl.Segmenter | null): Set<n
19
19
  * @param {any[]} items @param {TextMeasurer} m
20
20
  */
21
21
  export function finishText(items: any[], m: TextMeasurer): void;
22
+ /** Unicode format characters (Cf): bidi marks and embeddings, joiners, soft hyphen. They have no shape of their own. */
23
+ export const FORMAT_CHAR: RegExp;
22
24
  /**
23
25
  * @typedef {{ font: string, x: number, w: number, text: string, rtl?: boolean, shaped?: boolean, glyphs: number[] }} Run
24
26
  * One font, one direction. x and w in points from the start of the line; glyphs: [id, x, y, cluster] per glyph
@@ -1,9 +1,12 @@
1
+ /** The string cut into pieces of at most about max chars, each ending at a '>' (a tag boundary), so their join is s. */
2
+ export function slices(s: any, max: any): any[];
1
3
  /** Left, right or centre, from where the lines sit in their box. */
2
4
  export function alignOf(it: any): "center" | "left" | "right" | "both";
3
5
  /**
4
6
  * @param {any} model render() output
5
7
  * @param {{ title?: string, author?: string, lang?: string, fontStore?: any, fetchImage?: (src: string) => Promise<Uint8Array|null>,
6
- * rasterize?: (svg: string, w: number, h: number, scale: number) => Promise<Uint8Array|null>, figures?: boolean }} [opt]
8
+ * rasterize?: (svg: string, w: number, h: number, scale: number) => Promise<Uint8Array|null>, figures?: boolean, xmlChunk?: number }} [opt]
9
+ * xmlChunk: the document XML is written to the zip in pieces of about this many chars (default 4M; tests lower it)
7
10
  * fontStore: text in pictures as outlines (else the reader's fallback font); fetchImage: pictures by URL;
8
11
  * rasterize: the PNG fallback of a picture (default: a canvas in a browser, sharp in Node); figures: false leaves them out.
9
12
  * @returns {Promise<Uint8Array>}
@@ -16,4 +19,5 @@ export function exportDocx(model: any, opt?: {
16
19
  fetchImage?: (src: string) => Promise<Uint8Array | null>;
17
20
  rasterize?: (svg: string, w: number, h: number, scale: number) => Promise<Uint8Array | null>;
18
21
  figures?: boolean;
22
+ xmlChunk?: number;
19
23
  }): Promise<Uint8Array>;
@@ -4,12 +4,15 @@
4
4
  * drill-through opens the ReportWright viewer at drillBase (without one it is shown disabled).
5
5
  * Unless static, a file whose report has tables also gets a Tables view (htmldata.js): the tables as HTML, re-sorted on
6
6
  * their interactive-sort columns, groups opened and closed, rows filtered, by one inline script the file's CSP allows.
7
+ * exportHtml(model, { fonts, ...options }). The 0.7 form exportHtml(model, fontStore, options) still works (deprecated).
7
8
  * @param {any} model
8
- * @param {import('../engine/text/fonts.js').FontStore} fontStore
9
- * @param {{ title?: string, drillBase?: string, subset?: (font: Uint8Array, cps: Iterable<number>, o?: { layout?: boolean }) => Promise<Uint8Array>,
10
- * static?: boolean, locale?: string, currency?: string, lang?: string, strings?: Partial<typeof DATA_STRINGS> }} [opt]
9
+ * @param {{ fonts?: import('../engine/text/fonts.js').FontStore, fontStore?: import('../engine/text/fonts.js').FontStore, title?: string, drillBase?: string, subset?: (font: Uint8Array, cps: Iterable<number>, o?: { layout?: boolean }) => Promise<Uint8Array>,
10
+ * static?: boolean, locale?: string, currency?: string, lang?: string, strings?: Partial<typeof DATA_STRINGS>, timeoutMs?: number } | import('../engine/text/fonts.js').FontStore} [options]
11
+ * @param {any} [legacyOpt] the options of the 0.7 form
11
12
  */
12
- export function exportHtml(model: any, fontStore: import("../engine/text/fonts.js").FontStore, opt?: {
13
+ export function exportHtml(model: any, options?: {
14
+ fonts?: import("../engine/text/fonts.js").FontStore;
15
+ fontStore?: import("../engine/text/fonts.js").FontStore;
13
16
  title?: string;
14
17
  drillBase?: string;
15
18
  subset?: (font: Uint8Array, cps: Iterable<number>, o?: {
@@ -20,5 +23,6 @@ export function exportHtml(model: any, fontStore: import("../engine/text/fonts.j
20
23
  currency?: string;
21
24
  lang?: string;
22
25
  strings?: Partial<typeof DATA_STRINGS>;
23
- }): any;
26
+ timeoutMs?: number;
27
+ } | import("../engine/text/fonts.js").FontStore, legacyOpt?: any): Promise<string>;
24
28
  import { DATA_STRINGS } from './htmldata.js';
@@ -20,6 +20,17 @@ export function makePdfA(doc: import("pdf-lib").PDFDocument, { icc, title, autho
20
20
  * @param {Date} when
21
21
  */
22
22
  export function setInfoDates(doc: import("pdf-lib").PDFDocument, when: Date): void;
23
+ /**
24
+ * The XMP metadata packet: title, author, dates, and the PDF/A and PDF/UA identifiers when asked.
25
+ * @param {{ title: string, author?: string, stamp: string, pdfa?: string|null, ua?: boolean }} o
26
+ */
27
+ export function xmpPacket({ title, author, stamp, pdfa, ua }: {
28
+ title: string;
29
+ author?: string;
30
+ stamp: string;
31
+ pdfa?: string | null;
32
+ ua?: boolean;
33
+ }): string;
23
34
  /**
24
35
  * PDF/UA-1 without PDF/A: XMP metadata with the title and the PDF/UA identifier (the Info dictionary says the same).
25
36
  * @param {import('pdf-lib').PDFDocument} doc
@@ -0,0 +1,99 @@
1
+ export function drawRun(c: any, run: any, x: any, y: any, size: any, pf: any, color: any, spans: any, texts: any): void;
2
+ /**
3
+ * The text each shaped glyph stands for, for the font's ToUnicode map: the character whose own (character-map)
4
+ * glyph it is; the characters of its cluster that have no glyph of their own there (a conjunct, a joined
5
+ * Arabic form, a reph) go to ONE glyph, the first that is not a mark, and the cluster's other glyphs (dots,
6
+ * marks) stand for nothing, so a reader gets each character once. A glyph keeps its first text: a
7
+ * right-to-left cluster that would read differently with the texts already set goes into `spans` (drawRun
8
+ * gives it /ActualText). Left-to-right runs always get one span for the whole run.
9
+ * @param {any} run @param {any} font fontkit font @param {Map<number, string>} out
10
+ * @param {WeakMap<any, Set<number>>} [spans]
11
+ */
12
+ export function glyphText(run: any, font: any, out: Map<number, string>, spans?: WeakMap<any, Set<number>>): void;
13
+ /**
14
+ * Text inside its clip box needs no clip: the lines' advances within it across, the font's ascent and descent
15
+ * within it down. A cell's text almost always fits, and a clip per cell is most of a table page's operators.
16
+ */
17
+ export function insideClip(it: any, m: any): any;
18
+ /** one byte per char: the content stream holds the glyph bytes of literal strings as chars 0–255 */
19
+ export function latin1(s: any): any;
20
+ /**
21
+ * zlib (Flate) compression: Node's zlib on its thread pool (pages compress in parallel, off the main thread), else
22
+ * the platform's CompressionStream (browsers; in Node it is the same zlib behind web streams, slower), else fflate.
23
+ */
24
+ export function deflate(bytes: any): Promise<any>;
25
+ export function col(c: any): any;
26
+ export namespace BLACK {
27
+ let color: import("pdf-lib").RGB;
28
+ let opacity: number;
29
+ let rgb: string;
30
+ }
31
+ export function n2(v: any): number;
32
+ export function n3(v: any): number;
33
+ export function n4(v: any): number;
34
+ export function hex4(id: any): any;
35
+ export const KAPPA: number;
36
+ export function cleanText(t: any): any;
37
+ /**
38
+ * A page's operators as text. The graphics state is tracked, so a colour, line width, dash, opacity or font
39
+ * that is already set is not set again; q/Q save and restore it as the PDF does.
40
+ */
41
+ export class Content {
42
+ constructor(shared: any);
43
+ shared: any;
44
+ _s: string;
45
+ bt: boolean;
46
+ tx: number;
47
+ ty: number;
48
+ st: {
49
+ fill: string;
50
+ stroke: string;
51
+ lw: number;
52
+ dash: string;
53
+ ca: number;
54
+ CA: number;
55
+ font: string;
56
+ size: number;
57
+ };
58
+ /** @type {any[]} */ saved: any[];
59
+ /** straight lines waiting to be drawn after the text around them: { key, stroke, w, dash, segs: [x1, y1, x2, y2][] } */
60
+ lines: any;
61
+ tagged: boolean;
62
+ /** tagged, lines wait all the same and are drawn as one artifact (the streamed PDF's painter sets it) */
63
+ artLines: boolean;
64
+ set s(v: string);
65
+ /**
66
+ * The operators so far. Any other drawing reads or appends to it, so the lines waiting are drawn first: the text
67
+ * of a table's cells stays in one text object (relative moves, which compress to little) instead of one per cell.
68
+ */
69
+ get s(): string;
70
+ /**
71
+ * A straight line. Untagged, it waits until something other than text is drawn (table borders between cell
72
+ * texts); collinear segments that touch, in the same stroke, become one (a row's border is one line).
73
+ * ponytail: lines move after the text drawn just after them; both are thin and do not cover each other.
74
+ */
75
+ line(stroke: any, w: any, dash: any, x1: any, y1: any, x2: any, y2: any): void;
76
+ flushLines(): void;
77
+ q(): void;
78
+ Q(): void;
79
+ /**
80
+ * A line of plain text at (x, y). Lines follow one another in one text object, each placed relative to the
81
+ * last (in whole hundredths, so nothing drifts): most of a table page is these.
82
+ * @param {string} str the glyphs, as a literal string's escaped body (array: a TJ array's body)
83
+ */
84
+ text(pf: any, size: any, color: any, x: any, y: any, str: string, array?: boolean): void;
85
+ /** end the open text object, if any: anything but text needs that (and draws the lines waiting) */
86
+ et(): void;
87
+ lineWidth(w: any): void;
88
+ setLineWidth(w: any): void;
89
+ /** the graphics state that sets these opacities, or undefined when they are set already */
90
+ gsFor(ca: any, CA: any): any;
91
+ alpha(ca: any, CA: any): void;
92
+ setAlpha(ca: any, CA: any): void;
93
+ /** set up to fill with fill and/or stroke with stroke (width w, dash); the lines waiting are drawn first */
94
+ paint(fill: any, stroke: any, w?: number, dash?: any): void;
95
+ setPaint(fill: any, stroke: any, w?: number, dash?: any): void;
96
+ font(pf: any, size: any): void;
97
+ setFont(pf: any, size: any): void;
98
+ }
99
+ export const NODE_ZLIB: any;