@intactfile/engines 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 (207) hide show
  1. package/README.md +68 -0
  2. package/dist/archive/diagnose.d.ts +37 -0
  3. package/dist/archive/diagnose.d.ts.map +1 -0
  4. package/dist/archive/diagnose.js +165 -0
  5. package/dist/archive/diagnose.js.map +1 -0
  6. package/dist/archive/format.d.ts +52 -0
  7. package/dist/archive/format.d.ts.map +1 -0
  8. package/dist/archive/format.js +87 -0
  9. package/dist/archive/format.js.map +1 -0
  10. package/dist/archive/host.d.ts +83 -0
  11. package/dist/archive/host.d.ts.map +1 -0
  12. package/dist/archive/host.js +92 -0
  13. package/dist/archive/host.js.map +1 -0
  14. package/dist/archive/index.d.ts +22 -0
  15. package/dist/archive/index.d.ts.map +1 -0
  16. package/dist/archive/index.js +19 -0
  17. package/dist/archive/index.js.map +1 -0
  18. package/dist/archive/salvage.d.ts +73 -0
  19. package/dist/archive/salvage.d.ts.map +1 -0
  20. package/dist/archive/salvage.js +210 -0
  21. package/dist/archive/salvage.js.map +1 -0
  22. package/dist/byte-source.d.ts +19 -0
  23. package/dist/byte-source.d.ts.map +1 -0
  24. package/dist/byte-source.js +16 -0
  25. package/dist/byte-source.js.map +1 -0
  26. package/dist/bytesource/blob.d.ts +14 -0
  27. package/dist/bytesource/blob.d.ts.map +1 -0
  28. package/dist/bytesource/blob.js +23 -0
  29. package/dist/bytesource/blob.js.map +1 -0
  30. package/dist/crc32.d.ts +2 -0
  31. package/dist/crc32.d.ts.map +1 -0
  32. package/dist/crc32.js +18 -0
  33. package/dist/crc32.js.map +1 -0
  34. package/dist/detect/index.d.ts +16 -0
  35. package/dist/detect/index.d.ts.map +1 -0
  36. package/dist/detect/index.js +159 -0
  37. package/dist/detect/index.js.map +1 -0
  38. package/dist/index.d.ts +24 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +17 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/jpeg/browser-loader.d.ts +21 -0
  43. package/dist/jpeg/browser-loader.d.ts.map +1 -0
  44. package/dist/jpeg/browser-loader.js +28 -0
  45. package/dist/jpeg/browser-loader.js.map +1 -0
  46. package/dist/jpeg/diagnose.d.ts +50 -0
  47. package/dist/jpeg/diagnose.d.ts.map +1 -0
  48. package/dist/jpeg/diagnose.js +124 -0
  49. package/dist/jpeg/diagnose.js.map +1 -0
  50. package/dist/jpeg/exif.d.ts +11 -0
  51. package/dist/jpeg/exif.d.ts.map +1 -0
  52. package/dist/jpeg/exif.js +50 -0
  53. package/dist/jpeg/exif.js.map +1 -0
  54. package/dist/jpeg/format.d.ts +106 -0
  55. package/dist/jpeg/format.d.ts.map +1 -0
  56. package/dist/jpeg/format.js +248 -0
  57. package/dist/jpeg/format.js.map +1 -0
  58. package/dist/jpeg/index.d.ts +18 -0
  59. package/dist/jpeg/index.d.ts.map +1 -0
  60. package/dist/jpeg/index.js +14 -0
  61. package/dist/jpeg/index.js.map +1 -0
  62. package/dist/jpeg/mozjpeg-host.d.ts +60 -0
  63. package/dist/jpeg/mozjpeg-host.d.ts.map +1 -0
  64. package/dist/jpeg/mozjpeg-host.js +138 -0
  65. package/dist/jpeg/mozjpeg-host.js.map +1 -0
  66. package/dist/jpeg/repair.d.ts +89 -0
  67. package/dist/jpeg/repair.d.ts.map +1 -0
  68. package/dist/jpeg/repair.js +216 -0
  69. package/dist/jpeg/repair.js.map +1 -0
  70. package/dist/node.d.ts +11 -0
  71. package/dist/node.d.ts.map +1 -0
  72. package/dist/node.js +29 -0
  73. package/dist/node.js.map +1 -0
  74. package/dist/pdf/browser-loader.d.ts +30 -0
  75. package/dist/pdf/browser-loader.d.ts.map +1 -0
  76. package/dist/pdf/browser-loader.js +21 -0
  77. package/dist/pdf/browser-loader.js.map +1 -0
  78. package/dist/pdf/diagnose.d.ts +23 -0
  79. package/dist/pdf/diagnose.d.ts.map +1 -0
  80. package/dist/pdf/diagnose.js +113 -0
  81. package/dist/pdf/diagnose.js.map +1 -0
  82. package/dist/pdf/format.d.ts +61 -0
  83. package/dist/pdf/format.d.ts.map +1 -0
  84. package/dist/pdf/format.js +150 -0
  85. package/dist/pdf/format.js.map +1 -0
  86. package/dist/pdf/index.d.ts +17 -0
  87. package/dist/pdf/index.d.ts.map +1 -0
  88. package/dist/pdf/index.js +12 -0
  89. package/dist/pdf/index.js.map +1 -0
  90. package/dist/pdf/qpdf-host.d.ts +66 -0
  91. package/dist/pdf/qpdf-host.d.ts.map +1 -0
  92. package/dist/pdf/qpdf-host.js +149 -0
  93. package/dist/pdf/qpdf-host.js.map +1 -0
  94. package/dist/pdf/rebuild.d.ts +32 -0
  95. package/dist/pdf/rebuild.d.ts.map +1 -0
  96. package/dist/pdf/rebuild.js +90 -0
  97. package/dist/pdf/rebuild.js.map +1 -0
  98. package/dist/pdf/repair.d.ts +61 -0
  99. package/dist/pdf/repair.d.ts.map +1 -0
  100. package/dist/pdf/repair.js +167 -0
  101. package/dist/pdf/repair.js.map +1 -0
  102. package/dist/png/diagnose.d.ts +50 -0
  103. package/dist/png/diagnose.d.ts.map +1 -0
  104. package/dist/png/diagnose.js +261 -0
  105. package/dist/png/diagnose.js.map +1 -0
  106. package/dist/png/format.d.ts +133 -0
  107. package/dist/png/format.d.ts.map +1 -0
  108. package/dist/png/format.js +350 -0
  109. package/dist/png/format.js.map +1 -0
  110. package/dist/png/index.d.ts +13 -0
  111. package/dist/png/index.d.ts.map +1 -0
  112. package/dist/png/index.js +10 -0
  113. package/dist/png/index.js.map +1 -0
  114. package/dist/png/repair.d.ts +31 -0
  115. package/dist/png/repair.d.ts.map +1 -0
  116. package/dist/png/repair.js +335 -0
  117. package/dist/png/repair.js.map +1 -0
  118. package/dist/sqlite/diagnose.d.ts +31 -0
  119. package/dist/sqlite/diagnose.d.ts.map +1 -0
  120. package/dist/sqlite/diagnose.js +169 -0
  121. package/dist/sqlite/diagnose.js.map +1 -0
  122. package/dist/sqlite/format.d.ts +103 -0
  123. package/dist/sqlite/format.d.ts.map +1 -0
  124. package/dist/sqlite/format.js +237 -0
  125. package/dist/sqlite/format.js.map +1 -0
  126. package/dist/sqlite/index.d.ts +24 -0
  127. package/dist/sqlite/index.d.ts.map +1 -0
  128. package/dist/sqlite/index.js +19 -0
  129. package/dist/sqlite/index.js.map +1 -0
  130. package/dist/sqlite/recover.d.ts +66 -0
  131. package/dist/sqlite/recover.d.ts.map +1 -0
  132. package/dist/sqlite/recover.js +305 -0
  133. package/dist/sqlite/recover.js.map +1 -0
  134. package/dist/sqlite/scan.d.ts +94 -0
  135. package/dist/sqlite/scan.d.ts.map +1 -0
  136. package/dist/sqlite/scan.js +356 -0
  137. package/dist/sqlite/scan.js.map +1 -0
  138. package/dist/sqlite/sqlite-host.d.ts +37 -0
  139. package/dist/sqlite/sqlite-host.d.ts.map +1 -0
  140. package/dist/sqlite/sqlite-host.js +80 -0
  141. package/dist/sqlite/sqlite-host.js.map +1 -0
  142. package/dist/sqlite/wal.d.ts +14 -0
  143. package/dist/sqlite/wal.d.ts.map +1 -0
  144. package/dist/sqlite/wal.js +79 -0
  145. package/dist/sqlite/wal.js.map +1 -0
  146. package/dist/types.d.ts +2 -0
  147. package/dist/types.d.ts.map +1 -0
  148. package/dist/types.js +2 -0
  149. package/dist/types.js.map +1 -0
  150. package/dist/video/diagnose.d.ts +41 -0
  151. package/dist/video/diagnose.d.ts.map +1 -0
  152. package/dist/video/diagnose.js +188 -0
  153. package/dist/video/diagnose.js.map +1 -0
  154. package/dist/video/format.d.ts +87 -0
  155. package/dist/video/format.d.ts.map +1 -0
  156. package/dist/video/format.js +273 -0
  157. package/dist/video/format.js.map +1 -0
  158. package/dist/video/index.d.ts +21 -0
  159. package/dist/video/index.d.ts.map +1 -0
  160. package/dist/video/index.js +17 -0
  161. package/dist/video/index.js.map +1 -0
  162. package/dist/video/libav-host.d.ts +88 -0
  163. package/dist/video/libav-host.d.ts.map +1 -0
  164. package/dist/video/libav-host.js +66 -0
  165. package/dist/video/libav-host.js.map +1 -0
  166. package/dist/video/mp4-rebuild.d.ts +167 -0
  167. package/dist/video/mp4-rebuild.d.ts.map +1 -0
  168. package/dist/video/mp4-rebuild.js +270 -0
  169. package/dist/video/mp4-rebuild.js.map +1 -0
  170. package/dist/video/mp4box-host.d.ts +62 -0
  171. package/dist/video/mp4box-host.d.ts.map +1 -0
  172. package/dist/video/mp4box-host.js +209 -0
  173. package/dist/video/mp4box-host.js.map +1 -0
  174. package/dist/video/reconstruct.d.ts +97 -0
  175. package/dist/video/reconstruct.d.ts.map +1 -0
  176. package/dist/video/reconstruct.js +271 -0
  177. package/dist/video/reconstruct.js.map +1 -0
  178. package/dist/video/remux.d.ts +85 -0
  179. package/dist/video/remux.d.ts.map +1 -0
  180. package/dist/video/remux.js +350 -0
  181. package/dist/video/remux.js.map +1 -0
  182. package/dist/zip/diagnose.d.ts +22 -0
  183. package/dist/zip/diagnose.d.ts.map +1 -0
  184. package/dist/zip/diagnose.js +126 -0
  185. package/dist/zip/diagnose.js.map +1 -0
  186. package/dist/zip/format.d.ts +79 -0
  187. package/dist/zip/format.d.ts.map +1 -0
  188. package/dist/zip/format.js +129 -0
  189. package/dist/zip/format.js.map +1 -0
  190. package/dist/zip/repair.d.ts +32 -0
  191. package/dist/zip/repair.d.ts.map +1 -0
  192. package/dist/zip/repair.js +82 -0
  193. package/dist/zip/repair.js.map +1 -0
  194. package/dist/zip/salvage.d.ts +23 -0
  195. package/dist/zip/salvage.d.ts.map +1 -0
  196. package/dist/zip/salvage.js +140 -0
  197. package/dist/zip/salvage.js.map +1 -0
  198. package/dist/zip/scan.d.ts +64 -0
  199. package/dist/zip/scan.d.ts.map +1 -0
  200. package/dist/zip/scan.js +386 -0
  201. package/dist/zip/scan.js.map +1 -0
  202. package/dist/zip/writer.d.ts +14 -0
  203. package/dist/zip/writer.d.ts.map +1 -0
  204. package/dist/zip/writer.js +131 -0
  205. package/dist/zip/writer.js.map +1 -0
  206. package/package.json +71 -0
  207. package/src/archive/LICENSE-unrar.txt +53 -0
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Pure JPEG marker-scan primitives — no wasm, no third-party deps, so this
3
+ * module is safe to pull into the browser-facing diagnosis path.
4
+ *
5
+ * A JPEG is a sequence of marker segments framed by 0xFF <marker> bytes.
6
+ * Standalone markers (SOI, EOI, RSTn, TEM) carry no payload; every other
7
+ * marker is followed by a big-endian 2-byte length that INCLUDES those two
8
+ * length bytes. After SOS the entropy-coded scan data runs raw until the next
9
+ * real marker (0xFF followed by a non-0x00, non-RSTn byte), typically EOI.
10
+ *
11
+ * Two views are offered: a strict sequential walk (order, overflow, structural
12
+ * corruption) and a robust presence scan (which markers exist *anywhere*, so a
13
+ * destroyed header whose SOS+scan survived is still recognisable — the case
14
+ * donor transplant exists for).
15
+ */
16
+ export declare const M_SOI = 216;
17
+ export declare const M_EOI = 217;
18
+ export declare const M_TEM = 1;
19
+ export declare const M_RST0 = 208;
20
+ export declare const M_RST7 = 215;
21
+ export declare const M_SOS = 218;
22
+ export declare const M_DQT = 219;
23
+ export declare const M_DHT = 196;
24
+ export declare const M_DRI = 221;
25
+ export declare const M_APP0 = 224;
26
+ export declare const M_APP15 = 239;
27
+ export declare const M_COM = 254;
28
+ /** SOF markers are 0xC0..0xCF except 0xC4 (DHT), 0xC8 (JPG), 0xCC (DAC). */
29
+ export declare function isSofMarker(m: number): boolean;
30
+ export declare function isAppMarker(m: number): boolean;
31
+ export declare function isStandaloneMarker(m: number): boolean;
32
+ export declare function markerName(m: number): string;
33
+ export declare function readU16BE(b: Uint8Array, off: number): number;
34
+ /** Locate the first SOI (0xFFD8) within [0, window). Returns -1 if absent. */
35
+ export declare function findSoi(bytes: Uint8Array, window?: number): number;
36
+ export interface MarkerSegment {
37
+ marker: number;
38
+ name: string;
39
+ /** Offset of the 0xFF byte. */
40
+ offset: number;
41
+ /** Declared segment length (payload+2), or 0 for standalone markers. */
42
+ length: number;
43
+ }
44
+ export interface MarkerScan {
45
+ soiOffset: number;
46
+ segments: MarkerSegment[];
47
+ /** Offset of the SOS 0xFF byte, or -1. */
48
+ sosOffset: number;
49
+ /** First byte of entropy-coded scan data, or -1. */
50
+ scanStart: number;
51
+ /** One past the last scan byte (EOI offset or EOF), or -1. */
52
+ scanEnd: number;
53
+ /** Offset of the trailing EOI 0xFF byte, or -1. */
54
+ eoiOffset: number;
55
+ hasEoi: boolean;
56
+ /** A segment length ran past EOF (structural corruption or truncation). */
57
+ overflow: boolean;
58
+ /** Expected a 0xFF marker lead but found something else before SOS. */
59
+ badMarker: boolean;
60
+ /** Ran out of bytes while still walking the header (before SOS resolved). */
61
+ truncatedHeader: boolean;
62
+ }
63
+ /**
64
+ * Strict sequential walk from SOI. Stops at SOS (recording where the scan
65
+ * begins) or at the first structural problem. Never throws.
66
+ */
67
+ export declare function scanMarkers(bytes: Uint8Array, soiOffset: number): MarkerScan;
68
+ /** Find the trailing EOI (0xFFD9) scanning forward from `from`. */
69
+ export declare function findEoiFrom(bytes: Uint8Array, from: number): number;
70
+ export interface MarkerPresence {
71
+ hasDqt: boolean;
72
+ hasDht: boolean;
73
+ hasSof: boolean;
74
+ hasSos: boolean;
75
+ hasEoi: boolean;
76
+ /** Offset of the first SOS 0xFF byte, or -1. */
77
+ sosOffset: number;
78
+ /** Offset of the last EOI 0xFF byte, or -1. */
79
+ eoiOffset: number;
80
+ /** Offset of the first SOF 0xFF byte, or -1. */
81
+ sofOffset: number;
82
+ }
83
+ /**
84
+ * Robust presence scan: look for each key marker anywhere in [start, end),
85
+ * independent of sequence. Survives a zeroed/garbled header as long as the
86
+ * marker bytes themselves are intact — how we recognise "header destroyed but
87
+ * scan alive". Skips 0xFF00 byte-stuffing and 0xFFFF fill.
88
+ */
89
+ export declare function scanMarkerPresence(bytes: Uint8Array, start: number, end?: number): MarkerPresence;
90
+ /**
91
+ * Read the frame dimensions from a SOF segment at `sofOffset` (the 0xFF byte).
92
+ * SOF layout: FF Cx | len(2) | precision(1) | height(2) | width(2) | ...
93
+ * Returns null when the segment is not fully present.
94
+ */
95
+ export declare function readSofDimensions(bytes: Uint8Array, sofOffset: number): {
96
+ width: number;
97
+ height: number;
98
+ } | null;
99
+ /**
100
+ * Shannon entropy (bits/byte, 0..8) over [start, end). A healthy JPEG scan is
101
+ * high (~7.3–8.0); a zeroed or overwritten scan collapses toward 0 — a cheap
102
+ * triage hint for "structure looks fine but the pixels were destroyed". For
103
+ * large ranges the data is strided to cap cost. Returns null for empty ranges.
104
+ */
105
+ export declare function shannonEntropy(bytes: Uint8Array, start: number, end: number): number | null;
106
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/jpeg/format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,248 @@
1
+ /**
2
+ * Pure JPEG marker-scan primitives — no wasm, no third-party deps, so this
3
+ * module is safe to pull into the browser-facing diagnosis path.
4
+ *
5
+ * A JPEG is a sequence of marker segments framed by 0xFF <marker> bytes.
6
+ * Standalone markers (SOI, EOI, RSTn, TEM) carry no payload; every other
7
+ * marker is followed by a big-endian 2-byte length that INCLUDES those two
8
+ * length bytes. After SOS the entropy-coded scan data runs raw until the next
9
+ * real marker (0xFF followed by a non-0x00, non-RSTn byte), typically EOI.
10
+ *
11
+ * Two views are offered: a strict sequential walk (order, overflow, structural
12
+ * corruption) and a robust presence scan (which markers exist *anywhere*, so a
13
+ * destroyed header whose SOS+scan survived is still recognisable — the case
14
+ * donor transplant exists for).
15
+ */
16
+ // Standalone markers (no length field).
17
+ export const M_SOI = 0xd8;
18
+ export const M_EOI = 0xd9;
19
+ export const M_TEM = 0x01;
20
+ export const M_RST0 = 0xd0;
21
+ export const M_RST7 = 0xd7;
22
+ // Segment markers we care about.
23
+ export const M_SOS = 0xda;
24
+ export const M_DQT = 0xdb;
25
+ export const M_DHT = 0xc4;
26
+ export const M_DRI = 0xdd;
27
+ export const M_APP0 = 0xe0;
28
+ export const M_APP15 = 0xef;
29
+ export const M_COM = 0xfe;
30
+ /** SOF markers are 0xC0..0xCF except 0xC4 (DHT), 0xC8 (JPG), 0xCC (DAC). */
31
+ export function isSofMarker(m) {
32
+ return m >= 0xc0 && m <= 0xcf && m !== 0xc4 && m !== 0xc8 && m !== 0xcc;
33
+ }
34
+ export function isAppMarker(m) {
35
+ return m >= M_APP0 && m <= M_APP15;
36
+ }
37
+ export function isStandaloneMarker(m) {
38
+ return m === M_SOI || m === M_EOI || m === M_TEM || (m >= M_RST0 && m <= M_RST7);
39
+ }
40
+ export function markerName(m) {
41
+ switch (m) {
42
+ case M_SOI:
43
+ return 'SOI';
44
+ case M_EOI:
45
+ return 'EOI';
46
+ case M_SOS:
47
+ return 'SOS';
48
+ case M_DQT:
49
+ return 'DQT';
50
+ case M_DHT:
51
+ return 'DHT';
52
+ case M_DRI:
53
+ return 'DRI';
54
+ case M_COM:
55
+ return 'COM';
56
+ case M_TEM:
57
+ return 'TEM';
58
+ default:
59
+ break;
60
+ }
61
+ if (isSofMarker(m))
62
+ return `SOF${m - 0xc0}`;
63
+ if (isAppMarker(m))
64
+ return `APP${m - M_APP0}`;
65
+ if (m >= M_RST0 && m <= M_RST7)
66
+ return `RST${m - M_RST0}`;
67
+ return `0x${m.toString(16).padStart(2, '0')}`;
68
+ }
69
+ export function readU16BE(b, off) {
70
+ return ((b[off] ?? 0) << 8) | (b[off + 1] ?? 0);
71
+ }
72
+ /** Locate the first SOI (0xFFD8) within [0, window). Returns -1 if absent. */
73
+ export function findSoi(bytes, window = bytes.length) {
74
+ const limit = Math.min(bytes.length - 1, window);
75
+ for (let i = 0; i <= limit; i++) {
76
+ if (bytes[i] === 0xff && bytes[i + 1] === M_SOI)
77
+ return i;
78
+ }
79
+ return -1;
80
+ }
81
+ /**
82
+ * Strict sequential walk from SOI. Stops at SOS (recording where the scan
83
+ * begins) or at the first structural problem. Never throws.
84
+ */
85
+ export function scanMarkers(bytes, soiOffset) {
86
+ const scan = {
87
+ soiOffset,
88
+ segments: [],
89
+ sosOffset: -1,
90
+ scanStart: -1,
91
+ scanEnd: -1,
92
+ eoiOffset: -1,
93
+ hasEoi: false,
94
+ overflow: false,
95
+ badMarker: false,
96
+ truncatedHeader: false,
97
+ };
98
+ const len = bytes.length;
99
+ let i = soiOffset + 2;
100
+ while (i < len) {
101
+ // 0xFF fill bytes are permitted before a marker.
102
+ while (i < len && bytes[i] === 0xff && bytes[i + 1] === 0xff)
103
+ i++;
104
+ if (i + 1 >= len) {
105
+ scan.truncatedHeader = true;
106
+ break;
107
+ }
108
+ if (bytes[i] !== 0xff) {
109
+ scan.badMarker = true;
110
+ break;
111
+ }
112
+ const m = bytes[i + 1];
113
+ if (m === M_EOI) {
114
+ scan.hasEoi = true;
115
+ scan.eoiOffset = i;
116
+ break;
117
+ }
118
+ if (isStandaloneMarker(m)) {
119
+ i += 2;
120
+ continue;
121
+ }
122
+ if (i + 3 >= len) {
123
+ scan.truncatedHeader = true;
124
+ break;
125
+ }
126
+ const segLen = readU16BE(bytes, i + 2);
127
+ scan.segments.push({ marker: m, name: markerName(m), offset: i, length: segLen });
128
+ if (m === M_SOS) {
129
+ scan.sosOffset = i;
130
+ scan.scanStart = i + 2 + segLen;
131
+ // Scan data ends at the trailing EOI, else EOF.
132
+ const eoi = findEoiFrom(bytes, scan.scanStart);
133
+ scan.eoiOffset = eoi;
134
+ scan.hasEoi = eoi !== -1;
135
+ scan.scanEnd = eoi === -1 ? len : eoi;
136
+ if (scan.scanStart > len)
137
+ scan.overflow = true;
138
+ break;
139
+ }
140
+ const segEnd = i + 2 + segLen;
141
+ if (segLen < 2 || segEnd > len) {
142
+ scan.overflow = true;
143
+ break;
144
+ }
145
+ i = segEnd;
146
+ }
147
+ return scan;
148
+ }
149
+ /** Find the trailing EOI (0xFFD9) scanning forward from `from`. */
150
+ export function findEoiFrom(bytes, from) {
151
+ for (let i = Math.max(0, from); i + 1 < bytes.length; i++) {
152
+ if (bytes[i] === 0xff && bytes[i + 1] === M_EOI)
153
+ return i;
154
+ }
155
+ return -1;
156
+ }
157
+ /**
158
+ * Robust presence scan: look for each key marker anywhere in [start, end),
159
+ * independent of sequence. Survives a zeroed/garbled header as long as the
160
+ * marker bytes themselves are intact — how we recognise "header destroyed but
161
+ * scan alive". Skips 0xFF00 byte-stuffing and 0xFFFF fill.
162
+ */
163
+ export function scanMarkerPresence(bytes, start, end = bytes.length) {
164
+ const p = {
165
+ hasDqt: false,
166
+ hasDht: false,
167
+ hasSof: false,
168
+ hasSos: false,
169
+ hasEoi: false,
170
+ sosOffset: -1,
171
+ eoiOffset: -1,
172
+ sofOffset: -1,
173
+ };
174
+ const limit = Math.min(end, bytes.length) - 1;
175
+ for (let i = Math.max(0, start); i <= limit; i++) {
176
+ if (bytes[i] !== 0xff)
177
+ continue;
178
+ const m = bytes[i + 1];
179
+ if (m === 0x00 || m === 0xff)
180
+ continue; // stuffing / fill
181
+ if (m === M_DQT)
182
+ p.hasDqt = true;
183
+ else if (m === M_DHT)
184
+ p.hasDht = true;
185
+ else if (isSofMarker(m)) {
186
+ p.hasSof = true;
187
+ if (p.sofOffset === -1)
188
+ p.sofOffset = i;
189
+ }
190
+ else if (m === M_SOS) {
191
+ p.hasSos = true;
192
+ if (p.sosOffset === -1)
193
+ p.sosOffset = i;
194
+ }
195
+ else if (m === M_EOI) {
196
+ p.hasEoi = true;
197
+ p.eoiOffset = i;
198
+ }
199
+ }
200
+ return p;
201
+ }
202
+ /**
203
+ * Read the frame dimensions from a SOF segment at `sofOffset` (the 0xFF byte).
204
+ * SOF layout: FF Cx | len(2) | precision(1) | height(2) | width(2) | ...
205
+ * Returns null when the segment is not fully present.
206
+ */
207
+ export function readSofDimensions(bytes, sofOffset) {
208
+ if (sofOffset < 0 || sofOffset + 9 > bytes.length)
209
+ return null;
210
+ const height = readU16BE(bytes, sofOffset + 5);
211
+ const width = readU16BE(bytes, sofOffset + 7);
212
+ if (width === 0 || height === 0)
213
+ return null;
214
+ return { width, height };
215
+ }
216
+ /**
217
+ * Shannon entropy (bits/byte, 0..8) over [start, end). A healthy JPEG scan is
218
+ * high (~7.3–8.0); a zeroed or overwritten scan collapses toward 0 — a cheap
219
+ * triage hint for "structure looks fine but the pixels were destroyed". For
220
+ * large ranges the data is strided to cap cost. Returns null for empty ranges.
221
+ */
222
+ export function shannonEntropy(bytes, start, end) {
223
+ const lo = Math.max(0, start);
224
+ const hi = Math.min(bytes.length, end);
225
+ const span = hi - lo;
226
+ if (span <= 0)
227
+ return null;
228
+ const stride = span > 65536 ? Math.ceil(span / 65536) : 1;
229
+ const hist = new Uint32Array(256);
230
+ let n = 0;
231
+ for (let i = lo; i < hi; i += stride) {
232
+ const b = bytes[i];
233
+ hist[b] = (hist[b] ?? 0) + 1;
234
+ n++;
235
+ }
236
+ if (n === 0)
237
+ return null;
238
+ let h = 0;
239
+ for (let v = 0; v < 256; v++) {
240
+ const c = hist[v];
241
+ if (c === 0)
242
+ continue;
243
+ const pr = c / n;
244
+ h -= pr * Math.log2(pr);
245
+ }
246
+ return h;
247
+ }
248
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/jpeg/format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * JPEG engine subpath export (`@intactfile/engines/jpeg`). Kept out of the
3
+ * root export so browser bundles that never touch JPEGs never pull in the
4
+ * @jsquash codec wasm or exifr; even here, the codec wasm only loads on the
5
+ * first repairJpeg call. diagnoseJpeg is pure marker-scanning and safe to call
6
+ * eagerly.
7
+ */
8
+ export { diagnoseJpeg, LOW_SCAN_ENTROPY, SOI_SCAN_WINDOW } from './diagnose.js';
9
+ export type { JpegDiagnosis, JpegDamageClass } from './diagnose.js';
10
+ export { repairJpeg, buildRepairCandidates, transplantHeader } from './repair.js';
11
+ export type { JpegRepairResult, JpegRepairReport, JpegRepairOptions, JpegRepairOutcome, JpegRepairStrategy, JpegRepairAttempt, } from './repair.js';
12
+ export { extractExifThumbnail, extractExifOrientation } from './exif.js';
13
+ export { decodeJpeg, encodeJpeg, setJpegLoader, resetJpegHost, SALVAGE_ENCODE_OPTIONS, } from './mozjpeg-host.js';
14
+ export type { DecodedImage, DecodeResult, JpegCodecLoader, JpegEncodeOptions } from './mozjpeg-host.js';
15
+ export { createBrowserJpegLoader, DEFAULT_JPEG_BASE_URL } from './browser-loader.js';
16
+ export { markerName, isSofMarker, isAppMarker, scanMarkers, scanMarkerPresence, findSoi, findEoiFrom, readSofDimensions, shannonEntropy, } from './format.js';
17
+ export type { MarkerScan, MarkerSegment, MarkerPresence } from './format.js';
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/jpeg/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChF,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAClF,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAEzE,OAAO,EACL,UAAU,EACV,UAAU,EACV,aAAa,EACb,aAAa,EACb,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAExG,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAErF,OAAO,EACL,UAAU,EACV,WAAW,EACX,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,OAAO,EACP,WAAW,EACX,iBAAiB,EACjB,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * JPEG engine subpath export (`@intactfile/engines/jpeg`). Kept out of the
3
+ * root export so browser bundles that never touch JPEGs never pull in the
4
+ * @jsquash codec wasm or exifr; even here, the codec wasm only loads on the
5
+ * first repairJpeg call. diagnoseJpeg is pure marker-scanning and safe to call
6
+ * eagerly.
7
+ */
8
+ export { diagnoseJpeg, LOW_SCAN_ENTROPY, SOI_SCAN_WINDOW } from './diagnose.js';
9
+ export { repairJpeg, buildRepairCandidates, transplantHeader } from './repair.js';
10
+ export { extractExifThumbnail, extractExifOrientation } from './exif.js';
11
+ export { decodeJpeg, encodeJpeg, setJpegLoader, resetJpegHost, SALVAGE_ENCODE_OPTIONS, } from './mozjpeg-host.js';
12
+ export { createBrowserJpegLoader, DEFAULT_JPEG_BASE_URL } from './browser-loader.js';
13
+ export { markerName, isSofMarker, isAppMarker, scanMarkers, scanMarkerPresence, findSoi, findEoiFrom, readSofDimensions, shannonEntropy, } from './format.js';
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/jpeg/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGhF,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAUlF,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAEzE,OAAO,EACL,UAAU,EACV,UAAU,EACV,aAAa,EACb,aAAa,EACb,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAErF,OAAO,EACL,UAAU,EACV,WAAW,EACX,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,OAAO,EACP,WAAW,EACX,iBAAiB,EACjB,cAAc,GACf,MAAM,aAAa,CAAC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Isolated host for the MozJPEG (libjpeg-turbo lineage) wasm codec shipped by
3
+ * @jsquash/jpeg 1.6.0 (Apache-2.0). Two wasm modules: the decoder
4
+ * (mozjpeg_dec.wasm, ~163 KB) and the encoder (mozjpeg_enc.wasm, ~246 KB).
5
+ * Everything that touches the codec lives here; nothing else in the package
6
+ * imports @jsquash/jpeg, and the wasm is only compiled on first use.
7
+ *
8
+ * Loading is injectable, same shape as pdf/qpdf-host.ts and video/libav-host.ts:
9
+ * the Node default loader reads the two .wasm files from node_modules and
10
+ * compiles them; a browser host calls setJpegLoader() with a loader that
11
+ * fetches+compiles them from a same-origin URL (see browser-loader.ts). This
12
+ * matters because @jsquash's default codec path uses fetch(import.meta.url)
13
+ * to locate the wasm, which does not work in Node.
14
+ *
15
+ * Why a warning-capturing decoder matters: libjpeg emits "Premature end of
16
+ * JPEG file" / "Corrupt JPEG data" to stderr but STILL returns the rows it
17
+ * managed to decode (the rest filled grey). Capturing that stderr is how we
18
+ * honestly tell a full decode from a partial salvage.
19
+ */
20
+ import decodeWasmDefault from '@jsquash/jpeg/decode.js';
21
+ import encodeWasmDefault from '@jsquash/jpeg/encode.js';
22
+ import type { EncodeOptions } from '@jsquash/jpeg/meta.js';
23
+ export interface DecodedImage {
24
+ data: Uint8Array;
25
+ width: number;
26
+ height: number;
27
+ }
28
+ export type DecodeResult = {
29
+ ok: true;
30
+ image: DecodedImage;
31
+ warnings: string[];
32
+ } | {
33
+ ok: false;
34
+ warnings: string[];
35
+ error: string;
36
+ };
37
+ export interface JpegCodecLoader {
38
+ /** Resolve a compiled decoder module (mozjpeg_dec.wasm). */
39
+ decodeModule: () => Promise<WebAssembly.Module>;
40
+ /** Resolve a compiled encoder module (mozjpeg_enc.wasm). */
41
+ encodeModule: () => Promise<WebAssembly.Module>;
42
+ }
43
+ /** Inject how the codec wasm modules are obtained (browser hosts). */
44
+ export declare function setJpegLoader(load: () => Promise<JpegCodecLoader>): void;
45
+ /** Drop the cached codec init (tests, or after a wasm crash). */
46
+ export declare function resetJpegHost(): void;
47
+ /**
48
+ * Decode a JPEG, tolerating truncation/corruption. Returns a discriminated
49
+ * result rather than throwing: `ok:false` for a hard failure (no scan, missing
50
+ * SOS, unusable header), `ok:true` with `warnings` populated for a partial
51
+ * salvage (top rows recovered, remainder grey). Never throws for bad input.
52
+ */
53
+ export declare function decodeJpeg(bytes: Uint8Array): Promise<DecodeResult>;
54
+ export type JpegEncodeOptions = Partial<EncodeOptions>;
55
+ /** Baseline, widely-compatible re-emission of a salvaged raster. */
56
+ export declare const SALVAGE_ENCODE_OPTIONS: JpegEncodeOptions;
57
+ /** Encode an RGBA raster to a valid baseline JPEG. */
58
+ export declare function encodeJpeg(image: DecodedImage, options?: JpegEncodeOptions): Promise<Uint8Array>;
59
+ export { decodeWasmDefault, encodeWasmDefault };
60
+ //# sourceMappingURL=mozjpeg-host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mozjpeg-host.d.ts","sourceRoot":"","sources":["../../src/jpeg/mozjpeg-host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,iBAA4C,MAAM,yBAAyB,CAAC;AACnF,OAAO,iBAA4C,MAAM,yBAAyB,CAAC;AACnF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAQ3D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,YAAY,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,GACrD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD,MAAM,WAAW,eAAe;IAC9B,4DAA4D;IAC5D,YAAY,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAChD,4DAA4D;IAC5D,YAAY,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;CACjD;AAKD,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI,CAGxE;AAED,iEAAiE;AACjE,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAyDD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CAoBnE;AAED,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;AAEvD,oEAAoE;AACpE,eAAO,MAAM,sBAAsB,EAAE,iBAKpC,CAAC;AAEF,sDAAsD;AACtD,wBAAgB,UAAU,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,UAAU,CAAC,CAepG;AAGD,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,CAAC"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Isolated host for the MozJPEG (libjpeg-turbo lineage) wasm codec shipped by
3
+ * @jsquash/jpeg 1.6.0 (Apache-2.0). Two wasm modules: the decoder
4
+ * (mozjpeg_dec.wasm, ~163 KB) and the encoder (mozjpeg_enc.wasm, ~246 KB).
5
+ * Everything that touches the codec lives here; nothing else in the package
6
+ * imports @jsquash/jpeg, and the wasm is only compiled on first use.
7
+ *
8
+ * Loading is injectable, same shape as pdf/qpdf-host.ts and video/libav-host.ts:
9
+ * the Node default loader reads the two .wasm files from node_modules and
10
+ * compiles them; a browser host calls setJpegLoader() with a loader that
11
+ * fetches+compiles them from a same-origin URL (see browser-loader.ts). This
12
+ * matters because @jsquash's default codec path uses fetch(import.meta.url)
13
+ * to locate the wasm, which does not work in Node.
14
+ *
15
+ * Why a warning-capturing decoder matters: libjpeg emits "Premature end of
16
+ * JPEG file" / "Corrupt JPEG data" to stderr but STILL returns the rows it
17
+ * managed to decode (the rest filled grey). Capturing that stderr is how we
18
+ * honestly tell a full decode from a partial salvage.
19
+ */
20
+ import decodeWasmDefault, { init as initDecodeRaw } from '@jsquash/jpeg/decode.js';
21
+ import encodeWasmDefault, { init as initEncodeRaw } from '@jsquash/jpeg/encode.js';
22
+ const initDecode = initDecodeRaw;
23
+ const initEncode = initEncodeRaw;
24
+ let loaderOverride = null;
25
+ let initPromise = null;
26
+ /** Inject how the codec wasm modules are obtained (browser hosts). */
27
+ export function setJpegLoader(load) {
28
+ loaderOverride = load;
29
+ initPromise = null;
30
+ }
31
+ /** Drop the cached codec init (tests, or after a wasm crash). */
32
+ export function resetJpegHost() {
33
+ initPromise = null;
34
+ }
35
+ // stderr is captured per-run via a mutable sink; runs are serialized so the
36
+ // sink can never belong to two decodes at once.
37
+ let activeErr = null;
38
+ function errSink(line) {
39
+ activeErr?.push(typeof line === 'string' ? line : String(line));
40
+ }
41
+ async function defaultNodeLoader() {
42
+ const isNode = typeof process !== 'undefined' && !!process.versions?.node;
43
+ if (!isNode) {
44
+ throw new Error('jpeg host: no loader configured. In the browser, call setJpegLoader() with a loader that ' +
45
+ 'fetches and compiles the @jsquash/jpeg dec/enc wasm from a same-origin URL before repairing JPEGs.');
46
+ }
47
+ const { createRequire } = await import('node:module');
48
+ const { readFile } = await import('node:fs/promises');
49
+ const require = createRequire(import.meta.url);
50
+ const decPath = require.resolve('@jsquash/jpeg/codec/dec/mozjpeg_dec.wasm');
51
+ const encPath = require.resolve('@jsquash/jpeg/codec/enc/mozjpeg_enc.wasm');
52
+ return {
53
+ decodeModule: async () => WebAssembly.compile(await readFile(decPath)),
54
+ encodeModule: async () => WebAssembly.compile(await readFile(encPath)),
55
+ };
56
+ }
57
+ async function ensureInit() {
58
+ initPromise ??= (async () => {
59
+ const loader = await (loaderOverride ?? defaultNodeLoader)();
60
+ const [decMod, encMod] = await Promise.all([loader.decodeModule(), loader.encodeModule()]);
61
+ // Route the decoder's stderr into our capture sink; silence stdout.
62
+ await initDecode(decMod, { printErr: errSink, print: () => { } });
63
+ await initEncode(encMod, { printErr: () => { }, print: () => { } });
64
+ })().catch((e) => {
65
+ initPromise = null;
66
+ throw e;
67
+ });
68
+ return initPromise;
69
+ }
70
+ let runChain = Promise.resolve();
71
+ /** Serialize codec calls so the shared stderr sink is unambiguous. */
72
+ function exclusive(fn) {
73
+ const run = runChain.then(fn);
74
+ runChain = run.catch(() => undefined);
75
+ return run;
76
+ }
77
+ /** Standalone ArrayBuffer copy of `bytes` (jSquash decode wants an ArrayBuffer). */
78
+ function toArrayBuffer(bytes) {
79
+ const copy = new Uint8Array(bytes.length);
80
+ copy.set(bytes);
81
+ return copy.buffer;
82
+ }
83
+ /**
84
+ * Decode a JPEG, tolerating truncation/corruption. Returns a discriminated
85
+ * result rather than throwing: `ok:false` for a hard failure (no scan, missing
86
+ * SOS, unusable header), `ok:true` with `warnings` populated for a partial
87
+ * salvage (top rows recovered, remainder grey). Never throws for bad input.
88
+ */
89
+ export function decodeJpeg(bytes) {
90
+ return exclusive(async () => {
91
+ await ensureInit();
92
+ const warnings = [];
93
+ activeErr = warnings;
94
+ try {
95
+ const img = await decodeWasmDefault(toArrayBuffer(bytes));
96
+ const data = new Uint8Array(img.data.length);
97
+ data.set(img.data);
98
+ return { ok: true, image: { data, width: img.width, height: img.height }, warnings };
99
+ }
100
+ catch (e) {
101
+ return {
102
+ ok: false,
103
+ warnings,
104
+ error: e instanceof Error ? e.message : String(e),
105
+ };
106
+ }
107
+ finally {
108
+ activeErr = null;
109
+ }
110
+ });
111
+ }
112
+ /** Baseline, widely-compatible re-emission of a salvaged raster. */
113
+ export const SALVAGE_ENCODE_OPTIONS = {
114
+ quality: 85,
115
+ baseline: true,
116
+ progressive: false,
117
+ optimize_coding: true,
118
+ };
119
+ /** Encode an RGBA raster to a valid baseline JPEG. */
120
+ export function encodeJpeg(image, options = {}) {
121
+ return exclusive(async () => {
122
+ await ensureInit();
123
+ const imageData = {
124
+ data: new Uint8ClampedArray(image.data.buffer, image.data.byteOffset, image.data.byteLength),
125
+ width: image.width,
126
+ height: image.height,
127
+ colorSpace: 'srgb',
128
+ };
129
+ const buf = await encodeWasmDefault(imageData, {
130
+ ...SALVAGE_ENCODE_OPTIONS,
131
+ ...options,
132
+ });
133
+ return new Uint8Array(buf);
134
+ });
135
+ }
136
+ // Re-export for the default node path check and browser loader typing.
137
+ export { decodeWasmDefault, encodeWasmDefault };
138
+ //# sourceMappingURL=mozjpeg-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mozjpeg-host.js","sourceRoot":"","sources":["../../src/jpeg/mozjpeg-host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,iBAAiB,EAAE,EAAE,IAAI,IAAI,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACnF,OAAO,iBAAiB,EAAE,EAAE,IAAI,IAAI,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAMnF,MAAM,UAAU,GAAG,aAAmC,CAAC;AACvD,MAAM,UAAU,GAAG,aAAmC,CAAC;AAmBvD,IAAI,cAAc,GAA4C,IAAI,CAAC;AACnE,IAAI,WAAW,GAAyB,IAAI,CAAC;AAE7C,sEAAsE;AACtE,MAAM,UAAU,aAAa,CAAC,IAAoC;IAChE,cAAc,GAAG,IAAI,CAAC;IACtB,WAAW,GAAG,IAAI,CAAC;AACrB,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,aAAa;IAC3B,WAAW,GAAG,IAAI,CAAC;AACrB,CAAC;AAED,4EAA4E;AAC5E,gDAAgD;AAChD,IAAI,SAAS,GAAoB,IAAI,CAAC;AACtC,SAAS,OAAO,CAAC,IAAY;IAC3B,SAAS,EAAE,IAAI,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,KAAK,UAAU,iBAAiB;IAC9B,MAAM,MAAM,GAAG,OAAO,OAAO,KAAK,WAAW,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC;IAC1E,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,2FAA2F;YACzF,oGAAoG,CACvG,CAAC;IACJ,CAAC;IACD,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;IACtD,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,0CAA0C,CAAC,CAAC;IAC5E,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,0CAA0C,CAAC,CAAC;IAC5E,OAAO;QACL,YAAY,EAAE,KAAK,IAAI,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC;QACtE,YAAY,EAAE,KAAK,IAAI,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC;KACvE,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,UAAU;IACvB,WAAW,KAAK,CAAC,KAAK,IAAI,EAAE;QAC1B,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,IAAI,iBAAiB,CAAC,EAAE,CAAC;QAC7D,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,YAAY,EAAE,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;QAC3F,oEAAoE;QACpE,MAAM,UAAU,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC,CAAC;QACjE,MAAM,UAAU,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC,CAAC;IACpE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE;QACxB,WAAW,GAAG,IAAI,CAAC;QACnB,MAAM,CAAC,CAAC;IACV,CAAC,CAAC,CAAC;IACH,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,IAAI,QAAQ,GAAqB,OAAO,CAAC,OAAO,EAAE,CAAC;AACnD,sEAAsE;AACtE,SAAS,SAAS,CAAI,EAAoB;IACxC,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9B,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACtC,OAAO,GAAG,CAAC;AACb,CAAC;AAED,oFAAoF;AACpF,SAAS,aAAa,CAAC,KAAiB;IACtC,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1C,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAChB,OAAO,IAAI,CAAC,MAAM,CAAC;AACrB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,KAAiB;IAC1C,OAAO,SAAS,CAAC,KAAK,IAAI,EAAE;QAC1B,MAAM,UAAU,EAAE,CAAC;QACnB,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,SAAS,GAAG,QAAQ,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,iBAAiB,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;YAC1D,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC7C,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACnB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAW,CAAC;QAChG,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,QAAQ;gBACR,KAAK,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;aACzC,CAAC;QACb,CAAC;gBAAS,CAAC;YACT,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAID,oEAAoE;AACpE,MAAM,CAAC,MAAM,sBAAsB,GAAsB;IACvD,OAAO,EAAE,EAAE;IACX,QAAQ,EAAE,IAAI;IACd,WAAW,EAAE,KAAK;IAClB,eAAe,EAAE,IAAI;CACtB,CAAC;AAEF,sDAAsD;AACtD,MAAM,UAAU,UAAU,CAAC,KAAmB,EAAE,UAA6B,EAAE;IAC7E,OAAO,SAAS,CAAC,KAAK,IAAI,EAAE;QAC1B,MAAM,UAAU,EAAE,CAAC;QACnB,MAAM,SAAS,GAAG;YAChB,IAAI,EAAE,IAAI,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC;YAC5F,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,UAAU,EAAE,MAAe;SAC5B,CAAC;QACF,MAAM,GAAG,GAAG,MAAM,iBAAiB,CAAC,SAAiC,EAAE;YACrE,GAAG,sBAAsB;YACzB,GAAG,OAAO;SACX,CAAC,CAAC;QACH,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,uEAAuE;AACvE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,CAAC"}