@build-qube/papyra 0.1.0 → 0.3.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 +46 -1
- package/dist/attachments.d.ts +76 -0
- package/dist/attachments.d.ts.map +1 -0
- package/dist/attachments.js +65 -0
- package/dist/attachments.js.map +1 -0
- package/dist/canvas.d.ts +27 -2
- package/dist/canvas.d.ts.map +1 -1
- package/dist/canvas.js +58 -5
- package/dist/canvas.js.map +1 -1
- package/dist/document.d.ts +179 -4
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +311 -12
- package/dist/document.js.map +1 -1
- package/dist/encode.d.ts +2 -2
- package/dist/encode.d.ts.map +1 -1
- package/dist/encode.js +1 -1
- package/dist/encode.js.map +1 -1
- package/dist/encoded.d.ts +34 -5
- package/dist/encoded.d.ts.map +1 -1
- package/dist/encoded.js +28 -0
- package/dist/encoded.js.map +1 -1
- package/dist/errors.d.ts +45 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +69 -0
- package/dist/errors.js.map +1 -0
- package/dist/fingerprint.d.ts +18 -0
- package/dist/fingerprint.d.ts.map +1 -0
- package/dist/fingerprint.js +48 -0
- package/dist/fingerprint.js.map +1 -0
- package/dist/index.d.ts +14 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/links.d.ts +53 -0
- package/dist/links.d.ts.map +1 -0
- package/dist/links.js +26 -0
- package/dist/links.js.map +1 -0
- package/dist/outline.d.ts +9 -1
- package/dist/outline.d.ts.map +1 -1
- package/dist/outline.js +9 -3
- package/dist/outline.js.map +1 -1
- package/dist/structure.d.ts +119 -0
- package/dist/structure.d.ts.map +1 -0
- package/dist/structure.js +115 -0
- package/dist/structure.js.map +1 -0
- package/dist/text.d.ts +20 -0
- package/dist/text.d.ts.map +1 -1
- package/dist/text.js +9 -0
- package/dist/text.js.map +1 -1
- package/dist/types.d.ts +75 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/viewport.d.ts +129 -0
- package/dist/viewport.d.ts.map +1 -0
- package/dist/viewport.js +163 -0
- package/dist/viewport.js.map +1 -0
- package/package.json +2 -2
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A document that could not be opened because of its password.
|
|
3
|
+
*
|
|
4
|
+
* The base of both password failures, because a viewer handles them in one place: a
|
|
5
|
+
* dialog that either asks for the first time or says the last answer was wrong.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* try {
|
|
10
|
+
* doc = await open(file, { password });
|
|
11
|
+
* } catch (e) {
|
|
12
|
+
* if (e instanceof PasswordError) showPasswordDialog({ retry: e.retry });
|
|
13
|
+
* else throw e;
|
|
14
|
+
* }
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare class PasswordError extends Error {
|
|
18
|
+
/**
|
|
19
|
+
* A password was already tried and rejected.
|
|
20
|
+
*
|
|
21
|
+
* `false` the first time, so a dialog can open without an error on it.
|
|
22
|
+
*/
|
|
23
|
+
readonly retry: boolean;
|
|
24
|
+
}
|
|
25
|
+
/** The document is encrypted and {@link OpenOptions.password} was not supplied. */
|
|
26
|
+
export declare class PasswordRequiredError extends PasswordError {
|
|
27
|
+
/** Always `'PasswordRequiredError'`. */
|
|
28
|
+
readonly name = "PasswordRequiredError";
|
|
29
|
+
readonly retry = false;
|
|
30
|
+
constructor(message?: string);
|
|
31
|
+
}
|
|
32
|
+
/** A password was supplied and it did not open the document. */
|
|
33
|
+
export declare class IncorrectPasswordError extends PasswordError {
|
|
34
|
+
/** Always `'IncorrectPasswordError'`. */
|
|
35
|
+
readonly name = "IncorrectPasswordError";
|
|
36
|
+
readonly retry = true;
|
|
37
|
+
constructor(message?: string);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Rethrow a load failure as itself, or as the typed error it was tagged as.
|
|
41
|
+
*
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
44
|
+
export declare function rethrowLoadError(error: unknown): never;
|
|
45
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAeA;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACtC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAS;CACjC;AAED,mFAAmF;AACnF,qBAAa,qBAAsB,SAAQ,aAAa;IACtD,wCAAwC;IACxC,SAAkB,IAAI,2BAA2B;IACjD,SAAkB,KAAK,SAAS;IAChC,YAAY,OAAO,SAAmC,EAErD;CACF;AAED,gEAAgE;AAChE,qBAAa,sBAAuB,SAAQ,aAAa;IACvD,yCAAyC;IACzC,SAAkB,IAAI,4BAA4B;IAClD,SAAkB,KAAK,QAAQ;IAC/B,YAAY,OAAO,SAAuC,EAEzD;CACF;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAQtD"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tags the bindings put in front of a load failure's message.
|
|
3
|
+
*
|
|
4
|
+
* napi-rs gives every error it throws the same `code`, so the message is the only
|
|
5
|
+
* channel a typed failure can travel through. These are stripped before the error
|
|
6
|
+
* reaches a caller — keep them in step with `TAG_PASSWORD_REQUIRED` and
|
|
7
|
+
* `TAG_INCORRECT_PASSWORD` in `packages/bindings/src/lib.rs`.
|
|
8
|
+
*/
|
|
9
|
+
const TAGS = {
|
|
10
|
+
'papyra/password-required': (message) => new PasswordRequiredError(message),
|
|
11
|
+
'papyra/incorrect-password': (message) => new IncorrectPasswordError(message),
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* A document that could not be opened because of its password.
|
|
15
|
+
*
|
|
16
|
+
* The base of both password failures, because a viewer handles them in one place: a
|
|
17
|
+
* dialog that either asks for the first time or says the last answer was wrong.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* try {
|
|
22
|
+
* doc = await open(file, { password });
|
|
23
|
+
* } catch (e) {
|
|
24
|
+
* if (e instanceof PasswordError) showPasswordDialog({ retry: e.retry });
|
|
25
|
+
* else throw e;
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export class PasswordError extends Error {
|
|
30
|
+
/**
|
|
31
|
+
* A password was already tried and rejected.
|
|
32
|
+
*
|
|
33
|
+
* `false` the first time, so a dialog can open without an error on it.
|
|
34
|
+
*/
|
|
35
|
+
retry = false;
|
|
36
|
+
}
|
|
37
|
+
/** The document is encrypted and {@link OpenOptions.password} was not supplied. */
|
|
38
|
+
export class PasswordRequiredError extends PasswordError {
|
|
39
|
+
/** Always `'PasswordRequiredError'`. */
|
|
40
|
+
name = 'PasswordRequiredError';
|
|
41
|
+
retry = false;
|
|
42
|
+
constructor(message = 'this PDF is password-protected') {
|
|
43
|
+
super(message);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** A password was supplied and it did not open the document. */
|
|
47
|
+
export class IncorrectPasswordError extends PasswordError {
|
|
48
|
+
/** Always `'IncorrectPasswordError'`. */
|
|
49
|
+
name = 'IncorrectPasswordError';
|
|
50
|
+
retry = true;
|
|
51
|
+
constructor(message = 'the supplied password is incorrect') {
|
|
52
|
+
super(message);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Rethrow a load failure as itself, or as the typed error it was tagged as.
|
|
57
|
+
*
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
60
|
+
export function rethrowLoadError(error) {
|
|
61
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
62
|
+
for (const [tag, build] of Object.entries(TAGS)) {
|
|
63
|
+
if (message.startsWith(tag)) {
|
|
64
|
+
throw build(message.slice(tag.length).trim());
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,IAAI,GAAG;IACX,0BAA0B,EAAE,CAAC,OAAe,EAAE,EAAE,CAC9C,IAAI,qBAAqB,CAAC,OAAO,CAAC;IACpC,2BAA2B,EAAE,CAAC,OAAe,EAAE,EAAE,CAC/C,IAAI,sBAAsB,CAAC,OAAO,CAAC;CAC7B,CAAC;AAEX;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC;;;;OAIG;IACM,KAAK,GAAY,KAAK,CAAC;CACjC;AAED,mFAAmF;AACnF,MAAM,OAAO,qBAAsB,SAAQ,aAAa;IACtD,wCAAwC;IACtB,IAAI,GAAG,uBAAuB,CAAC;IAC/B,KAAK,GAAG,KAAK,CAAC;IAChC,YAAY,OAAO,GAAG,gCAAgC;QACpD,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;CACF;AAED,gEAAgE;AAChE,MAAM,OAAO,sBAAuB,SAAQ,aAAa;IACvD,yCAAyC;IACvB,IAAI,GAAG,wBAAwB,CAAC;IAChC,KAAK,GAAG,IAAI,CAAC;IAC/B,YAAY,OAAO,GAAG,oCAAoC;QACxD,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IACD,MAAM,KAAK,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A stable identifier for a document's bytes.
|
|
3
|
+
*
|
|
4
|
+
* Sixteen hex characters, derived from the head, the tail and the length of the file.
|
|
5
|
+
* Meant as a key for whatever a viewer remembers per document — the page it was left
|
|
6
|
+
* on, the zoom, a set of highlights.
|
|
7
|
+
*
|
|
8
|
+
* **This is a content hash, not the PDF's `/ID`.** hayro exposes no trailer accessor,
|
|
9
|
+
* so the identifier the spec defines is out of reach; the practical difference is
|
|
10
|
+
* that a document saved with an incremental update keeps its `/ID` and gets a new
|
|
11
|
+
* fingerprint here. For "is this the same file I had open", which is what the value
|
|
12
|
+
* is for, hashing the bytes is the stronger answer anyway — it also distinguishes two
|
|
13
|
+
* documents that were copied from one another and kept the same `/ID`.
|
|
14
|
+
*
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
export declare function fingerprint(bytes: Uint8Array): string;
|
|
18
|
+
//# sourceMappingURL=fingerprint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"AAqBA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAarD"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How many bytes to read from each end of the file.
|
|
3
|
+
*
|
|
4
|
+
* The tail is the load-bearing half: it holds the cross-reference table and the
|
|
5
|
+
* trailer, and the trailer is where `/ID` lives. So although this never parses the
|
|
6
|
+
* document, a file that carries an `/ID` still contributes it to the hash.
|
|
7
|
+
*/
|
|
8
|
+
const SAMPLE = 4096;
|
|
9
|
+
/** FNV-1a, 32-bit. Two runs at different offsets give the 64 bits below. */
|
|
10
|
+
function fnv1a(bytes, seed) {
|
|
11
|
+
let hash = seed;
|
|
12
|
+
for (const byte of bytes) {
|
|
13
|
+
hash ^= byte;
|
|
14
|
+
// The FNV prime, 16777619, as shifts — `Math.imul` keeps this in 32 bits where
|
|
15
|
+
// `*` would silently go through a double and lose the low bits.
|
|
16
|
+
hash = Math.imul(hash, 0x01000193);
|
|
17
|
+
}
|
|
18
|
+
return hash >>> 0;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A stable identifier for a document's bytes.
|
|
22
|
+
*
|
|
23
|
+
* Sixteen hex characters, derived from the head, the tail and the length of the file.
|
|
24
|
+
* Meant as a key for whatever a viewer remembers per document — the page it was left
|
|
25
|
+
* on, the zoom, a set of highlights.
|
|
26
|
+
*
|
|
27
|
+
* **This is a content hash, not the PDF's `/ID`.** hayro exposes no trailer accessor,
|
|
28
|
+
* so the identifier the spec defines is out of reach; the practical difference is
|
|
29
|
+
* that a document saved with an incremental update keeps its `/ID` and gets a new
|
|
30
|
+
* fingerprint here. For "is this the same file I had open", which is what the value
|
|
31
|
+
* is for, hashing the bytes is the stronger answer anyway — it also distinguishes two
|
|
32
|
+
* documents that were copied from one another and kept the same `/ID`.
|
|
33
|
+
*
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
export function fingerprint(bytes) {
|
|
37
|
+
const head = bytes.subarray(0, SAMPLE);
|
|
38
|
+
// `subarray` clamps, so a file shorter than one sample simply hashes twice rather
|
|
39
|
+
// than needing a branch.
|
|
40
|
+
const tail = bytes.subarray(Math.max(0, bytes.length - SAMPLE));
|
|
41
|
+
const low = fnv1a(tail, fnv1a(head, 0x811c9dc5));
|
|
42
|
+
// A second pass from a different seed, so the two halves of the output are not the
|
|
43
|
+
// same 32 bits twice. Length goes in as well: it separates a file from its own
|
|
44
|
+
// prefix, which the samples alone would not.
|
|
45
|
+
const high = fnv1a(tail, fnv1a(head, bytes.length >>> 0));
|
|
46
|
+
return high.toString(16).padStart(8, '0') + low.toString(16).padStart(8, '0');
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=fingerprint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,MAAM,GAAG,IAAI,CAAC;AAEpB,4EAA4E;AAC5E,SAAS,KAAK,CAAC,KAAiB,EAAE,IAAY;IAC5C,IAAI,IAAI,GAAG,IAAI,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,IAAI,CAAC;QACb,+EAA+E;QAC/E,gEAAgE;QAChE,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,IAAI,KAAK,CAAC,CAAC;AACpB,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,WAAW,CAAC,KAAiB;IAC3C,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACvC,kFAAkF;IAClF,yBAAyB;IACzB,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC;IAEhE,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;IACjD,mFAAmF;IACnF,+EAA+E;IAC/E,6CAA6C;IAC7C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;IAE1D,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAChF,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -13,12 +13,17 @@
|
|
|
13
13
|
* onScroll(() => job.setPriority(0));
|
|
14
14
|
* ```
|
|
15
15
|
*/
|
|
16
|
+
export type { Attachment } from './attachments.js';
|
|
17
|
+
export { attachmentMediaType, isInvoiceAttachment, } from './attachments.js';
|
|
16
18
|
export type { CacheStats } from './cache.js';
|
|
19
|
+
export type { PaintOptions } from './canvas.js';
|
|
17
20
|
export { paintToCanvas, toImageData } from './canvas.js';
|
|
18
|
-
export type { ImageHandle, RenderHandle } from './document.js';
|
|
21
|
+
export type { ImageHandle, RenderHandle, SvgHandle } from './document.js';
|
|
19
22
|
export { Document, open } from './document.js';
|
|
20
|
-
export type { EncodedFormat, EncodedImage, EncodeOptions, } from './encode.js';
|
|
21
|
-
export { encode, encodedImage, mimeType, PageImage } from './encode.js';
|
|
23
|
+
export type { EncodedFormat, EncodedImage, EncodeOptions, RasterFormat, SvgPage, } from './encode.js';
|
|
24
|
+
export { encode, encodedImage, mimeType, PageImage, svgPage, } from './encode.js';
|
|
25
|
+
export { IncorrectPasswordError, PasswordError, PasswordRequiredError, } from './errors.js';
|
|
26
|
+
export type { LinkTarget, PageLink } from './links.js';
|
|
22
27
|
export type { DestinationKind, OutlineDestination, OutlineNode, } from './outline.js';
|
|
23
28
|
export { buildOutlineTree, walkOutline } from './outline.js';
|
|
24
29
|
export type { Runtime } from './runtime.js';
|
|
@@ -27,7 +32,11 @@ export type { JobHandle, JobTiming } from './scheduler.js';
|
|
|
27
32
|
export { AbortError, DEFAULT_PRIORITY } from './scheduler.js';
|
|
28
33
|
export type { MatchOptions, SearchMatch } from './search.js';
|
|
29
34
|
export { findRanges, searchPageText } from './search.js';
|
|
35
|
+
export type { MarkedContent, OrderedLine, StructNode, } from './structure.js';
|
|
36
|
+
export { buildStructTree, readingOrder, structuredPageString, walkStructTree, } from './structure.js';
|
|
30
37
|
export type { PageText, Quad, Rect, TextLine } from './text.js';
|
|
31
|
-
export { lineQuad, pageString, quadBounds, scaleQuad, } from './text.js';
|
|
32
|
-
export type { OpenOptions, PageSize, PdfSource, RenderedPage, RenderOptions, SearchOptions, StreamedPage, StreamOptions, } from './types.js';
|
|
38
|
+
export { lineQuad, pageString, quadBounds, scaleQuad, scaleRect, } from './text.js';
|
|
39
|
+
export type { DocumentMetadata, OpenOptions, PageSize, PdfSource, RenderedPage, RenderOptions, SearchOptions, StreamedPage, StreamOptions, SvgOptions, } from './types.js';
|
|
40
|
+
export type { Rotation, Viewport, ViewportOptions } from './viewport.js';
|
|
41
|
+
export { rotatePage, rotateSize, viewport, viewportQuad, viewportRect, } from './viewport.js';
|
|
33
42
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACzD,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EACL,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACzD,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EACV,aAAa,EACb,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,OAAO,GACR,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,MAAM,EACN,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,OAAO,GACR,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,sBAAsB,EACtB,aAAa,EACb,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACvD,YAAY,EACV,eAAe,EACf,kBAAkB,EAClB,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC7D,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EACL,OAAO,EACP,cAAc,EACd,mBAAmB,EACnB,IAAI,GACL,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC9D,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACzD,YAAY,EACV,aAAa,EACb,WAAW,EACX,UAAU,GACX,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,cAAc,GACf,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAChE,OAAO,EACL,QAAQ,EACR,UAAU,EACV,UAAU,EACV,SAAS,EACT,SAAS,GACV,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,gBAAgB,EAChB,WAAW,EACX,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,aAAa,EACb,aAAa,EACb,YAAY,EACZ,aAAa,EACb,UAAU,GACX,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,EACL,UAAU,EACV,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,YAAY,GACb,MAAM,eAAe,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -13,12 +13,16 @@
|
|
|
13
13
|
* onScroll(() => job.setPriority(0));
|
|
14
14
|
* ```
|
|
15
15
|
*/
|
|
16
|
+
export { attachmentMediaType, isInvoiceAttachment, } from './attachments.js';
|
|
16
17
|
export { paintToCanvas, toImageData } from './canvas.js';
|
|
17
18
|
export { Document, open } from './document.js';
|
|
18
|
-
export { encode, encodedImage, mimeType, PageImage } from './encode.js';
|
|
19
|
+
export { encode, encodedImage, mimeType, PageImage, svgPage, } from './encode.js';
|
|
20
|
+
export { IncorrectPasswordError, PasswordError, PasswordRequiredError, } from './errors.js';
|
|
19
21
|
export { buildOutlineTree, walkOutline } from './outline.js';
|
|
20
22
|
export { backend, currentRuntime, hardwareConcurrency, init, } from './runtime.js';
|
|
21
23
|
export { AbortError, DEFAULT_PRIORITY } from './scheduler.js';
|
|
22
24
|
export { findRanges, searchPageText } from './search.js';
|
|
23
|
-
export {
|
|
25
|
+
export { buildStructTree, readingOrder, structuredPageString, walkStructTree, } from './structure.js';
|
|
26
|
+
export { lineQuad, pageString, quadBounds, scaleQuad, scaleRect, } from './text.js';
|
|
27
|
+
export { rotatePage, rotateSize, viewport, viewportQuad, viewportRect, } from './viewport.js';
|
|
24
28
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEzD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EACL,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEzD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAQ/C,OAAO,EACL,MAAM,EACN,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,OAAO,GACR,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,sBAAsB,EACtB,aAAa,EACb,qBAAqB,GACtB,MAAM,aAAa,CAAC;AAOrB,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE7D,OAAO,EACL,OAAO,EACP,cAAc,EACd,mBAAmB,EACnB,IAAI,GACL,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAE9D,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAMzD,OAAO,EACL,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,cAAc,GACf,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,QAAQ,EACR,UAAU,EACV,UAAU,EACV,SAAS,EACT,SAAS,GACV,MAAM,WAAW,CAAC;AAcnB,OAAO,EACL,UAAU,EACV,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,YAAY,GACb,MAAM,eAAe,CAAC"}
|
package/dist/links.d.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { PageLink as NativePageLink } from '@build-qube/papyra-native';
|
|
2
|
+
import { type OutlineDestination } from './outline.js';
|
|
3
|
+
import type { Rect } from './text.js';
|
|
4
|
+
/**
|
|
5
|
+
* Where a link goes.
|
|
6
|
+
*
|
|
7
|
+
* A discriminated union rather than two nullable fields, so narrowing on `kind` gives
|
|
8
|
+
* you the payload without a non-null assertion:
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* if (link.target.kind === 'uri') window.open(link.target.uri);
|
|
12
|
+
* else void doc.render(link.target.dest.page, { fitWidth: 1600 });
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export type LinkTarget = {
|
|
16
|
+
/** The link points somewhere in this document. */
|
|
17
|
+
readonly kind: 'internal';
|
|
18
|
+
/** The page and the view, in the same shape an outline entry uses. */
|
|
19
|
+
readonly dest: OutlineDestination;
|
|
20
|
+
} | {
|
|
21
|
+
/**
|
|
22
|
+
* The link points out of this document.
|
|
23
|
+
*
|
|
24
|
+
* Not necessarily `http`: `mailto:` and `file:` are both common, and papyra
|
|
25
|
+
* does not validate the string. Decide for yourself what you are willing to
|
|
26
|
+
* follow before handing it to a browser.
|
|
27
|
+
*/
|
|
28
|
+
readonly kind: 'uri';
|
|
29
|
+
/** The URI, exactly as the document wrote it. */
|
|
30
|
+
readonly uri: string;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* One link on a page: a clickable region, and what it does.
|
|
34
|
+
*
|
|
35
|
+
* Only links that resolve to something actionable are reported — a `/Link` pointing
|
|
36
|
+
* at a page the document does not contain, or carrying an action papyra does not act
|
|
37
|
+
* on, is dropped rather than handed over as a region that would swallow clicks.
|
|
38
|
+
*/
|
|
39
|
+
export interface PageLink {
|
|
40
|
+
/**
|
|
41
|
+
* The clickable region, in the same 72-DPI top-left space as {@link PageText} and
|
|
42
|
+
* {@link PageSize}. Multiply by `rendered.width / pageSize.width` to place it over
|
|
43
|
+
* a render — {@link scaleRect} does exactly that.
|
|
44
|
+
*/
|
|
45
|
+
readonly rect: Rect;
|
|
46
|
+
/** Where activating the link goes. Narrow on `target.kind`. */
|
|
47
|
+
readonly target: LinkTarget;
|
|
48
|
+
/** The annotation's tooltip, when it has one. */
|
|
49
|
+
readonly alt: string | null;
|
|
50
|
+
}
|
|
51
|
+
/** @internal */
|
|
52
|
+
export declare function toPageLink(native: NativePageLink): PageLink | null;
|
|
53
|
+
//# sourceMappingURL=links.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,IAAI,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC5E,OAAO,EAAE,KAAK,kBAAkB,EAAiB,MAAM,cAAc,CAAC;AACtE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC;;;;;;;;;;GAUG;AACH,MAAM,MAAM,UAAU,GAClB;IACE,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;CACnC,GACD;IACE;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,iDAAiD;IACjD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,CAAC;AAEN;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACvB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,iDAAiD;IACjD,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,gBAAgB;AAChB,wBAAgB,UAAU,CAAC,MAAM,EAAE,cAAc,GAAG,QAAQ,GAAG,IAAI,CAelE"}
|
package/dist/links.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { toDestination } from './outline.js';
|
|
2
|
+
/** @internal */
|
|
3
|
+
export function toPageLink(native) {
|
|
4
|
+
const target = linkTarget(native);
|
|
5
|
+
// The bindings only emit a link with one target or the other, so this is
|
|
6
|
+
// unreachable in practice; dropping it beats widening the type with a null target.
|
|
7
|
+
if (!target)
|
|
8
|
+
return null;
|
|
9
|
+
return {
|
|
10
|
+
rect: {
|
|
11
|
+
x: native.x0,
|
|
12
|
+
y: native.y0,
|
|
13
|
+
width: native.x1 - native.x0,
|
|
14
|
+
height: native.y1 - native.y0,
|
|
15
|
+
},
|
|
16
|
+
target,
|
|
17
|
+
alt: native.alt ?? null,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function linkTarget(native) {
|
|
21
|
+
if (native.uri !== undefined)
|
|
22
|
+
return { kind: 'uri', uri: native.uri };
|
|
23
|
+
const dest = toDestination(native.dest);
|
|
24
|
+
return dest ? { kind: 'internal', dest } : null;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=links.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"links.js","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"AACA,OAAO,EAA2B,aAAa,EAAE,MAAM,cAAc,CAAC;AAsDtE,gBAAgB;AAChB,MAAM,UAAU,UAAU,CAAC,MAAsB;IAC/C,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAClC,yEAAyE;IACzE,mFAAmF;IACnF,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,OAAO;QACL,IAAI,EAAE;YACJ,CAAC,EAAE,MAAM,CAAC,EAAE;YACZ,CAAC,EAAE,MAAM,CAAC,EAAE;YACZ,KAAK,EAAE,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE;YAC5B,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE;SAC9B;QACD,MAAM;QACN,GAAG,EAAE,MAAM,CAAC,GAAG,IAAI,IAAI;KACxB,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,MAAsB;IACxC,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC;IACtE,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACxC,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC"}
|
package/dist/outline.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { OutlineEntry as NativeEntry } from '@build-qube/papyra-native';
|
|
1
|
+
import type { OutlineDestination as NativeDestination, OutlineEntry as NativeEntry } from '@build-qube/papyra-native';
|
|
2
2
|
/** How a destination positions the page in the window (PDF 32000-1, 12.3.2.2). */
|
|
3
3
|
export type DestinationKind = 'XYZ' | 'Fit' | 'FitH' | 'FitV' | 'FitR' | 'FitB' | 'FitBH' | 'FitBV';
|
|
4
4
|
/**
|
|
@@ -45,6 +45,14 @@ export interface OutlineNode {
|
|
|
45
45
|
/** Nested entries, empty for a leaf. */
|
|
46
46
|
readonly children: OutlineNode[];
|
|
47
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* napi omits absent numbers rather than nulling them; normalise to one shape.
|
|
50
|
+
*
|
|
51
|
+
* Shared with the link reader, whose targets resolve to the same destinations.
|
|
52
|
+
*
|
|
53
|
+
* @internal
|
|
54
|
+
*/
|
|
55
|
+
export declare function toDestination(dest: NativeDestination | undefined): OutlineDestination | null;
|
|
48
56
|
/**
|
|
49
57
|
* Rebuild the tree from the flat pre-order list the bindings return.
|
|
50
58
|
*
|
package/dist/outline.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outline.d.ts","sourceRoot":"","sources":["../src/outline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"outline.d.ts","sourceRoot":"","sources":["../src/outline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,IAAI,iBAAiB,EACvC,YAAY,IAAI,WAAW,EAC5B,MAAM,2BAA2B,CAAC;AAEnC,kFAAkF;AAClF,MAAM,MAAM,eAAe,GACvB,KAAK,GACL,KAAK,GACL,MAAM,GACN,MAAM,GACN,MAAM,GACN,MAAM,GACN,OAAO,GACP,OAAO,CAAC;AAEZ;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,0BAA0B;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,gEAAgE;IAChE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,+DAA+D;IAC/D,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,+CAA+C;IAC/C,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,oFAAoF;IACpF,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,sCAAsC;AACtC,MAAM,WAAW,WAAW;IAC1B,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACzC,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,yDAAyD;IACzD,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,yDAAyD;IACzD,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,WAAW,EAAE,CAAC;CAClC;AAaD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,iBAAiB,GAAG,SAAS,GAClC,kBAAkB,GAAG,IAAI,CAa3B;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,SAAS,WAAW,EAAE,GAC9B,WAAW,EAAE,CAyBf;AAED,sEAAsE;AACtE,wBAAiB,WAAW,CAC1B,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,KAAK,SAAI,GACR,SAAS,CAAC;IACX,iBAAiB;IACjB,IAAI,EAAE,WAAW,CAAC;IAClB,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAKD"}
|
package/dist/outline.js
CHANGED
|
@@ -8,8 +8,14 @@ const KINDS = new Set([
|
|
|
8
8
|
'FitBH',
|
|
9
9
|
'FitBV',
|
|
10
10
|
]);
|
|
11
|
-
/**
|
|
12
|
-
|
|
11
|
+
/**
|
|
12
|
+
* napi omits absent numbers rather than nulling them; normalise to one shape.
|
|
13
|
+
*
|
|
14
|
+
* Shared with the link reader, whose targets resolve to the same destinations.
|
|
15
|
+
*
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
export function toDestination(dest) {
|
|
13
19
|
if (!dest)
|
|
14
20
|
return null;
|
|
15
21
|
return {
|
|
@@ -36,7 +42,7 @@ export function buildOutlineTree(entries) {
|
|
|
36
42
|
const roots = [];
|
|
37
43
|
const stack = [];
|
|
38
44
|
for (const entry of entries) {
|
|
39
|
-
const dest =
|
|
45
|
+
const dest = toDestination(entry.dest);
|
|
40
46
|
const node = {
|
|
41
47
|
title: entry.title,
|
|
42
48
|
dest,
|
package/dist/outline.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outline.js","sourceRoot":"","sources":["../src/outline.ts"],"names":[],"mappings":"AA8DA,MAAM,KAAK,GAAG,IAAI,GAAG,CAAS;IAC5B,KAAK;IACL,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;CACR,CAAC,CAAC;AAEH
|
|
1
|
+
{"version":3,"file":"outline.js","sourceRoot":"","sources":["../src/outline.ts"],"names":[],"mappings":"AA8DA,MAAM,KAAK,GAAG,IAAI,GAAG,CAAS;IAC5B,KAAK;IACL,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;CACR,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAmC;IAEnC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,8EAA8E;QAC9E,iDAAiD;QACjD,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAoB;QACnE,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI;QACvB,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,IAAI;QACrB,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI;QACzB,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,IAAI;QAC3B,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI;KACxB,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAA+B;IAE/B,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,MAAM,KAAK,GAAkB,EAAE,CAAC;IAEhC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,IAAI,GAAgB;YACxB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,IAAI;YACJ,IAAI,EAAE,IAAI,EAAE,IAAI,IAAI,IAAI;YACxB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,QAAQ,EAAE,EAAE;SACb,CAAC;QAEF,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QAClD,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC;QACrB,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QAChC,IAAI,MAAM;YAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;;YAClC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,sEAAsE;AACtE,MAAM,SAAS,CAAC,CAAC,WAAW,CAC1B,KAA6B,EAC7B,KAAK,GAAG,CAAC;IAOT,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QACtB,KAAK,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { StructEntry as NativeEntry } from '@build-qube/papyra-native';
|
|
2
|
+
import type { PageText, TextLine } from './text.js';
|
|
3
|
+
/**
|
|
4
|
+
* One run of page content owned by a {@link StructNode}.
|
|
5
|
+
*
|
|
6
|
+
* The pair is what makes the join work: a marked-content id is only unique within a
|
|
7
|
+
* single page's content stream, so an id on its own addresses nothing.
|
|
8
|
+
*/
|
|
9
|
+
export interface MarkedContent {
|
|
10
|
+
/** 0-based page index. */
|
|
11
|
+
readonly page: number;
|
|
12
|
+
/** Matches {@link TextLine.mcid} on that page. */
|
|
13
|
+
readonly mcid: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* A node in the document structure tree.
|
|
17
|
+
*
|
|
18
|
+
* A tagged PDF states what its content *means* — which runs are a heading, which are
|
|
19
|
+
* a table cell — and, more usefully than either, what order it is meant to be read
|
|
20
|
+
* in. Nothing else in a PDF carries that: {@link PageText.lines} is content-stream
|
|
21
|
+
* order, which interleaves the columns of a two-column page.
|
|
22
|
+
*/
|
|
23
|
+
export interface StructNode {
|
|
24
|
+
/**
|
|
25
|
+
* Standard structure type: `'Document'`, `'H1'`, `'P'`, `'Table'`, `'TD'`,
|
|
26
|
+
* `'Figure'`, and the rest of ISO 32000-1's set.
|
|
27
|
+
*
|
|
28
|
+
* Already resolved through the document's `/RoleMap`, so a file that tags its
|
|
29
|
+
* headings `Heading1` and maps that onto `H1` reports `'H1'` here. Word and
|
|
30
|
+
* InDesign both emit such files, so matching on {@link StructNode.rawRole} instead
|
|
31
|
+
* misses a large share of real tagged documents.
|
|
32
|
+
*/
|
|
33
|
+
readonly role: string;
|
|
34
|
+
/**
|
|
35
|
+
* The document's own tag, before `/RoleMap`. Equal to {@link StructNode.role}
|
|
36
|
+
* unless the document remapped it.
|
|
37
|
+
*/
|
|
38
|
+
readonly rawRole: string;
|
|
39
|
+
/**
|
|
40
|
+
* Content this element owns directly, in the order the tree declares it.
|
|
41
|
+
*
|
|
42
|
+
* Empty for a pure container — a `Sect` whose text all belongs to the `P`s beneath
|
|
43
|
+
* it — which is most interior nodes.
|
|
44
|
+
*/
|
|
45
|
+
readonly content: readonly MarkedContent[];
|
|
46
|
+
/** `/Alt`: replacement text for a figure, and the only text an image has. */
|
|
47
|
+
readonly alt: string | null;
|
|
48
|
+
/**
|
|
49
|
+
* `/ActualText`: text that replaces the content rather than describing it, which is
|
|
50
|
+
* how a document spells out a ligature or a decorative glyph.
|
|
51
|
+
*/
|
|
52
|
+
readonly actualText: string | null;
|
|
53
|
+
/** `/Lang`: a BCP 47 tag overriding the document language for this subtree. */
|
|
54
|
+
readonly lang: string | null;
|
|
55
|
+
/** `/T`: a human-readable title for the element, such as a table's caption. */
|
|
56
|
+
readonly title: string | null;
|
|
57
|
+
/** Nested elements, empty for a leaf. */
|
|
58
|
+
readonly children: StructNode[];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Rebuild the tree from the flat pre-order list the bindings return.
|
|
62
|
+
*
|
|
63
|
+
* The same stack-by-level pass {@link buildOutlineTree} uses, and correct for the same
|
|
64
|
+
* reason: pre-order guarantees a node's parent is the most recent node one level
|
|
65
|
+
* shallower. A level that skips a step cannot come from our own walker, and is clamped
|
|
66
|
+
* rather than trusted — a malformed document should flatten, not crash.
|
|
67
|
+
*/
|
|
68
|
+
export declare function buildStructTree(entries: readonly NativeEntry[]): StructNode[];
|
|
69
|
+
/** Walk a structure tree depth-first, yielding each node with its depth. */
|
|
70
|
+
export declare function walkStructTree(nodes: readonly StructNode[], depth?: number): Generator<{
|
|
71
|
+
/** The element. */
|
|
72
|
+
node: StructNode;
|
|
73
|
+
/** How deep it sits, 0 for a root. */
|
|
74
|
+
depth: number;
|
|
75
|
+
}>;
|
|
76
|
+
/** One line of a page, with the structure element that claims it. */
|
|
77
|
+
export interface OrderedLine {
|
|
78
|
+
/** The line, exactly as {@link PageText} reported it. */
|
|
79
|
+
readonly line: TextLine;
|
|
80
|
+
/**
|
|
81
|
+
* The element whose content the line's first glyph sits in, or `null` for a line
|
|
82
|
+
* the structure tree does not account for.
|
|
83
|
+
*/
|
|
84
|
+
readonly node: StructNode | null;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Put a page's lines into the reading order the document declares.
|
|
88
|
+
*
|
|
89
|
+
* This is the payoff of a tagged PDF and the one thing geometry cannot recover: on a
|
|
90
|
+
* two-column page the content stream may draw both columns interleaved, and no line
|
|
91
|
+
* grouping fixes that, because the drawing order genuinely is what it is. The
|
|
92
|
+
* structure tree states the intended order outright.
|
|
93
|
+
*
|
|
94
|
+
* Lines are keyed by their first glyph's {@link TextLine.mcid}, so a line is placed by
|
|
95
|
+
* the element that *starts* it. Ties — several lines inside one `P`, which is the
|
|
96
|
+
* normal case for a wrapped paragraph — keep their original relative order, so within
|
|
97
|
+
* an element the result is still the content stream's sequence. That is what makes
|
|
98
|
+
* this safe on a document whose tagging is partial.
|
|
99
|
+
*
|
|
100
|
+
* Lines with no structure element go **last**, rather than being dropped: untagged
|
|
101
|
+
* content is usually a running head or a page number, and losing it silently would be
|
|
102
|
+
* worse than putting it at the end. Pass `includeUntagged: false` to drop them.
|
|
103
|
+
*
|
|
104
|
+
* Returns the lines in content-stream order, unchanged, when the page has no tagged
|
|
105
|
+
* content at all — an untagged document is the common case and should not come back
|
|
106
|
+
* empty or reshuffled.
|
|
107
|
+
*/
|
|
108
|
+
export declare function readingOrder(text: PageText, tree: readonly StructNode[], options?: {
|
|
109
|
+
/** Keep lines no element claims, at the end. Defaults to `true`. */
|
|
110
|
+
readonly includeUntagged?: boolean;
|
|
111
|
+
}): OrderedLine[];
|
|
112
|
+
/**
|
|
113
|
+
* Every character of a page in declared reading order, one line per entry.
|
|
114
|
+
*
|
|
115
|
+
* The structure-aware counterpart to {@link pageString}; identical to it on an
|
|
116
|
+
* untagged page.
|
|
117
|
+
*/
|
|
118
|
+
export declare function structuredPageString(text: PageText, tree: readonly StructNode[]): string;
|
|
119
|
+
//# sourceMappingURL=structure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structure.d.ts","sourceRoot":"","sources":["../src/structure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,IAAI,WAAW,EAE3B,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,0BAA0B;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACzB;;;;;;;;OAQG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;IAC3C,6EAA6E;IAC7E,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,+EAA+E;IAC/E,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,yCAAyC;IACzC,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAC;CACjC;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,GAAG,UAAU,EAAE,CAyB7E;AAED,4EAA4E;AAC5E,wBAAiB,cAAc,CAC7B,KAAK,EAAE,SAAS,UAAU,EAAE,EAC5B,KAAK,SAAI,GACR,SAAS,CAAC;IACX,mBAAmB;IACnB,IAAI,EAAE,UAAU,CAAC;IACjB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAKD;AAED,qEAAqE;AACrE,MAAM,WAAW,WAAW;IAC1B,yDAAyD;IACzD,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,SAAS,UAAU,EAAE,EAC3B,OAAO,GAAE;IACP,oEAAoE;IACpE,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;CAC/B,GACL,WAAW,EAAE,CA4Cf;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,SAAS,UAAU,EAAE,GAC1B,MAAM,CAIR"}
|