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.
Files changed (199) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +86 -0
  3. package/dist/cli.d.ts +30 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +344 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/index.d.ts +36 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +25 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/pipeline/avif.d.ts +3 -0
  12. package/dist/pipeline/avif.d.ts.map +1 -0
  13. package/dist/pipeline/avif.js +30 -0
  14. package/dist/pipeline/avif.js.map +1 -0
  15. package/dist/pipeline/convert.d.ts +28 -0
  16. package/dist/pipeline/convert.d.ts.map +1 -0
  17. package/dist/pipeline/convert.js +111 -0
  18. package/dist/pipeline/convert.js.map +1 -0
  19. package/dist/pipeline/index.d.ts +17 -0
  20. package/dist/pipeline/index.d.ts.map +1 -0
  21. package/dist/pipeline/index.js +17 -0
  22. package/dist/pipeline/index.js.map +1 -0
  23. package/dist/pipeline/ocrLayoutBuilder.d.ts +10 -0
  24. package/dist/pipeline/ocrLayoutBuilder.d.ts.map +1 -0
  25. package/dist/pipeline/ocrLayoutBuilder.js +62 -0
  26. package/dist/pipeline/ocrLayoutBuilder.js.map +1 -0
  27. package/dist/pipeline/pdfDocument.d.ts +12 -0
  28. package/dist/pipeline/pdfDocument.d.ts.map +1 -0
  29. package/dist/pipeline/pdfDocument.js +76 -0
  30. package/dist/pipeline/pdfDocument.js.map +1 -0
  31. package/dist/pipeline/renderPage.d.ts +10 -0
  32. package/dist/pipeline/renderPage.d.ts.map +1 -0
  33. package/dist/pipeline/renderPage.js +36 -0
  34. package/dist/pipeline/renderPage.js.map +1 -0
  35. package/dist/pipeline/textExtract.d.ts +29 -0
  36. package/dist/pipeline/textExtract.d.ts.map +1 -0
  37. package/dist/pipeline/textExtract.js +48 -0
  38. package/dist/pipeline/textExtract.js.map +1 -0
  39. package/dist/yom/blobLimits.d.ts +15 -0
  40. package/dist/yom/blobLimits.d.ts.map +1 -0
  41. package/dist/yom/blobLimits.js +25 -0
  42. package/dist/yom/blobLimits.js.map +1 -0
  43. package/dist/yom/byteSource.d.ts +56 -0
  44. package/dist/yom/byteSource.d.ts.map +1 -0
  45. package/dist/yom/byteSource.js +111 -0
  46. package/dist/yom/byteSource.js.map +1 -0
  47. package/dist/yom/bytes.d.ts +2 -0
  48. package/dist/yom/bytes.d.ts.map +1 -0
  49. package/dist/yom/bytes.js +13 -0
  50. package/dist/yom/bytes.js.map +1 -0
  51. package/dist/yom/constants.d.ts +34 -0
  52. package/dist/yom/constants.d.ts.map +1 -0
  53. package/dist/yom/constants.js +82 -0
  54. package/dist/yom/constants.js.map +1 -0
  55. package/dist/yom/errors.d.ts +44 -0
  56. package/dist/yom/errors.d.ts.map +1 -0
  57. package/dist/yom/errors.js +44 -0
  58. package/dist/yom/errors.js.map +1 -0
  59. package/dist/yom/flatbufferVerify.d.ts +21 -0
  60. package/dist/yom/flatbufferVerify.d.ts.map +1 -0
  61. package/dist/yom/flatbufferVerify.js +255 -0
  62. package/dist/yom/flatbufferVerify.js.map +1 -0
  63. package/dist/yom/generated/yomu/yom/blob-kind.d.ts +9 -0
  64. package/dist/yom/generated/yomu/yom/blob-kind.d.ts.map +1 -0
  65. package/dist/yom/generated/yomu/yom/blob-kind.js +12 -0
  66. package/dist/yom/generated/yomu/yom/blob-kind.js.map +1 -0
  67. package/dist/yom/generated/yomu/yom/blob-ref.d.ts +45 -0
  68. package/dist/yom/generated/yomu/yom/blob-ref.d.ts.map +1 -0
  69. package/dist/yom/generated/yomu/yom/blob-ref.js +141 -0
  70. package/dist/yom/generated/yomu/yom/blob-ref.js.map +1 -0
  71. package/dist/yom/generated/yomu/yom/book-metadata.d.ts +32 -0
  72. package/dist/yom/generated/yomu/yom/book-metadata.d.ts.map +1 -0
  73. package/dist/yom/generated/yomu/yom/book-metadata.js +89 -0
  74. package/dist/yom/generated/yomu/yom/book-metadata.js.map +1 -0
  75. package/dist/yom/generated/yomu/yom/compression.d.ts +5 -0
  76. package/dist/yom/generated/yomu/yom/compression.d.ts.map +1 -0
  77. package/dist/yom/generated/yomu/yom/compression.js +8 -0
  78. package/dist/yom/generated/yomu/yom/compression.js.map +1 -0
  79. package/dist/yom/generated/yomu/yom/main-index.d.ts +63 -0
  80. package/dist/yom/generated/yomu/yom/main-index.d.ts.map +1 -0
  81. package/dist/yom/generated/yomu/yom/main-index.js +208 -0
  82. package/dist/yom/generated/yomu/yom/main-index.js.map +1 -0
  83. package/dist/yom/generated/yomu/yom/ocrblock.d.ts +32 -0
  84. package/dist/yom/generated/yomu/yom/ocrblock.d.ts.map +1 -0
  85. package/dist/yom/generated/yomu/yom/ocrblock.js +84 -0
  86. package/dist/yom/generated/yomu/yom/ocrblock.js.map +1 -0
  87. package/dist/yom/generated/yomu/yom/ocrlayout.d.ts +27 -0
  88. package/dist/yom/generated/yomu/yom/ocrlayout.d.ts.map +1 -0
  89. package/dist/yom/generated/yomu/yom/ocrlayout.js +76 -0
  90. package/dist/yom/generated/yomu/yom/ocrlayout.js.map +1 -0
  91. package/dist/yom/generated/yomu/yom/ocrline.d.ts +35 -0
  92. package/dist/yom/generated/yomu/yom/ocrline.d.ts.map +1 -0
  93. package/dist/yom/generated/yomu/yom/ocrline.js +95 -0
  94. package/dist/yom/generated/yomu/yom/ocrline.js.map +1 -0
  95. package/dist/yom/generated/yomu/yom/ocrpage.d.ts +46 -0
  96. package/dist/yom/generated/yomu/yom/ocrpage.d.ts.map +1 -0
  97. package/dist/yom/generated/yomu/yom/ocrpage.js +147 -0
  98. package/dist/yom/generated/yomu/yom/ocrpage.js.map +1 -0
  99. package/dist/yom/generated/yomu/yom/ocrtoken.d.ts +44 -0
  100. package/dist/yom/generated/yomu/yom/ocrtoken.d.ts.map +1 -0
  101. package/dist/yom/generated/yomu/yom/ocrtoken.js +128 -0
  102. package/dist/yom/generated/yomu/yom/ocrtoken.js.map +1 -0
  103. package/dist/yom/generated/yomu/yom/outline-entry.d.ts +31 -0
  104. package/dist/yom/generated/yomu/yom/outline-entry.d.ts.map +1 -0
  105. package/dist/yom/generated/yomu/yom/outline-entry.js +92 -0
  106. package/dist/yom/generated/yomu/yom/outline-entry.js.map +1 -0
  107. package/dist/yom/generated/yomu/yom/page-entry.d.ts +95 -0
  108. package/dist/yom/generated/yomu/yom/page-entry.d.ts.map +1 -0
  109. package/dist/yom/generated/yomu/yom/page-entry.js +288 -0
  110. package/dist/yom/generated/yomu/yom/page-entry.js.map +1 -0
  111. package/dist/yom/generated/yomu/yom/pdfexport-metadata.d.ts +32 -0
  112. package/dist/yom/generated/yomu/yom/pdfexport-metadata.d.ts.map +1 -0
  113. package/dist/yom/generated/yomu/yom/pdfexport-metadata.js +96 -0
  114. package/dist/yom/generated/yomu/yom/pdfexport-metadata.js.map +1 -0
  115. package/dist/yom/generated/yomu/yom/reading-direction.d.ts +5 -0
  116. package/dist/yom/generated/yomu/yom/reading-direction.d.ts.map +1 -0
  117. package/dist/yom/generated/yomu/yom/reading-direction.js +8 -0
  118. package/dist/yom/generated/yomu/yom/reading-direction.js.map +1 -0
  119. package/dist/yom/generated/yomu/yom/search-term-ref.d.ts +34 -0
  120. package/dist/yom/generated/yomu/yom/search-term-ref.d.ts.map +1 -0
  121. package/dist/yom/generated/yomu/yom/search-term-ref.js +99 -0
  122. package/dist/yom/generated/yomu/yom/search-term-ref.js.map +1 -0
  123. package/dist/yom/generated/yomu/yom.d.ts +6 -0
  124. package/dist/yom/generated/yomu/yom.d.ts.map +1 -0
  125. package/dist/yom/generated/yomu/yom.js +8 -0
  126. package/dist/yom/generated/yomu/yom.js.map +1 -0
  127. package/dist/yom/hash.d.ts +4 -0
  128. package/dist/yom/hash.d.ts.map +1 -0
  129. package/dist/yom/hash.js +21 -0
  130. package/dist/yom/hash.js.map +1 -0
  131. package/dist/yom/header.d.ts +44 -0
  132. package/dist/yom/header.d.ts.map +1 -0
  133. package/dist/yom/header.js +115 -0
  134. package/dist/yom/header.js.map +1 -0
  135. package/dist/yom/reader.d.ts +57 -0
  136. package/dist/yom/reader.d.ts.map +1 -0
  137. package/dist/yom/reader.js +141 -0
  138. package/dist/yom/reader.js.map +1 -0
  139. package/dist/yom/searchIndex.d.ts +41 -0
  140. package/dist/yom/searchIndex.d.ts.map +1 -0
  141. package/dist/yom/searchIndex.js +133 -0
  142. package/dist/yom/searchIndex.js.map +1 -0
  143. package/dist/yom/textNormalizer.d.ts +19 -0
  144. package/dist/yom/textNormalizer.d.ts.map +1 -0
  145. package/dist/yom/textNormalizer.js +77 -0
  146. package/dist/yom/textNormalizer.js.map +1 -0
  147. package/dist/yom/validator.d.ts +14 -0
  148. package/dist/yom/validator.d.ts.map +1 -0
  149. package/dist/yom/validator.js +197 -0
  150. package/dist/yom/validator.js.map +1 -0
  151. package/dist/yom/writer.d.ts +76 -0
  152. package/dist/yom/writer.d.ts.map +1 -0
  153. package/dist/yom/writer.js +154 -0
  154. package/dist/yom/writer.js.map +1 -0
  155. package/dist/yom/zstd.d.ts +14 -0
  156. package/dist/yom/zstd.d.ts.map +1 -0
  157. package/dist/yom/zstd.js +43 -0
  158. package/dist/yom/zstd.js.map +1 -0
  159. package/package.json +65 -0
  160. package/src/cli.ts +372 -0
  161. package/src/index.ts +109 -0
  162. package/src/pipeline/avif.ts +33 -0
  163. package/src/pipeline/convert.ts +148 -0
  164. package/src/pipeline/index.ts +28 -0
  165. package/src/pipeline/ocrLayoutBuilder.ts +73 -0
  166. package/src/pipeline/pdfDocument.ts +86 -0
  167. package/src/pipeline/renderPage.ts +48 -0
  168. package/src/pipeline/textExtract.ts +64 -0
  169. package/src/worker/convert.worker.ts +54 -0
  170. package/src/yom/blobLimits.ts +30 -0
  171. package/src/yom/byteSource.ts +144 -0
  172. package/src/yom/bytes.ts +11 -0
  173. package/src/yom/constants.ts +89 -0
  174. package/src/yom/errors.ts +43 -0
  175. package/src/yom/flatbufferVerify.ts +298 -0
  176. package/src/yom/generated/yomu/yom/blob-kind.ts +12 -0
  177. package/src/yom/generated/yomu/yom/blob-ref.ts +184 -0
  178. package/src/yom/generated/yomu/yom/book-metadata.ts +121 -0
  179. package/src/yom/generated/yomu/yom/compression.ts +8 -0
  180. package/src/yom/generated/yomu/yom/main-index.ts +257 -0
  181. package/src/yom/generated/yomu/yom/ocrblock.ts +117 -0
  182. package/src/yom/generated/yomu/yom/ocrlayout.ts +102 -0
  183. package/src/yom/generated/yomu/yom/ocrline.ts +131 -0
  184. package/src/yom/generated/yomu/yom/ocrpage.ts +191 -0
  185. package/src/yom/generated/yomu/yom/ocrtoken.ts +173 -0
  186. package/src/yom/generated/yomu/yom/outline-entry.ts +124 -0
  187. package/src/yom/generated/yomu/yom/page-entry.ts +388 -0
  188. package/src/yom/generated/yomu/yom/pdfexport-metadata.ts +128 -0
  189. package/src/yom/generated/yomu/yom/reading-direction.ts +8 -0
  190. package/src/yom/generated/yomu/yom/search-term-ref.ts +134 -0
  191. package/src/yom/generated/yomu/yom.ts +9 -0
  192. package/src/yom/hash.ts +20 -0
  193. package/src/yom/header.ts +132 -0
  194. package/src/yom/reader.ts +163 -0
  195. package/src/yom/searchIndex.ts +178 -0
  196. package/src/yom/textNormalizer.ts +92 -0
  197. package/src/yom/validator.ts +245 -0
  198. package/src/yom/writer.ts +337 -0
  199. package/src/yom/zstd.ts +47 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"searchIndex.d.ts","sourceRoot":"","sources":["../../src/yom/searchIndex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,UAAU,CAAC;IAC3B,YAAY,EAAE,UAAU,CAAC;IACzB,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,GAAG;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,gBAAgB,CAAC,mBAAmB,EAAE,MAAM,EAAE,GAAG,iBAAiB,CAoDjF;AAED,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,GAAG,EAAE,CA0BtD"}
@@ -0,0 +1,133 @@
1
+ export function buildSearchIndex(normalizedPageTexts) {
2
+ const postingsByTerm = new Map();
3
+ normalizedPageTexts.forEach((text, pageIndex) => {
4
+ const characters = Array.from(text);
5
+ if (characters.length < 2)
6
+ return;
7
+ for (let index = 0; index <= characters.length - 2; index++) {
8
+ const gram = characters[index] + characters[index + 1];
9
+ let hits = postingsByTerm.get(gram);
10
+ if (!hits) {
11
+ hits = [];
12
+ postingsByTerm.set(gram, hits);
13
+ }
14
+ hits.push({ page: pageIndex, position: index });
15
+ }
16
+ });
17
+ const encoder = new TextEncoder();
18
+ const dictionaryChunks = [];
19
+ const postingsChunks = [];
20
+ const searchTerms = [];
21
+ let dictionaryCursor = 0;
22
+ let postingsCursor = 0;
23
+ const terms = Array.from(postingsByTerm.keys()).sort();
24
+ for (const term of terms) {
25
+ const hits = postingsByTerm.get(term).sort((a, b) => (a.page === b.page ? a.position - b.position : a.page - b.page));
26
+ const termBytes = encoder.encode(term);
27
+ dictionaryChunks.push(termBytes);
28
+ const dictionaryOffset = dictionaryCursor;
29
+ dictionaryCursor += termBytes.length;
30
+ const postingsBytes = encodePostings(hits);
31
+ postingsChunks.push(postingsBytes);
32
+ const postingsOffset = postingsCursor;
33
+ postingsCursor += postingsBytes.length;
34
+ searchTerms.push({
35
+ term,
36
+ dictionaryOffset,
37
+ dictionaryLength: termBytes.length,
38
+ postingsOffset,
39
+ postingsLength: postingsBytes.length,
40
+ });
41
+ }
42
+ return {
43
+ dictionaryBlob: concatBytes(dictionaryChunks, dictionaryCursor),
44
+ postingsBlob: concatBytes(postingsChunks, postingsCursor),
45
+ searchTerms,
46
+ };
47
+ }
48
+ /** Decodes one term's postings byte range back into `(page, position)` hits. */
49
+ export function decodePostings(blob) {
50
+ const hits = [];
51
+ let offset = 0;
52
+ let previousPage = 0;
53
+ let previousPosition = 0;
54
+ let isFirst = true;
55
+ while (offset < blob.length) {
56
+ const first = readVarint(blob, offset);
57
+ offset = first.nextOffset;
58
+ const second = readVarint(blob, offset);
59
+ offset = second.nextOffset;
60
+ if (isFirst) {
61
+ previousPage = first.value;
62
+ previousPosition = second.value;
63
+ isFirst = false;
64
+ }
65
+ else if (first.value === 0) {
66
+ previousPosition += second.value;
67
+ }
68
+ else {
69
+ previousPage += first.value;
70
+ previousPosition = second.value;
71
+ }
72
+ hits.push({ page: previousPage, position: previousPosition });
73
+ }
74
+ return hits;
75
+ }
76
+ function encodePostings(hits) {
77
+ const bytes = [];
78
+ let previousPage = 0;
79
+ let previousPosition = 0;
80
+ hits.forEach((hit, index) => {
81
+ if (index === 0) {
82
+ writeVarint(hit.page, bytes);
83
+ writeVarint(hit.position, bytes);
84
+ }
85
+ else if (hit.page === previousPage) {
86
+ writeVarint(0, bytes);
87
+ writeVarint(hit.position - previousPosition, bytes);
88
+ }
89
+ else {
90
+ writeVarint(hit.page - previousPage, bytes);
91
+ writeVarint(hit.position, bytes);
92
+ }
93
+ previousPage = hit.page;
94
+ previousPosition = hit.position;
95
+ });
96
+ return Uint8Array.from(bytes);
97
+ }
98
+ function writeVarint(value, out) {
99
+ let remaining = value >>> 0;
100
+ while (true) {
101
+ let byte = remaining & 0x7f;
102
+ remaining >>>= 7;
103
+ if (remaining !== 0)
104
+ byte |= 0x80;
105
+ out.push(byte);
106
+ if (remaining === 0)
107
+ break;
108
+ }
109
+ }
110
+ function readVarint(bytes, offset) {
111
+ let result = 0;
112
+ let shift = 0;
113
+ let cursor = offset;
114
+ while (true) {
115
+ const byte = bytes[cursor];
116
+ cursor += 1;
117
+ result |= (byte & 0x7f) << shift;
118
+ if ((byte & 0x80) === 0)
119
+ break;
120
+ shift += 7;
121
+ }
122
+ return { value: result >>> 0, nextOffset: cursor };
123
+ }
124
+ function concatBytes(chunks, totalLength) {
125
+ const out = new Uint8Array(totalLength);
126
+ let offset = 0;
127
+ for (const chunk of chunks) {
128
+ out.set(chunk, offset);
129
+ offset += chunk.length;
130
+ }
131
+ return out;
132
+ }
133
+ //# sourceMappingURL=searchIndex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"searchIndex.js","sourceRoot":"","sources":["../../src/yom/searchIndex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export interface NormalizedTextBlob {
2
+ data: Uint8Array;
3
+ normalizedPageTexts: string[];
4
+ /** Each page's byte range within `data` (end-exclusive). */
5
+ pageRanges: Array<{
6
+ start: number;
7
+ end: number;
8
+ }>;
9
+ }
10
+ /** NFKC + whitespace-removal for a single page's text. */
11
+ export declare function normalizeText(text: string): string;
12
+ /**
13
+ * Builds the single blob that stores every page's normalized text back to
14
+ * back, each page separated by `"\n"` (a normalized page's text never
15
+ * contains raw whitespace itself since it was just stripped, so `"\n"` is an
16
+ * unambiguous separator).
17
+ */
18
+ export declare function buildNormalizedTextBlob(pageTexts: string[]): NormalizedTextBlob;
19
+ //# sourceMappingURL=textNormalizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textNormalizer.d.ts","sourceRoot":"","sources":["../../src/yom/textNormalizer.ts"],"names":[],"mappings":"AAgDA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,UAAU,CAAC;IACjB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,4DAA4D;IAC5D,UAAU,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnD;AAED,0DAA0D;AAC1D,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,kBAAkB,CAyB/E"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Whitespace-insensitive Japanese text normalization for YOM search. Ports
3
+ * the Swift implementation in `swift/Sources/YOMFormat/YOMTextNormalizer.swift`:
4
+ * NFKC-normalized text with all
5
+ * whitespace (including the full-width space U+3000) removed entirely, not
6
+ * just collapsed, since Japanese text carries no meaningful inter-word
7
+ * spacing and OCR/PDF line wraps insert whitespace at essentially arbitrary
8
+ * points that must not affect matching.
9
+ *
10
+ * Matches Swift's `CharacterSet.whitespacesAndNewlines` (Unicode `Zs` +
11
+ * newlines) rather than JS's broader `\s` (which also strips U+FEFF BOM).
12
+ * Every code point below is written as an explicit `\uXXXX` escape so the
13
+ * exact whitespace set is auditable rather than relying on invisible
14
+ * characters in source.
15
+ */
16
+ const WHITESPACE_CODEPOINTS = [
17
+ 0x0009, // tab
18
+ 0x000a, // LF
19
+ 0x000b, // vertical tab
20
+ 0x000c, // form feed
21
+ 0x000d, // CR
22
+ 0x0020, // space
23
+ 0x0085, // NEL
24
+ 0x00a0, // no-break space (Zs)
25
+ 0x1680, // ogham space mark (Zs)
26
+ 0x2000,
27
+ 0x2001,
28
+ 0x2002,
29
+ 0x2003,
30
+ 0x2004,
31
+ 0x2005,
32
+ 0x2006,
33
+ 0x2007,
34
+ 0x2008,
35
+ 0x2009,
36
+ 0x200a, // en/em spaces etc. (Zs)
37
+ 0x2028, // line separator
38
+ 0x2029, // paragraph separator
39
+ 0x202f, // narrow no-break space (Zs)
40
+ 0x205f, // medium mathematical space (Zs)
41
+ 0x3000, // ideographic (full-width) space (Zs)
42
+ ];
43
+ const WHITESPACE_PATTERN = new RegExp(`[${WHITESPACE_CODEPOINTS.map((cp) => `\\u{${cp.toString(16)}}`).join("")}]`, "gu");
44
+ /** NFKC + whitespace-removal for a single page's text. */
45
+ export function normalizeText(text) {
46
+ return text.normalize("NFKC").replace(WHITESPACE_PATTERN, "");
47
+ }
48
+ /**
49
+ * Builds the single blob that stores every page's normalized text back to
50
+ * back, each page separated by `"\n"` (a normalized page's text never
51
+ * contains raw whitespace itself since it was just stripped, so `"\n"` is an
52
+ * unambiguous separator).
53
+ */
54
+ export function buildNormalizedTextBlob(pageTexts) {
55
+ const normalizedPages = pageTexts.map(normalizeText);
56
+ const encoder = new TextEncoder();
57
+ const chunks = [];
58
+ const ranges = [];
59
+ let cursor = 0;
60
+ for (const page of normalizedPages) {
61
+ const bytes = encoder.encode(page);
62
+ chunks.push(bytes);
63
+ ranges.push({ start: cursor, end: cursor + bytes.length });
64
+ cursor += bytes.length;
65
+ const newline = encoder.encode("\n");
66
+ chunks.push(newline);
67
+ cursor += newline.length;
68
+ }
69
+ const data = new Uint8Array(cursor);
70
+ let offset = 0;
71
+ for (const chunk of chunks) {
72
+ data.set(chunk, offset);
73
+ offset += chunk.length;
74
+ }
75
+ return { data, normalizedPageTexts: normalizedPages, pageRanges: ranges };
76
+ }
77
+ //# sourceMappingURL=textNormalizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textNormalizer.js","sourceRoot":"","sources":["../../src/yom/textNormalizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,qBAAqB,GAAG;IAC5B,MAAM,EAAE,MAAM;IACd,MAAM,EAAE,KAAK;IACb,MAAM,EAAE,eAAe;IACvB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,KAAK;IACb,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,MAAM;IACd,MAAM,EAAE,sBAAsB;IAC9B,MAAM,EAAE,wBAAwB;IAChC,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM,EAAE,yBAAyB;IACjC,MAAM,EAAE,iBAAiB;IACzB,MAAM,EAAE,sBAAsB;IAC9B,MAAM,EAAE,6BAA6B;IACrC,MAAM,EAAE,iCAAiC;IACzC,MAAM,EAAE,sCAAsC;CAC/C,CAAC;AAEF,MAAM,kBAAkB,GAAG,IAAI,MAAM,CACnC,IAAI,qBAAqB,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,EAC5E,IAAI,CACL,CAAC;AASF,0DAA0D;AAC1D,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;AAChE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,SAAmB;IACzD,MAAM,eAAe,GAAG,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,MAAM,MAAM,GAA0C,EAAE,CAAC;IACzD,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC;QACvB,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrB,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAC3B,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC;IACzB,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,mBAAmB,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;AAC5E,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Strict, standalone validation of a YOM v1 packfile, independent of
3
+ * `YOMPackfileReader`. Ports the Swift implementation in
4
+ * `swift/Sources/YOMFormat/YOMValidator.swift`: magic/
5
+ * version, file-size consistency, index/file/blob hashes, blob offset bounds
6
+ * and alignment, the fixed compression-by-kind policy, and the "exactly one
7
+ * page image blob + one thumbnail blob per page" rule.
8
+ *
9
+ * Throws on the first failure found rather than collecting every violation.
10
+ */
11
+ export declare class YOMValidationError extends Error {
12
+ }
13
+ export declare function validateYOM(data: Uint8Array): Promise<void>;
14
+ //# sourceMappingURL=validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/yom/validator.ts"],"names":[],"mappings":"AA4BA;;;;;;;;;GASG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;CAAG;AAEhD,wBAAsB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBjE"}
@@ -0,0 +1,197 @@
1
+ import { BlobKind } from "./generated/yomu/yom/blob-kind.js";
2
+ import { Compression } from "./generated/yomu/yom/compression.js";
3
+ import { MAX_TOTAL_UNCOMPRESSED, YOM_HEADER_SIZE, YOM_IMAGE_BLOB_ALIGNMENT, YOM_MAGIC, YOM_FORMAT_VERSION, requiredCompression, } from "./constants.js";
4
+ import { getVerifiedRootAsMainIndex } from "./flatbufferVerify.js";
5
+ import { enforceBlobSizePolicy } from "./blobLimits.js";
6
+ import { BlobTooLargeError } from "./errors.js";
7
+ import { HEADER_FIELDS_SIZE, encodeFooter, encodeHeader, headersEqual, parseHeaderFields, zeroingHashes, } from "./header.js";
8
+ import { bytesEqual, sha256 } from "./hash.js";
9
+ import { zstdDecompress } from "./zstd.js";
10
+ import { concatBytes } from "./bytes.js";
11
+ /**
12
+ * Strict, standalone validation of a YOM v1 packfile, independent of
13
+ * `YOMPackfileReader`. Ports the Swift implementation in
14
+ * `swift/Sources/YOMFormat/YOMValidator.swift`: magic/
15
+ * version, file-size consistency, index/file/blob hashes, blob offset bounds
16
+ * and alignment, the fixed compression-by-kind policy, and the "exactly one
17
+ * page image blob + one thumbnail blob per page" rule.
18
+ *
19
+ * Throws on the first failure found rather than collecting every violation.
20
+ */
21
+ export class YOMValidationError extends Error {
22
+ }
23
+ export async function validateYOM(data) {
24
+ const header = validateHeaderAndFooter(data);
25
+ const indexEnd = header.indexOffset + header.indexUncompressedLength;
26
+ const footerStart = data.length - HEADER_FIELDS_SIZE;
27
+ const indexBytes = data.subarray(Number(header.indexOffset), Number(indexEnd));
28
+ await validateIndexAndFileHashes(data, header, indexBytes, footerStart);
29
+ // Full bounded structural verification of the index before traversal (Gap 3).
30
+ const mainIndex = getVerifiedRootAsMainIndex(indexBytes, true);
31
+ const blobCounts = await validateBlobs(mainIndex, data, indexEnd, footerStart);
32
+ const pageCount = mainIndex.pagesLength();
33
+ if (blobCounts.image !== pageCount) {
34
+ throw new YOMValidationError(`expected ${pageCount} PageImage blobs, found ${blobCounts.image}`);
35
+ }
36
+ if (blobCounts.thumbnail !== pageCount) {
37
+ throw new YOMValidationError(`expected ${pageCount} ThumbnailImage blobs, found ${blobCounts.thumbnail}`);
38
+ }
39
+ validatePageBlobReferences(mainIndex);
40
+ }
41
+ /** Parses and cross-checks the fixed header against its footer mirror. */
42
+ function validateHeaderAndFooter(data) {
43
+ if (data.length < YOM_HEADER_SIZE + HEADER_FIELDS_SIZE) {
44
+ throw new YOMValidationError("file too small");
45
+ }
46
+ const header = parseHeaderFields(data.subarray(0, YOM_HEADER_SIZE));
47
+ if (!bytesEqual(header.magic, YOM_MAGIC))
48
+ throw new YOMValidationError("bad magic");
49
+ if (header.formatVersion !== YOM_FORMAT_VERSION) {
50
+ throw new YOMValidationError(`unsupported format version ${header.formatVersion}`);
51
+ }
52
+ const indexEnd = header.indexOffset + header.indexUncompressedLength;
53
+ if (header.indexOffset !== BigInt(YOM_HEADER_SIZE) || indexEnd > BigInt(data.length)) {
54
+ throw new YOMValidationError("index out of bounds");
55
+ }
56
+ const footerStart = data.length - HEADER_FIELDS_SIZE;
57
+ if (BigInt(footerStart) < indexEnd)
58
+ throw new YOMValidationError("index out of bounds");
59
+ const footer = parseHeaderFields(data.subarray(footerStart));
60
+ if (!headersEqual(footer, header))
61
+ throw new YOMValidationError("footer does not match header");
62
+ return header;
63
+ }
64
+ /**
65
+ * Recomputes the index hash and the whole-file hash (with hash fields
66
+ * zeroed, matching the writer's convention) and compares them against the
67
+ * values stored in the header.
68
+ */
69
+ async function validateIndexAndFileHashes(data, header, indexBytes, footerStart) {
70
+ const actualIndexHash = await sha256(indexBytes);
71
+ if (!bytesEqual(actualIndexHash, header.indexHash))
72
+ throw new YOMValidationError("index hash mismatch");
73
+ const hashingHeader = zeroingHashes(header);
74
+ const recomputeInput = concatBytes([
75
+ encodeHeader(hashingHeader),
76
+ data.subarray(YOM_HEADER_SIZE, footerStart),
77
+ encodeFooter(hashingHeader),
78
+ ]);
79
+ const actualFileHash = await sha256(recomputeInput);
80
+ if (!bytesEqual(actualFileHash, header.fileHash))
81
+ throw new YOMValidationError("file hash mismatch");
82
+ }
83
+ /**
84
+ * Validates every blob's compression policy, alignment, bounds, and hash.
85
+ * Returns how many PageImage/ThumbnailImage blobs were found, so the caller
86
+ * can enforce "exactly one of each per page, no extras".
87
+ */
88
+ async function validateBlobs(mainIndex, data, indexEnd, footerStart) {
89
+ let imageBlobCount = 0;
90
+ let thumbnailBlobCount = 0;
91
+ let totalUncompressed = 0;
92
+ for (let blobIndex = 0; blobIndex < mainIndex.blobsLength(); blobIndex++) {
93
+ const blob = mainIndex.blobs(blobIndex);
94
+ if (!blob)
95
+ throw new YOMValidationError(`blob ${blobIndex} missing`);
96
+ validateBlobCompressionAndAlignment(blob, blobIndex);
97
+ const blobEnd = blob.offset() + blob.compressedLength();
98
+ if (blob.offset() < indexEnd || blobEnd > BigInt(footerStart)) {
99
+ throw new YOMValidationError(`blob ${blobIndex} out of bounds`);
100
+ }
101
+ // Reader-side size caps before touching bytes (Gap 2).
102
+ const compressedLength = Number(blob.compressedLength());
103
+ const uncompressedLength = Number(blob.uncompressedLength());
104
+ try {
105
+ enforceBlobSizePolicy(blob.kind(), compressedLength, uncompressedLength);
106
+ }
107
+ catch (err) {
108
+ if (err instanceof BlobTooLargeError) {
109
+ throw new YOMValidationError(`blob ${blobIndex} ${err.message}`);
110
+ }
111
+ throw err;
112
+ }
113
+ totalUncompressed += uncompressedLength;
114
+ if (totalUncompressed > MAX_TOTAL_UNCOMPRESSED) {
115
+ throw new YOMValidationError(`total uncompressed size exceeds cap ${MAX_TOTAL_UNCOMPRESSED}`);
116
+ }
117
+ const rawBytes = data.subarray(Number(blob.offset()), Number(blobEnd));
118
+ await validateBlobHash(blob, blobIndex, uncompressedLength, rawBytes);
119
+ if (blob.kind() === BlobKind.PageImage)
120
+ imageBlobCount += 1;
121
+ if (blob.kind() === BlobKind.ThumbnailImage)
122
+ thumbnailBlobCount += 1;
123
+ }
124
+ return { image: imageBlobCount, thumbnail: thumbnailBlobCount };
125
+ }
126
+ function validateBlobCompressionAndAlignment(blob, blobIndex) {
127
+ const required = requiredCompression(blob.kind());
128
+ if (blob.compression() !== required) {
129
+ throw new YOMValidationError(`blob ${blobIndex} compression policy violation: kind ${blob.kind()} declared ${blob.compression()} required ${required}`);
130
+ }
131
+ const alignment = BigInt(Math.max(blob.alignment(), 1));
132
+ if (blob.offset() % alignment !== 0n) {
133
+ throw new YOMValidationError(`blob ${blobIndex} alignment violation`);
134
+ }
135
+ if (blob.kind() === BlobKind.PageImage || blob.kind() === BlobKind.ThumbnailImage) {
136
+ if (blob.alignment() < YOM_IMAGE_BLOB_ALIGNMENT) {
137
+ throw new YOMValidationError(`blob ${blobIndex} alignment violation`);
138
+ }
139
+ }
140
+ }
141
+ async function validateBlobHash(blob, blobIndex, uncompressedLength, rawBytes) {
142
+ let original;
143
+ if (blob.compression() === Compression.None) {
144
+ original = rawBytes;
145
+ }
146
+ else {
147
+ try {
148
+ original = await zstdDecompress(rawBytes, uncompressedLength);
149
+ }
150
+ catch {
151
+ throw new YOMValidationError(`blob ${blobIndex} hash mismatch (decompression failed)`);
152
+ }
153
+ }
154
+ const actualHash = await sha256(original);
155
+ const expectedHash = blob.hashArray();
156
+ if (!expectedHash || !bytesEqual(actualHash, expectedHash)) {
157
+ throw new YOMValidationError(`blob ${blobIndex} hash mismatch`);
158
+ }
159
+ }
160
+ /**
161
+ * Confirms every page references exactly one PageImage and one
162
+ * ThumbnailImage blob, each of the right kind, with no blob shared between
163
+ * two pages.
164
+ */
165
+ function validatePageBlobReferences(mainIndex) {
166
+ const blobCount = mainIndex.blobsLength();
167
+ const usedImageBlobIndices = new Set();
168
+ const usedThumbnailBlobIndices = new Set();
169
+ for (let pageIndex = 0; pageIndex < mainIndex.pagesLength(); pageIndex++) {
170
+ const page = mainIndex.pages(pageIndex);
171
+ if (!page)
172
+ throw new YOMValidationError(`page ${pageIndex} missing`);
173
+ const imageBlobIndex = page.pageImageBlobIndex();
174
+ if (imageBlobIndex < 0 || imageBlobIndex >= blobCount) {
175
+ throw new YOMValidationError(`page ${pageIndex} missing image blob`);
176
+ }
177
+ if (mainIndex.blobs(imageBlobIndex)?.kind() !== BlobKind.PageImage) {
178
+ throw new YOMValidationError(`page ${pageIndex} image blob has wrong kind`);
179
+ }
180
+ if (usedImageBlobIndices.has(imageBlobIndex)) {
181
+ throw new YOMValidationError(`blob ${imageBlobIndex} referenced as image by more than one page`);
182
+ }
183
+ usedImageBlobIndices.add(imageBlobIndex);
184
+ const thumbnailBlobIndex = page.thumbnailBlobIndex();
185
+ if (thumbnailBlobIndex < 0 || thumbnailBlobIndex >= blobCount) {
186
+ throw new YOMValidationError(`page ${pageIndex} missing thumbnail blob`);
187
+ }
188
+ if (mainIndex.blobs(thumbnailBlobIndex)?.kind() !== BlobKind.ThumbnailImage) {
189
+ throw new YOMValidationError(`page ${pageIndex} thumbnail blob has wrong kind`);
190
+ }
191
+ if (usedThumbnailBlobIndices.has(thumbnailBlobIndex)) {
192
+ throw new YOMValidationError(`blob ${thumbnailBlobIndex} referenced as thumbnail by more than one page`);
193
+ }
194
+ usedThumbnailBlobIndices.add(thumbnailBlobIndex);
195
+ }
196
+ }
197
+ //# sourceMappingURL=validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/yom/validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ import { BlobKind } from "./generated/yomu/yom/blob-kind.js";
2
+ import { Compression } from "./generated/yomu/yom/compression.js";
3
+ import type { ReadingDirection } from "./generated/yomu/yom/reading-direction.js";
4
+ /**
5
+ * Emits a YOM v1 packfile: `[4096-byte header][uncompressed MainIndex
6
+ * FlatBuffer][blob area, each blob aligned per its BlobRef.alignment,
7
+ * offsets relative to file start][footer mirror]`. Ports the Swift
8
+ * implementation in `swift/Sources/YOMFormat/YOMPackfileWriter.swift` +
9
+ * `YOMPackfileWriter+Index.swift` field-for-field.
10
+ *
11
+ * Compression is not caller-selectable: every blob's declared `compression`
12
+ * must equal `requiredCompression(kind)` exactly, checked before any bytes
13
+ * are written. Hashes are always computed over each blob's original
14
+ * (pre-compression) bytes.
15
+ */
16
+ export interface BlobInput {
17
+ kind: BlobKind;
18
+ data: Uint8Array;
19
+ compression: Compression;
20
+ }
21
+ export interface PageInput {
22
+ pageLabel: string;
23
+ pixelWidth: number;
24
+ pixelHeight: number;
25
+ dpi: number;
26
+ colorSpace: string;
27
+ colorProfileRef: string;
28
+ mediaBox: number[];
29
+ cropBox: number[];
30
+ contentBox: number[];
31
+ rotation: number;
32
+ readingDirection: ReadingDirection;
33
+ /** Must have `kind === BlobKind.PageImage`. */
34
+ pageImage: BlobInput;
35
+ /** Must have `kind === BlobKind.ThumbnailImage`. */
36
+ thumbnail: BlobInput;
37
+ }
38
+ export interface BookInput {
39
+ title: string;
40
+ readingDirection: ReadingDirection;
41
+ createdAtUnix: bigint;
42
+ }
43
+ export interface SearchTermInput {
44
+ term: string;
45
+ dictionaryOffset: bigint;
46
+ dictionaryLength: bigint;
47
+ postingsOffset: bigint;
48
+ postingsLength: bigint;
49
+ }
50
+ export interface OutlineInput {
51
+ title: string;
52
+ pageId: number;
53
+ children: OutlineInput[];
54
+ }
55
+ export interface PDFExportInput {
56
+ pageLabels: string[];
57
+ outline: OutlineInput[];
58
+ }
59
+ export interface WriterInput {
60
+ book: BookInput;
61
+ pages: PageInput[];
62
+ /** Must have `kind === BlobKind.OCRLayout` when present. */
63
+ ocrLayout?: BlobInput;
64
+ /** Must have `kind === BlobKind.NormalizedText` when present. */
65
+ normalizedText?: BlobInput;
66
+ /** Must have `kind === BlobKind.SearchDictionary` when present. */
67
+ searchDictionary?: BlobInput;
68
+ /** Must have `kind === BlobKind.SearchPostings` when present. */
69
+ searchPostings?: BlobInput;
70
+ searchTerms: SearchTermInput[];
71
+ pdfExport?: PDFExportInput;
72
+ }
73
+ export declare class YOMWriterError extends Error {
74
+ }
75
+ export declare function writeYOM(input: WriterInput): Promise<Uint8Array>;
76
+ //# sourceMappingURL=writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer.d.ts","sourceRoot":"","sources":["../../src/yom/writer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAClE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAqBlF;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,UAAU,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,+CAA+C;IAC/C,SAAS,EAAE,SAAS,CAAC;IACrB,oDAAoD;IACpD,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,iEAAiE;IACjE,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B,iEAAiE;IACjE,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,SAAS,CAAC,EAAE,cAAc,CAAC;CAC5B;AAED,qBAAa,cAAe,SAAQ,KAAK;CAAG;AAgC5C,wBAAsB,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CA2GtE"}