yom-format 0.1.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/LICENSE +21 -0
- package/README.md +86 -0
- package/dist/cli.d.ts +30 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +344 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/pipeline/avif.d.ts +3 -0
- package/dist/pipeline/avif.d.ts.map +1 -0
- package/dist/pipeline/avif.js +30 -0
- package/dist/pipeline/avif.js.map +1 -0
- package/dist/pipeline/convert.d.ts +28 -0
- package/dist/pipeline/convert.d.ts.map +1 -0
- package/dist/pipeline/convert.js +111 -0
- package/dist/pipeline/convert.js.map +1 -0
- package/dist/pipeline/index.d.ts +17 -0
- package/dist/pipeline/index.d.ts.map +1 -0
- package/dist/pipeline/index.js +17 -0
- package/dist/pipeline/index.js.map +1 -0
- package/dist/pipeline/ocrLayoutBuilder.d.ts +10 -0
- package/dist/pipeline/ocrLayoutBuilder.d.ts.map +1 -0
- package/dist/pipeline/ocrLayoutBuilder.js +62 -0
- package/dist/pipeline/ocrLayoutBuilder.js.map +1 -0
- package/dist/pipeline/pdfDocument.d.ts +12 -0
- package/dist/pipeline/pdfDocument.d.ts.map +1 -0
- package/dist/pipeline/pdfDocument.js +76 -0
- package/dist/pipeline/pdfDocument.js.map +1 -0
- package/dist/pipeline/renderPage.d.ts +10 -0
- package/dist/pipeline/renderPage.d.ts.map +1 -0
- package/dist/pipeline/renderPage.js +36 -0
- package/dist/pipeline/renderPage.js.map +1 -0
- package/dist/pipeline/textExtract.d.ts +29 -0
- package/dist/pipeline/textExtract.d.ts.map +1 -0
- package/dist/pipeline/textExtract.js +48 -0
- package/dist/pipeline/textExtract.js.map +1 -0
- package/dist/yom/blobLimits.d.ts +15 -0
- package/dist/yom/blobLimits.d.ts.map +1 -0
- package/dist/yom/blobLimits.js +25 -0
- package/dist/yom/blobLimits.js.map +1 -0
- package/dist/yom/byteSource.d.ts +56 -0
- package/dist/yom/byteSource.d.ts.map +1 -0
- package/dist/yom/byteSource.js +111 -0
- package/dist/yom/byteSource.js.map +1 -0
- package/dist/yom/bytes.d.ts +2 -0
- package/dist/yom/bytes.d.ts.map +1 -0
- package/dist/yom/bytes.js +13 -0
- package/dist/yom/bytes.js.map +1 -0
- package/dist/yom/constants.d.ts +34 -0
- package/dist/yom/constants.d.ts.map +1 -0
- package/dist/yom/constants.js +82 -0
- package/dist/yom/constants.js.map +1 -0
- package/dist/yom/errors.d.ts +44 -0
- package/dist/yom/errors.d.ts.map +1 -0
- package/dist/yom/errors.js +44 -0
- package/dist/yom/errors.js.map +1 -0
- package/dist/yom/flatbufferVerify.d.ts +21 -0
- package/dist/yom/flatbufferVerify.d.ts.map +1 -0
- package/dist/yom/flatbufferVerify.js +255 -0
- package/dist/yom/flatbufferVerify.js.map +1 -0
- package/dist/yom/generated/yomu/yom/blob-kind.d.ts +9 -0
- package/dist/yom/generated/yomu/yom/blob-kind.d.ts.map +1 -0
- package/dist/yom/generated/yomu/yom/blob-kind.js +12 -0
- package/dist/yom/generated/yomu/yom/blob-kind.js.map +1 -0
- package/dist/yom/generated/yomu/yom/blob-ref.d.ts +45 -0
- package/dist/yom/generated/yomu/yom/blob-ref.d.ts.map +1 -0
- package/dist/yom/generated/yomu/yom/blob-ref.js +141 -0
- package/dist/yom/generated/yomu/yom/blob-ref.js.map +1 -0
- package/dist/yom/generated/yomu/yom/book-metadata.d.ts +32 -0
- package/dist/yom/generated/yomu/yom/book-metadata.d.ts.map +1 -0
- package/dist/yom/generated/yomu/yom/book-metadata.js +89 -0
- package/dist/yom/generated/yomu/yom/book-metadata.js.map +1 -0
- package/dist/yom/generated/yomu/yom/compression.d.ts +5 -0
- package/dist/yom/generated/yomu/yom/compression.d.ts.map +1 -0
- package/dist/yom/generated/yomu/yom/compression.js +8 -0
- package/dist/yom/generated/yomu/yom/compression.js.map +1 -0
- package/dist/yom/generated/yomu/yom/main-index.d.ts +63 -0
- package/dist/yom/generated/yomu/yom/main-index.d.ts.map +1 -0
- package/dist/yom/generated/yomu/yom/main-index.js +208 -0
- package/dist/yom/generated/yomu/yom/main-index.js.map +1 -0
- package/dist/yom/generated/yomu/yom/ocrblock.d.ts +32 -0
- package/dist/yom/generated/yomu/yom/ocrblock.d.ts.map +1 -0
- package/dist/yom/generated/yomu/yom/ocrblock.js +84 -0
- package/dist/yom/generated/yomu/yom/ocrblock.js.map +1 -0
- package/dist/yom/generated/yomu/yom/ocrlayout.d.ts +27 -0
- package/dist/yom/generated/yomu/yom/ocrlayout.d.ts.map +1 -0
- package/dist/yom/generated/yomu/yom/ocrlayout.js +76 -0
- package/dist/yom/generated/yomu/yom/ocrlayout.js.map +1 -0
- package/dist/yom/generated/yomu/yom/ocrline.d.ts +35 -0
- package/dist/yom/generated/yomu/yom/ocrline.d.ts.map +1 -0
- package/dist/yom/generated/yomu/yom/ocrline.js +95 -0
- package/dist/yom/generated/yomu/yom/ocrline.js.map +1 -0
- package/dist/yom/generated/yomu/yom/ocrpage.d.ts +46 -0
- package/dist/yom/generated/yomu/yom/ocrpage.d.ts.map +1 -0
- package/dist/yom/generated/yomu/yom/ocrpage.js +147 -0
- package/dist/yom/generated/yomu/yom/ocrpage.js.map +1 -0
- package/dist/yom/generated/yomu/yom/ocrtoken.d.ts +44 -0
- package/dist/yom/generated/yomu/yom/ocrtoken.d.ts.map +1 -0
- package/dist/yom/generated/yomu/yom/ocrtoken.js +128 -0
- package/dist/yom/generated/yomu/yom/ocrtoken.js.map +1 -0
- package/dist/yom/generated/yomu/yom/outline-entry.d.ts +31 -0
- package/dist/yom/generated/yomu/yom/outline-entry.d.ts.map +1 -0
- package/dist/yom/generated/yomu/yom/outline-entry.js +92 -0
- package/dist/yom/generated/yomu/yom/outline-entry.js.map +1 -0
- package/dist/yom/generated/yomu/yom/page-entry.d.ts +95 -0
- package/dist/yom/generated/yomu/yom/page-entry.d.ts.map +1 -0
- package/dist/yom/generated/yomu/yom/page-entry.js +288 -0
- package/dist/yom/generated/yomu/yom/page-entry.js.map +1 -0
- package/dist/yom/generated/yomu/yom/pdfexport-metadata.d.ts +32 -0
- package/dist/yom/generated/yomu/yom/pdfexport-metadata.d.ts.map +1 -0
- package/dist/yom/generated/yomu/yom/pdfexport-metadata.js +96 -0
- package/dist/yom/generated/yomu/yom/pdfexport-metadata.js.map +1 -0
- package/dist/yom/generated/yomu/yom/reading-direction.d.ts +5 -0
- package/dist/yom/generated/yomu/yom/reading-direction.d.ts.map +1 -0
- package/dist/yom/generated/yomu/yom/reading-direction.js +8 -0
- package/dist/yom/generated/yomu/yom/reading-direction.js.map +1 -0
- package/dist/yom/generated/yomu/yom/search-term-ref.d.ts +34 -0
- package/dist/yom/generated/yomu/yom/search-term-ref.d.ts.map +1 -0
- package/dist/yom/generated/yomu/yom/search-term-ref.js +99 -0
- package/dist/yom/generated/yomu/yom/search-term-ref.js.map +1 -0
- package/dist/yom/generated/yomu/yom.d.ts +6 -0
- package/dist/yom/generated/yomu/yom.d.ts.map +1 -0
- package/dist/yom/generated/yomu/yom.js +8 -0
- package/dist/yom/generated/yomu/yom.js.map +1 -0
- package/dist/yom/hash.d.ts +4 -0
- package/dist/yom/hash.d.ts.map +1 -0
- package/dist/yom/hash.js +21 -0
- package/dist/yom/hash.js.map +1 -0
- package/dist/yom/header.d.ts +44 -0
- package/dist/yom/header.d.ts.map +1 -0
- package/dist/yom/header.js +115 -0
- package/dist/yom/header.js.map +1 -0
- package/dist/yom/reader.d.ts +57 -0
- package/dist/yom/reader.d.ts.map +1 -0
- package/dist/yom/reader.js +141 -0
- package/dist/yom/reader.js.map +1 -0
- package/dist/yom/searchIndex.d.ts +41 -0
- package/dist/yom/searchIndex.d.ts.map +1 -0
- package/dist/yom/searchIndex.js +133 -0
- package/dist/yom/searchIndex.js.map +1 -0
- package/dist/yom/textNormalizer.d.ts +19 -0
- package/dist/yom/textNormalizer.d.ts.map +1 -0
- package/dist/yom/textNormalizer.js +77 -0
- package/dist/yom/textNormalizer.js.map +1 -0
- package/dist/yom/validator.d.ts +14 -0
- package/dist/yom/validator.d.ts.map +1 -0
- package/dist/yom/validator.js +197 -0
- package/dist/yom/validator.js.map +1 -0
- package/dist/yom/writer.d.ts +76 -0
- package/dist/yom/writer.d.ts.map +1 -0
- package/dist/yom/writer.js +154 -0
- package/dist/yom/writer.js.map +1 -0
- package/dist/yom/zstd.d.ts +14 -0
- package/dist/yom/zstd.d.ts.map +1 -0
- package/dist/yom/zstd.js +43 -0
- package/dist/yom/zstd.js.map +1 -0
- package/package.json +65 -0
- package/src/cli.ts +372 -0
- package/src/index.ts +109 -0
- package/src/pipeline/avif.ts +33 -0
- package/src/pipeline/convert.ts +148 -0
- package/src/pipeline/index.ts +28 -0
- package/src/pipeline/ocrLayoutBuilder.ts +73 -0
- package/src/pipeline/pdfDocument.ts +86 -0
- package/src/pipeline/renderPage.ts +48 -0
- package/src/pipeline/textExtract.ts +64 -0
- package/src/worker/convert.worker.ts +54 -0
- package/src/yom/blobLimits.ts +30 -0
- package/src/yom/byteSource.ts +144 -0
- package/src/yom/bytes.ts +11 -0
- package/src/yom/constants.ts +89 -0
- package/src/yom/errors.ts +43 -0
- package/src/yom/flatbufferVerify.ts +298 -0
- package/src/yom/generated/yomu/yom/blob-kind.ts +12 -0
- package/src/yom/generated/yomu/yom/blob-ref.ts +184 -0
- package/src/yom/generated/yomu/yom/book-metadata.ts +121 -0
- package/src/yom/generated/yomu/yom/compression.ts +8 -0
- package/src/yom/generated/yomu/yom/main-index.ts +257 -0
- package/src/yom/generated/yomu/yom/ocrblock.ts +117 -0
- package/src/yom/generated/yomu/yom/ocrlayout.ts +102 -0
- package/src/yom/generated/yomu/yom/ocrline.ts +131 -0
- package/src/yom/generated/yomu/yom/ocrpage.ts +191 -0
- package/src/yom/generated/yomu/yom/ocrtoken.ts +173 -0
- package/src/yom/generated/yomu/yom/outline-entry.ts +124 -0
- package/src/yom/generated/yomu/yom/page-entry.ts +388 -0
- package/src/yom/generated/yomu/yom/pdfexport-metadata.ts +128 -0
- package/src/yom/generated/yomu/yom/reading-direction.ts +8 -0
- package/src/yom/generated/yomu/yom/search-term-ref.ts +134 -0
- package/src/yom/generated/yomu/yom.ts +9 -0
- package/src/yom/hash.ts +20 -0
- package/src/yom/header.ts +132 -0
- package/src/yom/reader.ts +163 -0
- package/src/yom/searchIndex.ts +178 -0
- package/src/yom/textNormalizer.ts +92 -0
- package/src/yom/validator.ts +245 -0
- package/src/yom/writer.ts +337 -0
- package/src/yom/zstd.ts +47 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 juntaki
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# yom-format
|
|
2
|
+
|
|
3
|
+
TypeScript implementation of the [YOM](https://github.com/juntaki/yom-format)
|
|
4
|
+
packfile format: a read-only, single-file package for scanned books (AVIF
|
|
5
|
+
pages, a FlatBuffers index, and optional OCR / full-text search data). This
|
|
6
|
+
package provides a reader, writer, and validator, plus an optional
|
|
7
|
+
browser-side PDF → `.yom` conversion pipeline.
|
|
8
|
+
|
|
9
|
+
The format specification lives at
|
|
10
|
+
[`docs/format-spec.md`](https://github.com/juntaki/yom-format/blob/main/docs/format-spec.md)
|
|
11
|
+
in the main repository; this package is one of two implementations kept
|
|
12
|
+
byte-compatible with it (the other is the Swift package in `swift/`, used by
|
|
13
|
+
[Yomu](https://yomu.juntaki.com)).
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
npm install yom-format
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Read a `.yom` file
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { YOMPackfileReader } from "yom-format";
|
|
25
|
+
|
|
26
|
+
const bytes = new Uint8Array(await readFile("book.yom")); // however you load the file
|
|
27
|
+
const reader = await YOMPackfileReader.open(bytes);
|
|
28
|
+
|
|
29
|
+
console.log(reader.title, reader.pageCount);
|
|
30
|
+
const avifPage = await reader.pageImage(0); // AVIF bytes for page 0
|
|
31
|
+
const avifThumb = await reader.thumbnailImage(0);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Validate a `.yom` file
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import { validateYOM, YOMValidationError } from "yom-format";
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
await validateYOM(bytes);
|
|
41
|
+
console.log("valid");
|
|
42
|
+
} catch (error) {
|
|
43
|
+
if (error instanceof YOMValidationError) {
|
|
44
|
+
console.error("invalid package:", error.message);
|
|
45
|
+
} else {
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The main entry also exports `writeYOM` (build a package from pages + blobs),
|
|
52
|
+
`buildSearchIndex` / `decodePostings` (the bigram search index), and the
|
|
53
|
+
lower-level `constants` / `header` helpers used by all three.
|
|
54
|
+
|
|
55
|
+
## PDF → `.yom` conversion (browser only)
|
|
56
|
+
|
|
57
|
+
Converting a PDF into a `.yom` package is a separate subpath so the core
|
|
58
|
+
reader/writer stays free of pdf.js and image-codec dependencies:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { convertPdfToYom } from "yom-format/pipeline";
|
|
62
|
+
|
|
63
|
+
const yomBytes = await convertPdfToYom(pdfBytes, {
|
|
64
|
+
title: "Book Title",
|
|
65
|
+
onProgress: (stage, fraction) => console.log(stage, fraction),
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
This pipeline renders with pdf.js onto a `Canvas`/`OffscreenCanvas`, encodes
|
|
70
|
+
pages and thumbnails as AVIF, and writes a validated package — it requires a
|
|
71
|
+
DOM environment and a bundler that can handle pdf.js's worker and the
|
|
72
|
+
WebAssembly codecs (`@bokuweb/zstd-wasm`, `@jsquash/avif`); it will not run
|
|
73
|
+
under plain Node. It is not bundled with a Web Worker wrapper — wrap
|
|
74
|
+
`convertPdfToYom` in your own worker if you need conversion off the main
|
|
75
|
+
thread (see `src/worker/convert.worker.ts` in the repository for the pattern
|
|
76
|
+
this project uses internally).
|
|
77
|
+
|
|
78
|
+
## Links
|
|
79
|
+
|
|
80
|
+
- Format specification: [`docs/format-spec.md`](https://github.com/juntaki/yom-format/blob/main/docs/format-spec.md)
|
|
81
|
+
- Source repository: [github.com/juntaki/yom-format](https://github.com/juntaki/yom-format)
|
|
82
|
+
- Built for [Yomu](https://yomu.juntaki.com), an iOS reader for scanned PDFs
|
|
83
|
+
|
|
84
|
+
## License
|
|
85
|
+
|
|
86
|
+
MIT
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
export interface CliIO {
|
|
3
|
+
out(line: string): void;
|
|
4
|
+
err(line: string): void;
|
|
5
|
+
}
|
|
6
|
+
interface ParsedArgs {
|
|
7
|
+
positionals: string[];
|
|
8
|
+
json: boolean;
|
|
9
|
+
page?: number;
|
|
10
|
+
kind?: string;
|
|
11
|
+
out?: string;
|
|
12
|
+
}
|
|
13
|
+
/** `info` -- magic, version, sizes, page count, index summary. */
|
|
14
|
+
export declare function cmdInfo(args: ParsedArgs, io: CliIO): Promise<number>;
|
|
15
|
+
/** `verify` -- full validation for a local file; per-blob ranged verify for a URL. */
|
|
16
|
+
export declare function cmdVerify(args: ParsedArgs, io: CliIO): Promise<number>;
|
|
17
|
+
/** `ls` -- per-page index, label, dimensions, and page-image blob size. */
|
|
18
|
+
export declare function cmdLs(args: ParsedArgs, io: CliIO): Promise<number>;
|
|
19
|
+
/** `extract` -- write one blob (page image/thumbnail, or file-wide ocr/text) to disk. */
|
|
20
|
+
export declare function cmdExtract(args: ParsedArgs, io: CliIO): Promise<number>;
|
|
21
|
+
/** `meta` -- book metadata + page labels + outline (when present) as JSON. */
|
|
22
|
+
export declare function cmdMeta(args: ParsedArgs, io: CliIO): Promise<number>;
|
|
23
|
+
/**
|
|
24
|
+
* Dispatches a parsed argv to a command handler. Returns the process exit
|
|
25
|
+
* code (0 ok, non-zero on failure / bad args). Never throws for usage
|
|
26
|
+
* errors -- they are reported and mapped to exit code 2.
|
|
27
|
+
*/
|
|
28
|
+
export declare function runCli(argv: string[], io: CliIO): Promise<number>;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAwBA,MAAM,WAAW,KAAK;IACpB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,UAAU,UAAU;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAoDD,kEAAkE;AAClE,wBAAsB,OAAO,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAwC1E;AAED,sFAAsF;AACtF,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAwB5E;AAED,2EAA2E;AAC3E,wBAAsB,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAmCxE;AAED,yFAAyF;AACzF,wBAAsB,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAgC7E;AAED,8EAA8E;AAC9E,wBAAsB,OAAO,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CA4B1E;AAgDD;;;;GAIG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CA4CvE"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* `yom` -- a small, dependency-light CLI for inspecting, verifying, and
|
|
4
|
+
* extracting from existing `.yom` packfiles.
|
|
5
|
+
*
|
|
6
|
+
* Commands: info | verify | ls | extract | meta. `verify` also accepts an
|
|
7
|
+
* HTTP(S) URL (exercising the Gap-1 ranged reader end-to-end); the others
|
|
8
|
+
* operate on a local file. PDF -> .yom conversion is intentionally NOT here:
|
|
9
|
+
* that pipeline is browser-only. Use the web convert tool or the iOS app.
|
|
10
|
+
*
|
|
11
|
+
* Command handlers are exported for testability; the process entry point at
|
|
12
|
+
* the bottom only runs when the file is executed directly.
|
|
13
|
+
*/
|
|
14
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
15
|
+
import { pathToFileURL } from "node:url";
|
|
16
|
+
import { YOMPackfileReader } from "./yom/reader.js";
|
|
17
|
+
import { validateYOM } from "./yom/validator.js";
|
|
18
|
+
import { parseHeaderFields } from "./yom/header.js";
|
|
19
|
+
import { YOM_HEADER_SIZE } from "./yom/constants.js";
|
|
20
|
+
import { pdfExportPresent } from "./yom/flatbufferVerify.js";
|
|
21
|
+
import { ReadingDirection } from "./yom/generated/yomu/yom/reading-direction.js";
|
|
22
|
+
const VALUE_FLAGS = new Set(["--page", "--kind", "-o", "--out"]);
|
|
23
|
+
function parseArgs(args) {
|
|
24
|
+
const parsed = { positionals: [], json: false };
|
|
25
|
+
for (let i = 0; i < args.length; i++) {
|
|
26
|
+
const arg = args[i];
|
|
27
|
+
if (arg === "--json") {
|
|
28
|
+
parsed.json = true;
|
|
29
|
+
}
|
|
30
|
+
else if (VALUE_FLAGS.has(arg)) {
|
|
31
|
+
const value = args[++i];
|
|
32
|
+
if (value === undefined)
|
|
33
|
+
throw new CliUsageError(`missing value for ${arg}`);
|
|
34
|
+
if (arg === "--page")
|
|
35
|
+
parsed.page = Number(value);
|
|
36
|
+
else if (arg === "--kind")
|
|
37
|
+
parsed.kind = value;
|
|
38
|
+
else
|
|
39
|
+
parsed.out = value; // -o | --out
|
|
40
|
+
}
|
|
41
|
+
else if (arg.startsWith("-")) {
|
|
42
|
+
throw new CliUsageError(`unknown flag ${arg}`);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
parsed.positionals.push(arg);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return parsed;
|
|
49
|
+
}
|
|
50
|
+
class CliUsageError extends Error {
|
|
51
|
+
}
|
|
52
|
+
const USAGE = `yom -- inspect and extract from .yom packfiles
|
|
53
|
+
|
|
54
|
+
Usage:
|
|
55
|
+
yom info <file.yom> [--json]
|
|
56
|
+
yom verify <file.yom | url> [--json]
|
|
57
|
+
yom ls <file.yom> [--json]
|
|
58
|
+
yom extract <file.yom> --page N --kind image|thumb|ocr|text -o <out>
|
|
59
|
+
yom meta <file.yom>
|
|
60
|
+
|
|
61
|
+
Note: PDF -> .yom conversion is browser-only; use the web convert tool or the
|
|
62
|
+
iOS app. There is no 'convert' command.`;
|
|
63
|
+
function isUrl(target) {
|
|
64
|
+
return /^https?:\/\//i.test(target);
|
|
65
|
+
}
|
|
66
|
+
async function loadLocalBytes(path) {
|
|
67
|
+
const buf = await readFile(path);
|
|
68
|
+
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
69
|
+
}
|
|
70
|
+
function readingDirectionName(value) {
|
|
71
|
+
return ReadingDirection[value] ?? String(value);
|
|
72
|
+
}
|
|
73
|
+
/** `info` -- magic, version, sizes, page count, index summary. */
|
|
74
|
+
export async function cmdInfo(args, io) {
|
|
75
|
+
const target = args.positionals[0];
|
|
76
|
+
if (!target)
|
|
77
|
+
throw new CliUsageError("info requires a <file.yom>");
|
|
78
|
+
const bytes = await loadLocalBytes(target);
|
|
79
|
+
const reader = await YOMPackfileReader.open(bytes);
|
|
80
|
+
const header = parseHeaderFields(bytes.subarray(0, YOM_HEADER_SIZE));
|
|
81
|
+
const index = reader.mainIndex;
|
|
82
|
+
const info = {
|
|
83
|
+
magic: new TextDecoder().decode(header.magic),
|
|
84
|
+
formatVersion: header.formatVersion,
|
|
85
|
+
fileSize: bytes.length,
|
|
86
|
+
indexOffset: Number(header.indexOffset),
|
|
87
|
+
indexLength: Number(header.indexUncompressedLength),
|
|
88
|
+
pageCount: reader.pageCount,
|
|
89
|
+
blobCount: index.blobsLength(),
|
|
90
|
+
title: reader.title,
|
|
91
|
+
hasOcr: index.ocrLayoutBlobIndex() >= 0,
|
|
92
|
+
hasNormalizedText: index.normalizedTextBlobIndex() >= 0,
|
|
93
|
+
hasSearch: index.searchDictionaryBlobIndex() >= 0,
|
|
94
|
+
searchTermCount: index.searchTermsLength(),
|
|
95
|
+
};
|
|
96
|
+
if (args.json) {
|
|
97
|
+
io.out(JSON.stringify(info, null, 2));
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
io.out(`magic: ${info.magic}`);
|
|
101
|
+
io.out(`formatVersion: ${info.formatVersion}`);
|
|
102
|
+
io.out(`fileSize: ${info.fileSize}`);
|
|
103
|
+
io.out(`indexOffset: ${info.indexOffset}`);
|
|
104
|
+
io.out(`indexLength: ${info.indexLength}`);
|
|
105
|
+
io.out(`title: ${info.title}`);
|
|
106
|
+
io.out(`pageCount: ${info.pageCount}`);
|
|
107
|
+
io.out(`blobCount: ${info.blobCount}`);
|
|
108
|
+
io.out(`hasOcr: ${info.hasOcr}`);
|
|
109
|
+
io.out(`hasNormalizedText:${info.hasNormalizedText}`);
|
|
110
|
+
io.out(`hasSearch: ${info.hasSearch}`);
|
|
111
|
+
io.out(`searchTermCount: ${info.searchTermCount}`);
|
|
112
|
+
}
|
|
113
|
+
return 0;
|
|
114
|
+
}
|
|
115
|
+
/** `verify` -- full validation for a local file; per-blob ranged verify for a URL. */
|
|
116
|
+
export async function cmdVerify(args, io) {
|
|
117
|
+
const target = args.positionals[0];
|
|
118
|
+
if (!target)
|
|
119
|
+
throw new CliUsageError("verify requires a <file.yom | url>");
|
|
120
|
+
try {
|
|
121
|
+
if (isUrl(target)) {
|
|
122
|
+
// Exercise the ranged reader end-to-end: open reads header+index (with
|
|
123
|
+
// bounded index verify), then each blob read verifies its own SHA-256.
|
|
124
|
+
const reader = await YOMPackfileReader.openURL(target, { fallbackToFullFetch: true });
|
|
125
|
+
for (let i = 0; i < reader.mainIndex.blobsLength(); i++) {
|
|
126
|
+
await reader.readBlob(i);
|
|
127
|
+
}
|
|
128
|
+
report(io, args.json, { ok: true, target, mode: "range-per-blob" });
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
const bytes = await loadLocalBytes(target);
|
|
132
|
+
await validateYOM(bytes);
|
|
133
|
+
report(io, args.json, { ok: true, target, mode: "full" });
|
|
134
|
+
}
|
|
135
|
+
return 0;
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
139
|
+
report(io, args.json, { ok: false, target, reason });
|
|
140
|
+
return 1;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/** `ls` -- per-page index, label, dimensions, and page-image blob size. */
|
|
144
|
+
export async function cmdLs(args, io) {
|
|
145
|
+
const target = args.positionals[0];
|
|
146
|
+
if (!target)
|
|
147
|
+
throw new CliUsageError("ls requires a <file.yom>");
|
|
148
|
+
const bytes = await loadLocalBytes(target);
|
|
149
|
+
const reader = await YOMPackfileReader.open(bytes);
|
|
150
|
+
const index = reader.mainIndex;
|
|
151
|
+
const rows = [];
|
|
152
|
+
for (let i = 0; i < reader.pageCount; i++) {
|
|
153
|
+
const page = reader.page(i);
|
|
154
|
+
const imageBlob = index.blobs(page.pageImageBlobIndex());
|
|
155
|
+
rows.push({
|
|
156
|
+
page: i,
|
|
157
|
+
label: page.pageLabel() ?? "",
|
|
158
|
+
pixelWidth: page.pixelWidth(),
|
|
159
|
+
pixelHeight: page.pixelHeight(),
|
|
160
|
+
imageBlobIndex: page.pageImageBlobIndex(),
|
|
161
|
+
imageBlobBytes: imageBlob ? Number(imageBlob.compressedLength()) : 0,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
const hasOcr = index.ocrLayoutBlobIndex() >= 0;
|
|
165
|
+
const hasNormalizedText = index.normalizedTextBlobIndex() >= 0;
|
|
166
|
+
if (args.json) {
|
|
167
|
+
io.out(JSON.stringify({ pageCount: reader.pageCount, hasOcr, hasNormalizedText, pages: rows }, null, 2));
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
io.out(`pages: ${reader.pageCount} hasOcr: ${hasOcr} hasNormalizedText: ${hasNormalizedText}`);
|
|
171
|
+
io.out("idx label WxH imageBytes");
|
|
172
|
+
for (const r of rows) {
|
|
173
|
+
io.out(`${String(r.page).padEnd(4)} ${r.label.padEnd(16)} ${`${r.pixelWidth}x${r.pixelHeight}`.padEnd(13)} ${r.imageBlobBytes}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return 0;
|
|
177
|
+
}
|
|
178
|
+
/** `extract` -- write one blob (page image/thumbnail, or file-wide ocr/text) to disk. */
|
|
179
|
+
export async function cmdExtract(args, io) {
|
|
180
|
+
const target = args.positionals[0];
|
|
181
|
+
if (!target)
|
|
182
|
+
throw new CliUsageError("extract requires a <file.yom>");
|
|
183
|
+
if (!args.kind)
|
|
184
|
+
throw new CliUsageError("extract requires --kind image|thumb|ocr|text");
|
|
185
|
+
if (!args.out)
|
|
186
|
+
throw new CliUsageError("extract requires -o <out>");
|
|
187
|
+
const bytes = await loadLocalBytes(target);
|
|
188
|
+
const reader = await YOMPackfileReader.open(bytes);
|
|
189
|
+
const index = reader.mainIndex;
|
|
190
|
+
let data;
|
|
191
|
+
switch (args.kind) {
|
|
192
|
+
case "image":
|
|
193
|
+
requirePage(args);
|
|
194
|
+
data = await reader.pageImage(args.page);
|
|
195
|
+
break;
|
|
196
|
+
case "thumb":
|
|
197
|
+
requirePage(args);
|
|
198
|
+
data = await reader.thumbnailImage(args.page);
|
|
199
|
+
break;
|
|
200
|
+
case "ocr":
|
|
201
|
+
data = await readFileWideBlob(reader, index.ocrLayoutBlobIndex(), "ocr");
|
|
202
|
+
break;
|
|
203
|
+
case "text":
|
|
204
|
+
data = await readFileWideBlob(reader, index.normalizedTextBlobIndex(), "normalized text");
|
|
205
|
+
break;
|
|
206
|
+
default:
|
|
207
|
+
throw new CliUsageError(`unknown --kind ${args.kind} (expected image|thumb|ocr|text)`);
|
|
208
|
+
}
|
|
209
|
+
await writeFile(args.out, data);
|
|
210
|
+
io.out(`wrote ${data.length} bytes to ${args.out}`);
|
|
211
|
+
return 0;
|
|
212
|
+
}
|
|
213
|
+
/** `meta` -- book metadata + page labels + outline (when present) as JSON. */
|
|
214
|
+
export async function cmdMeta(args, io) {
|
|
215
|
+
const target = args.positionals[0];
|
|
216
|
+
if (!target)
|
|
217
|
+
throw new CliUsageError("meta requires a <file.yom>");
|
|
218
|
+
const bytes = await loadLocalBytes(target);
|
|
219
|
+
const reader = await YOMPackfileReader.open(bytes);
|
|
220
|
+
const index = reader.mainIndex;
|
|
221
|
+
const book = index.book();
|
|
222
|
+
const pageLabels = [];
|
|
223
|
+
for (let i = 0; i < reader.pageCount; i++) {
|
|
224
|
+
pageLabels.push(reader.page(i).pageLabel() ?? "");
|
|
225
|
+
}
|
|
226
|
+
const header = parseHeaderFields(bytes.subarray(0, YOM_HEADER_SIZE));
|
|
227
|
+
const indexOffset = Number(header.indexOffset);
|
|
228
|
+
const indexBytes = bytes.subarray(indexOffset, indexOffset + Number(header.indexUncompressedLength));
|
|
229
|
+
const meta = {
|
|
230
|
+
title: reader.title,
|
|
231
|
+
pageCount: book ? book.pageCount() : reader.pageCount,
|
|
232
|
+
readingDirection: book ? readingDirectionName(book.readingDirection()) : null,
|
|
233
|
+
createdAtUnix: book ? book.createdAtUnix().toString() : null,
|
|
234
|
+
pageLabels,
|
|
235
|
+
outline: pdfExportPresent(indexBytes) ? readOutline(index) : [],
|
|
236
|
+
};
|
|
237
|
+
io.out(JSON.stringify(meta, null, 2));
|
|
238
|
+
return 0;
|
|
239
|
+
}
|
|
240
|
+
function readOutline(index) {
|
|
241
|
+
const pdf = index.pdfExport();
|
|
242
|
+
if (!pdf)
|
|
243
|
+
return [];
|
|
244
|
+
const nodes = [];
|
|
245
|
+
for (let i = 0; i < pdf.outlineLength(); i++) {
|
|
246
|
+
const entry = pdf.outline(i);
|
|
247
|
+
if (entry)
|
|
248
|
+
nodes.push(readOutlineEntry(entry));
|
|
249
|
+
}
|
|
250
|
+
return nodes;
|
|
251
|
+
}
|
|
252
|
+
function readOutlineEntry(entry) {
|
|
253
|
+
const children = [];
|
|
254
|
+
for (let i = 0; i < entry.childrenLength(); i++) {
|
|
255
|
+
const child = entry.children(i);
|
|
256
|
+
if (child)
|
|
257
|
+
children.push(readOutlineEntry(child));
|
|
258
|
+
}
|
|
259
|
+
return { title: entry.title() ?? "", pageId: entry.pageId(), children };
|
|
260
|
+
}
|
|
261
|
+
function requirePage(args) {
|
|
262
|
+
if (args.page === undefined || !Number.isInteger(args.page) || args.page < 0) {
|
|
263
|
+
throw new CliUsageError("extract --kind image|thumb requires --page N (a non-negative integer)");
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
async function readFileWideBlob(reader, blobIndex, label) {
|
|
267
|
+
if (blobIndex < 0)
|
|
268
|
+
throw new CliUsageError(`this file has no ${label} blob`);
|
|
269
|
+
return reader.readBlob(blobIndex);
|
|
270
|
+
}
|
|
271
|
+
function report(io, json, payload) {
|
|
272
|
+
if (json) {
|
|
273
|
+
io.out(JSON.stringify(payload));
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
if (payload.ok)
|
|
277
|
+
io.out(`OK ${payload.target}${payload.mode ? ` (${payload.mode})` : ""}`);
|
|
278
|
+
else
|
|
279
|
+
io.err(`FAIL ${payload.target}: ${payload.reason}`);
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Dispatches a parsed argv to a command handler. Returns the process exit
|
|
283
|
+
* code (0 ok, non-zero on failure / bad args). Never throws for usage
|
|
284
|
+
* errors -- they are reported and mapped to exit code 2.
|
|
285
|
+
*/
|
|
286
|
+
export async function runCli(argv, io) {
|
|
287
|
+
const command = argv[0];
|
|
288
|
+
if (!command || command === "--help" || command === "-h" || command === "help") {
|
|
289
|
+
io.out(USAGE);
|
|
290
|
+
return command ? 0 : 2;
|
|
291
|
+
}
|
|
292
|
+
let args;
|
|
293
|
+
try {
|
|
294
|
+
args = parseArgs(argv.slice(1));
|
|
295
|
+
}
|
|
296
|
+
catch (err) {
|
|
297
|
+
io.err(err instanceof Error ? err.message : String(err));
|
|
298
|
+
io.err(USAGE);
|
|
299
|
+
return 2;
|
|
300
|
+
}
|
|
301
|
+
try {
|
|
302
|
+
switch (command) {
|
|
303
|
+
case "info":
|
|
304
|
+
return await cmdInfo(args, io);
|
|
305
|
+
case "verify":
|
|
306
|
+
return await cmdVerify(args, io);
|
|
307
|
+
case "ls":
|
|
308
|
+
return await cmdLs(args, io);
|
|
309
|
+
case "extract":
|
|
310
|
+
return await cmdExtract(args, io);
|
|
311
|
+
case "meta":
|
|
312
|
+
return await cmdMeta(args, io);
|
|
313
|
+
case "convert":
|
|
314
|
+
io.err("PDF -> .yom conversion is browser-only; use the web convert tool or the iOS app.");
|
|
315
|
+
return 2;
|
|
316
|
+
default:
|
|
317
|
+
io.err(`unknown command: ${command}`);
|
|
318
|
+
io.err(USAGE);
|
|
319
|
+
return 2;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
catch (err) {
|
|
323
|
+
if (err instanceof CliUsageError) {
|
|
324
|
+
io.err(err.message);
|
|
325
|
+
return 2;
|
|
326
|
+
}
|
|
327
|
+
io.err(err instanceof Error ? err.message : String(err));
|
|
328
|
+
return 1;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
const consoleIO = {
|
|
332
|
+
out: (line) => process.stdout.write(`${line}\n`),
|
|
333
|
+
err: (line) => process.stderr.write(`${line}\n`),
|
|
334
|
+
};
|
|
335
|
+
const invokedDirectly = process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href;
|
|
336
|
+
if (invokedDirectly) {
|
|
337
|
+
runCli(process.argv.slice(2), consoleIO)
|
|
338
|
+
.then((code) => process.exit(code))
|
|
339
|
+
.catch((err) => {
|
|
340
|
+
consoleIO.err(err instanceof Error ? err.message : String(err));
|
|
341
|
+
process.exit(1);
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public API for reading, writing, and validating YOM v1 packfiles.
|
|
3
|
+
*
|
|
4
|
+
* This entry point is platform-agnostic (no DOM/pdf.js dependency). For the
|
|
5
|
+
* browser-only PDF-to-YOM conversion pipeline, import from
|
|
6
|
+
* `yom-format/pipeline` instead.
|
|
7
|
+
*/
|
|
8
|
+
export { YOMPackfileReader, YOMReaderError } from "./yom/reader.js";
|
|
9
|
+
export { type ByteSource, MemoryByteSource, HttpRangeByteSource, ByteSourceError, type HttpRangeOptions, } from "./yom/byteSource.js";
|
|
10
|
+
export { YOMError, BlobTooLargeError, CorruptBlobError, MalformedIndexError, RangeNotSupportedError, } from "./yom/errors.js";
|
|
11
|
+
export { verifyMainIndex } from "./yom/flatbufferVerify.js";
|
|
12
|
+
export { MAX_BLOB_UNCOMPRESSED_IMAGE, MAX_BLOB_UNCOMPRESSED_TEXT, MAX_BLOB_UNCOMPRESSED_POSTINGS, MAX_TOTAL_UNCOMPRESSED, MAX_INFLATION_RATIO, maxBlobUncompressed, } from "./yom/constants.js";
|
|
13
|
+
export { writeYOM, YOMWriterError, type WriterInput, type BookInput, type PageInput, type BlobInput, type SearchTermInput, type OutlineInput, type PDFExportInput, } from "./yom/writer.js";
|
|
14
|
+
export { validateYOM, YOMValidationError } from "./yom/validator.js";
|
|
15
|
+
export { YOM_FILE_EXTENSION, YOM_MIME_TYPE, YOM_MAGIC, YOM_HEADER_SIZE, YOM_FORMAT_VERSION, YOM_HASH_LENGTH, YOM_IMAGE_BLOB_ALIGNMENT, YOM_DEFAULT_BLOB_ALIGNMENT, requiredCompression, requiredAlignment, } from "./yom/constants.js";
|
|
16
|
+
export { HEADER_FIELDS_SIZE, type YOMHeader, YOMHeaderParseError, encodeHeaderFields, encodeHeader, encodeFooter, parseHeaderFields, zeroingHashes, headersEqual, } from "./yom/header.js";
|
|
17
|
+
export { buildSearchIndex, decodePostings, type SearchTerm, type SearchIndexResult, type Hit, } from "./yom/searchIndex.js";
|
|
18
|
+
export { normalizeText, buildNormalizedTextBlob, type NormalizedTextBlob, } from "./yom/textNormalizer.js";
|
|
19
|
+
export { sha256, bytesEqual } from "./yom/hash.js";
|
|
20
|
+
export { concatBytes } from "./yom/bytes.js";
|
|
21
|
+
export { BlobKind } from "./yom/generated/yomu/yom/blob-kind.js";
|
|
22
|
+
export { Compression } from "./yom/generated/yomu/yom/compression.js";
|
|
23
|
+
export { ReadingDirection } from "./yom/generated/yomu/yom/reading-direction.js";
|
|
24
|
+
export type { MainIndex } from "./yom/generated/yomu/yom/main-index.js";
|
|
25
|
+
export type { PageEntry } from "./yom/generated/yomu/yom/page-entry.js";
|
|
26
|
+
export type { BlobRef } from "./yom/generated/yomu/yom/blob-ref.js";
|
|
27
|
+
export type { BookMetadata } from "./yom/generated/yomu/yom/book-metadata.js";
|
|
28
|
+
export type { OutlineEntry } from "./yom/generated/yomu/yom/outline-entry.js";
|
|
29
|
+
export type { SearchTermRef } from "./yom/generated/yomu/yom/search-term-ref.js";
|
|
30
|
+
export type { PDFExportMetadata } from "./yom/generated/yomu/yom/pdfexport-metadata.js";
|
|
31
|
+
export type { OCRLayout } from "./yom/generated/yomu/yom/ocrlayout.js";
|
|
32
|
+
export type { OCRPage } from "./yom/generated/yomu/yom/ocrpage.js";
|
|
33
|
+
export type { OCRBlock } from "./yom/generated/yomu/yom/ocrblock.js";
|
|
34
|
+
export type { OCRLine } from "./yom/generated/yomu/yom/ocrline.js";
|
|
35
|
+
export type { OCRToken } from "./yom/generated/yomu/yom/ocrtoken.js";
|
|
36
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEpE,OAAO,EACL,KAAK,UAAU,EACf,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,KAAK,gBAAgB,GACtB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,QAAQ,EACR,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE5D,OAAO,EACL,2BAA2B,EAC3B,0BAA0B,EAC1B,8BAA8B,EAC9B,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,QAAQ,EACR,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,cAAc,GACpB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAErE,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,SAAS,EACT,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,wBAAwB,EACxB,0BAA0B,EAC1B,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,kBAAkB,EAClB,KAAK,SAAS,EACd,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,YAAY,GACb,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,GAAG,GACT,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,KAAK,kBAAkB,GACxB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,OAAO,EAAE,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,+CAA+C,CAAC;AACjF,YAAY,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAC;AACxE,YAAY,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAC;AACxE,YAAY,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;AACpE,YAAY,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAC;AAC9E,YAAY,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAC;AAC9E,YAAY,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;AACjF,YAAY,EAAE,iBAAiB,EAAE,MAAM,gDAAgD,CAAC;AACxF,YAAY,EAAE,SAAS,EAAE,MAAM,uCAAuC,CAAC;AACvE,YAAY,EAAE,OAAO,EAAE,MAAM,qCAAqC,CAAC;AACnE,YAAY,EAAE,QAAQ,EAAE,MAAM,sCAAsC,CAAC;AACrE,YAAY,EAAE,OAAO,EAAE,MAAM,qCAAqC,CAAC;AACnE,YAAY,EAAE,QAAQ,EAAE,MAAM,sCAAsC,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public API for reading, writing, and validating YOM v1 packfiles.
|
|
3
|
+
*
|
|
4
|
+
* This entry point is platform-agnostic (no DOM/pdf.js dependency). For the
|
|
5
|
+
* browser-only PDF-to-YOM conversion pipeline, import from
|
|
6
|
+
* `yom-format/pipeline` instead.
|
|
7
|
+
*/
|
|
8
|
+
export { YOMPackfileReader, YOMReaderError } from "./yom/reader.js";
|
|
9
|
+
export { MemoryByteSource, HttpRangeByteSource, ByteSourceError, } from "./yom/byteSource.js";
|
|
10
|
+
export { YOMError, BlobTooLargeError, CorruptBlobError, MalformedIndexError, RangeNotSupportedError, } from "./yom/errors.js";
|
|
11
|
+
export { verifyMainIndex } from "./yom/flatbufferVerify.js";
|
|
12
|
+
export { MAX_BLOB_UNCOMPRESSED_IMAGE, MAX_BLOB_UNCOMPRESSED_TEXT, MAX_BLOB_UNCOMPRESSED_POSTINGS, MAX_TOTAL_UNCOMPRESSED, MAX_INFLATION_RATIO, maxBlobUncompressed, } from "./yom/constants.js";
|
|
13
|
+
export { writeYOM, YOMWriterError, } from "./yom/writer.js";
|
|
14
|
+
export { validateYOM, YOMValidationError } from "./yom/validator.js";
|
|
15
|
+
export { YOM_FILE_EXTENSION, YOM_MIME_TYPE, YOM_MAGIC, YOM_HEADER_SIZE, YOM_FORMAT_VERSION, YOM_HASH_LENGTH, YOM_IMAGE_BLOB_ALIGNMENT, YOM_DEFAULT_BLOB_ALIGNMENT, requiredCompression, requiredAlignment, } from "./yom/constants.js";
|
|
16
|
+
export { HEADER_FIELDS_SIZE, YOMHeaderParseError, encodeHeaderFields, encodeHeader, encodeFooter, parseHeaderFields, zeroingHashes, headersEqual, } from "./yom/header.js";
|
|
17
|
+
export { buildSearchIndex, decodePostings, } from "./yom/searchIndex.js";
|
|
18
|
+
export { normalizeText, buildNormalizedTextBlob, } from "./yom/textNormalizer.js";
|
|
19
|
+
export { sha256, bytesEqual } from "./yom/hash.js";
|
|
20
|
+
export { concatBytes } from "./yom/bytes.js";
|
|
21
|
+
// FlatBuffers-generated enums and record types used by the API above.
|
|
22
|
+
export { BlobKind } from "./yom/generated/yomu/yom/blob-kind.js";
|
|
23
|
+
export { Compression } from "./yom/generated/yomu/yom/compression.js";
|
|
24
|
+
export { ReadingDirection } from "./yom/generated/yomu/yom/reading-direction.js";
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEpE,OAAO,EAEL,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,GAEhB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,QAAQ,EACR,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE5D,OAAO,EACL,2BAA2B,EAC3B,0BAA0B,EAC1B,8BAA8B,EAC9B,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,QAAQ,EACR,cAAc,GAQf,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAErE,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,SAAS,EACT,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,wBAAwB,EACxB,0BAA0B,EAC1B,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,kBAAkB,EAElB,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,YAAY,GACb,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,gBAAgB,EAChB,cAAc,GAIf,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,aAAa,EACb,uBAAuB,GAExB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,sEAAsE;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,+CAA+C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"avif.d.ts","sourceRoot":"","sources":["../../src/pipeline/avif.ts"],"names":[],"mappings":"AAwBA,wBAAsB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAG1E;AAED,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAG/E"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import encode from "@jsquash/avif/encode";
|
|
2
|
+
/**
|
|
3
|
+
* AVIF is the only page/thumbnail image codec YOM v1 supports (see
|
|
4
|
+
* docs/format-spec.md §5.1-5.2). `@jsquash/avif`'s `quality` is a 0-100
|
|
5
|
+
* cq-level scale, independent of the
|
|
6
|
+
* native encoder's ImageIO `0..1` quality knob (`AVIFCodec.swift`) -- these
|
|
7
|
+
* two encoders are not required to numerically match, only to both emit
|
|
8
|
+
* valid, reasonably-sized AVIF per the format's page/thumbnail split.
|
|
9
|
+
*/
|
|
10
|
+
const PAGE_QUALITY = 60;
|
|
11
|
+
const THUMBNAIL_QUALITY = 40;
|
|
12
|
+
/**
|
|
13
|
+
* libavif's `speed` is 0 (slowest/best compression) to 10 (fastest/worst
|
|
14
|
+
* compression); `@jsquash/avif`'s default is 6 ("balanced"). This app's own
|
|
15
|
+
* product direction is an "extremely fast, focused" reader over archival
|
|
16
|
+
* image quality (see `pivot-fast-reader-remove-ai-ocr`), and these pages are
|
|
17
|
+
* themselves lossy re-renders of the source PDF rather than original scans,
|
|
18
|
+
* so trading a little compression efficiency for much faster encoding is
|
|
19
|
+
* the right default for a browser-only, no-hardware-encoder pipeline.
|
|
20
|
+
*/
|
|
21
|
+
const ENCODE_SPEED = 9;
|
|
22
|
+
export async function encodePageAvif(image) {
|
|
23
|
+
const buffer = await encode(image, { quality: PAGE_QUALITY, speed: ENCODE_SPEED });
|
|
24
|
+
return new Uint8Array(buffer);
|
|
25
|
+
}
|
|
26
|
+
export async function encodeThumbnailAvif(image) {
|
|
27
|
+
const buffer = await encode(image, { quality: THUMBNAIL_QUALITY, speed: ENCODE_SPEED });
|
|
28
|
+
return new Uint8Array(buffer);
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=avif.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"avif.js","sourceRoot":"","sources":["../../src/pipeline/avif.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,sBAAsB,CAAC;AAE1C;;;;;;;GAOG;AACH,MAAM,YAAY,GAAG,EAAE,CAAC;AACxB,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAE7B;;;;;;;;GAQG;AACH,MAAM,YAAY,GAAG,CAAC,CAAC;AAEvB,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAgB;IACnD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;IACnF,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,KAAgB;IACxD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;IACxF,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC"}
|