@jax-data-science/sci-image-visualizer 0.11.0 → 0.12.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 (32) hide show
  1. package/esm2022/index.mjs +4 -1
  2. package/esm2022/lib/contracts/image.contract.mjs +1 -1
  3. package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +70 -2
  4. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +2 -2
  5. package/esm2022/lib/implementations/napari-js/napari-volume-region-meshes.mjs +11 -1
  6. package/esm2022/lib/region-editor/region-editor.component.mjs +46 -41
  7. package/esm2022/lib/region-import/label-volume.mjs +35 -4
  8. package/esm2022/lib/region-import/ome-zarr-labels.mjs +253 -0
  9. package/esm2022/lib/region-import/open-annotations.mjs +289 -0
  10. package/esm2022/lib/region-import/zarr-codecs.mjs +167 -0
  11. package/esm2022/lib/region-import/zip.mjs +157 -0
  12. package/esm2022/lib/routing-visualizer.service.mjs +20 -7
  13. package/esm2022/lib/visualizer/region-load.mjs +16 -1
  14. package/fesm2022/{jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BELcx0jv.mjs → jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-a68Hw5rw.mjs} +1050 -50
  15. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-a68Hw5rw.mjs.map +1 -0
  16. package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-DEDSm_NL.mjs → jax-data-science-sci-image-visualizer-onnx-sam-session-CvadfzjS.mjs} +4 -2
  17. package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-DEDSm_NL.mjs.map → jax-data-science-sci-image-visualizer-onnx-sam-session-CvadfzjS.mjs.map} +1 -1
  18. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +3 -1
  19. package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -1
  20. package/index.d.ts +6 -0
  21. package/lib/contracts/image.contract.d.ts +7 -0
  22. package/lib/implementations/napari-js/napari-spatial-3d-scene.d.ts +40 -1
  23. package/lib/implementations/napari-js/napari-volume-region-meshes.d.ts +5 -0
  24. package/lib/region-editor/region-editor.component.d.ts +5 -4
  25. package/lib/region-import/label-volume.d.ts +4 -0
  26. package/lib/region-import/ome-zarr-labels.d.ts +36 -0
  27. package/lib/region-import/open-annotations.d.ts +73 -0
  28. package/lib/region-import/zarr-codecs.d.ts +14 -0
  29. package/lib/region-import/zip.d.ts +31 -0
  30. package/lib/routing-visualizer.service.d.ts +9 -1
  31. package/package.json +2 -1
  32. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BELcx0jv.mjs.map +0 -1
@@ -0,0 +1,157 @@
1
+ const EOCD = 0x06054b50;
2
+ const ZIP64_LOCATOR = 0x07064b50;
3
+ const ZIP64_EOCD = 0x06064b50;
4
+ const CENTRAL = 0x02014b50;
5
+ const LOCAL = 0x04034b50;
6
+ const U32 = 0xffffffff;
7
+ /** Whether a file name is a zip archive. */
8
+ export function isZipName(name) {
9
+ return /\.zip$/i.test(name);
10
+ }
11
+ /** The members of the archive in `bytes` (directories and macOS metadata left out). */
12
+ export function readZip(bytes, inflateRaw = platformInflateRaw) {
13
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
14
+ const eocd = findEocd(view);
15
+ let count = view.getUint16(eocd + 10, true);
16
+ let dirOffset = view.getUint32(eocd + 16, true);
17
+ if (count === 0xffff || dirOffset === U32) {
18
+ const locator = eocd - 20;
19
+ if (locator < 0 || view.getUint32(locator, true) !== ZIP64_LOCATOR)
20
+ throw new Error('zip: ZIP64 locator missing');
21
+ const z64 = num(view, locator + 8);
22
+ if (view.getUint32(z64, true) !== ZIP64_EOCD)
23
+ throw new Error('zip: ZIP64 directory end missing');
24
+ count = num(view, z64 + 32);
25
+ dirOffset = num(view, z64 + 48);
26
+ }
27
+ const entries = [];
28
+ let at = dirOffset;
29
+ for (let i = 0; i < count; i++) {
30
+ if (view.getUint32(at, true) !== CENTRAL)
31
+ throw new Error('zip: bad central directory');
32
+ const flags = view.getUint16(at + 8, true);
33
+ const method = view.getUint16(at + 10, true);
34
+ const crc = view.getUint32(at + 16, true);
35
+ let compressed = view.getUint32(at + 20, true);
36
+ let size = view.getUint32(at + 24, true);
37
+ const nameLen = view.getUint16(at + 28, true);
38
+ const extraLen = view.getUint16(at + 30, true);
39
+ const commentLen = view.getUint16(at + 32, true);
40
+ let local = view.getUint32(at + 42, true);
41
+ const nameBytes = bytes.subarray(at + 46, at + 46 + nameLen);
42
+ const name = (flags & 0x800 ? new TextDecoder() : new TextDecoder('latin1'))
43
+ .decode(nameBytes)
44
+ .replace(/\\/g, '/');
45
+ // ZIP64: the 32-bit fields that overflowed are in the extra field, in this order.
46
+ let x = at + 46 + nameLen;
47
+ const extraEnd = x + extraLen;
48
+ while (x + 4 <= extraEnd) {
49
+ const id = view.getUint16(x, true);
50
+ const len = view.getUint16(x + 2, true);
51
+ if (id === 0x0001) {
52
+ let p = x + 4;
53
+ if (size === U32)
54
+ ((size = num(view, p)), (p += 8));
55
+ if (compressed === U32)
56
+ ((compressed = num(view, p)), (p += 8));
57
+ if (local === U32)
58
+ local = num(view, p);
59
+ }
60
+ x += 4 + len;
61
+ }
62
+ at = extraEnd + commentLen;
63
+ if (name.endsWith('/') || /(^|\/)__MACOSX\//.test(name) || /(^|\/)\.DS_Store$/.test(name))
64
+ continue;
65
+ const entry = { flags, method, crc, compressed, size, local };
66
+ entries.push({ name, size, bytes: () => readMember(bytes, view, name, entry, inflateRaw) });
67
+ }
68
+ return entries;
69
+ }
70
+ /**
71
+ * `files` with every `.zip` among them replaced by its members, named by their paths in it (a
72
+ * single top folder the archive wraps everything in is kept, as a folder pick would keep it).
73
+ */
74
+ export async function expandZips(files, inflateRaw) {
75
+ const out = [];
76
+ for (const file of files) {
77
+ if (!isZipName(file.name)) {
78
+ out.push(file);
79
+ continue;
80
+ }
81
+ for (const entry of readZip(await file.bytes(), inflateRaw)) {
82
+ out.push({
83
+ name: entry.name,
84
+ bytes: () => entry.bytes(),
85
+ text: async () => new TextDecoder().decode(await entry.bytes()),
86
+ });
87
+ }
88
+ }
89
+ return out;
90
+ }
91
+ async function readMember(bytes, view, name, m, inflateRaw) {
92
+ if (m.flags & 0x1)
93
+ throw new Error(`zip: ${name} is encrypted`);
94
+ if (view.getUint32(m.local, true) !== LOCAL)
95
+ throw new Error(`zip: ${name}: bad local header`);
96
+ const start = m.local + 30 + view.getUint16(m.local + 26, true) + view.getUint16(m.local + 28, true);
97
+ const raw = bytes.subarray(start, start + m.compressed);
98
+ if (raw.length !== m.compressed)
99
+ throw new Error(`zip: ${name} is truncated`);
100
+ let out;
101
+ if (m.method === 0)
102
+ out = raw;
103
+ else if (m.method === 8)
104
+ out = await inflateRaw(raw);
105
+ else
106
+ throw new Error(`zip: ${name} uses compression method ${m.method}, not stored or deflate`);
107
+ if (out.length !== m.size)
108
+ throw new Error(`zip: ${name} is ${out.length} bytes, expected ${m.size}`);
109
+ if (crc32(out) !== m.crc)
110
+ throw new Error(`zip: ${name} fails its CRC check`);
111
+ return out;
112
+ }
113
+ /** The end-of-central-directory record: the last one, within the 64 KiB a comment may take. */
114
+ function findEocd(view) {
115
+ const stop = Math.max(0, view.byteLength - 22 - 0xffff);
116
+ for (let at = view.byteLength - 22; at >= stop; at--) {
117
+ if (view.getUint32(at, true) === EOCD)
118
+ return at;
119
+ }
120
+ throw new Error('zip: not a zip archive (no central directory)');
121
+ }
122
+ /** A little-endian u64 that fits a double (archives under 8 PB). */
123
+ function num(view, at) {
124
+ return view.getUint32(at, true) + view.getUint32(at + 4, true) * 0x100000000;
125
+ }
126
+ let crcTable = null;
127
+ /** CRC-32 (IEEE), as zip records it. */
128
+ export function crc32(data) {
129
+ if (!crcTable) {
130
+ crcTable = new Uint32Array(256);
131
+ for (let n = 0; n < 256; n++) {
132
+ let c = n;
133
+ for (let k = 0; k < 8; k++)
134
+ c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
135
+ crcTable[n] = c >>> 0;
136
+ }
137
+ }
138
+ let c = 0xffffffff;
139
+ for (let i = 0; i < data.length; i++)
140
+ c = crcTable[(c ^ data[i]) & 0xff] ^ (c >>> 8);
141
+ return (c ^ 0xffffffff) >>> 0;
142
+ }
143
+ async function platformInflateRaw(bytes) {
144
+ if (typeof DecompressionStream === 'undefined')
145
+ throw new Error('zip: deflated members need DecompressionStream');
146
+ let inflater;
147
+ try {
148
+ // Compression Streams' raw DEFLATE (Chrome 103, Firefox 113, Safari 16.4 on).
149
+ inflater = new DecompressionStream('deflate-raw');
150
+ }
151
+ catch {
152
+ throw new Error('zip: this browser cannot inflate zip members (no DecompressionStream "deflate-raw")');
153
+ }
154
+ const stream = new Blob([bytes]).stream().pipeThrough(inflater);
155
+ return new Uint8Array(await new Response(stream).arrayBuffer());
156
+ }
157
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiemlwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9yZWdpb24taW1wb3J0L3ppcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUF1QkEsTUFBTSxJQUFJLEdBQUcsVUFBVSxDQUFDO0FBQ3hCLE1BQU0sYUFBYSxHQUFHLFVBQVUsQ0FBQztBQUNqQyxNQUFNLFVBQVUsR0FBRyxVQUFVLENBQUM7QUFDOUIsTUFBTSxPQUFPLEdBQUcsVUFBVSxDQUFDO0FBQzNCLE1BQU0sS0FBSyxHQUFHLFVBQVUsQ0FBQztBQUN6QixNQUFNLEdBQUcsR0FBRyxVQUFVLENBQUM7QUFFdkIsNENBQTRDO0FBQzVDLE1BQU0sVUFBVSxTQUFTLENBQUMsSUFBWTtJQUNwQyxPQUFPLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDOUIsQ0FBQztBQUVELHVGQUF1RjtBQUN2RixNQUFNLFVBQVUsT0FBTyxDQUFDLEtBQWlCLEVBQUUsYUFBeUIsa0JBQWtCO0lBQ3BGLE1BQU0sSUFBSSxHQUFHLElBQUksUUFBUSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLFVBQVUsRUFBRSxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDNUUsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzVCLElBQUksS0FBSyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxHQUFHLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUM1QyxJQUFJLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksR0FBRyxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDaEQsSUFBSSxLQUFLLEtBQUssTUFBTSxJQUFJLFNBQVMsS0FBSyxHQUFHLEVBQUUsQ0FBQztRQUMxQyxNQUFNLE9BQU8sR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQzFCLElBQUksT0FBTyxHQUFHLENBQUMsSUFBSSxJ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QUMsQ0FBQztJQUM1RSxPQUFPLElBQUksVUFBVSxDQUFDLE1BQU0sSUFBSSxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztBQUNsRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGUgbWVtYmVycyBvZiBhIGAuemlwYCwgcmVhZCBpbiB0aGUgYnJvd3NlcjogYW5ub3RhdGlvbnMgaGFuZGVkIG92ZXIgYXMgb25lIGFyY2hpdmUgKGEgZm9sZGVyXG4gKiBvZiBwZXItc2xpY2UgR2VvSlNPTiwgYSBsYWJlbCB2b2x1bWUgd2l0aCBpdHMgb250b2xvZ3ksIGFuIE9NRS1aYXJyIHN0b3JlJ3MgbGFiZWxzKS5cbiAqXG4gKiBPbmx5IHdoYXQgc3VjaCBhcmNoaXZlcyB1c2U6IHN0b3JlZCBvciBkZWZsYXRlZCBtZW1iZXJzLCBaSVA2NCBzaXplcyBhbmQgb2Zmc2V0cywgVVRGLTggb3JcbiAqIGxlZ2FjeSBuYW1lcy4gQW4gZW5jcnlwdGVkIG9yIG90aGVyd2lzZSBjb21wcmVzc2VkIG1lbWJlciB0aHJvd3Mgd2hlbiBpdCBpcyByZWFkLCByYXRoZXIgdGhhbiBiZVxuICogcmVhZCB3cm9uZ2x5OyBhIG1lbWJlcidzIENSQy0zMiBpcyBjaGVja2VkLiBNZW1iZXJzIGFyZSByZWFkIG9uIGRlbWFuZCwgc28gYW4gYXJjaGl2ZSBvZiBtYW55XG4gKiBjaHVua3MgKGEgemFyciBzdG9yZSkgaXMgbm90IGluZmxhdGVkIHdob2xlLiBQdXJlOiB1c2FibGUgZnJvbSB3b3JrZXJzLlxuICovXG5pbXBvcnQgdHlwZSB7IFJlZ2lvbkltcG9ydEZpbGUgfSBmcm9tICcuL3JlZ2lvbi1pbXBvcnQnO1xuXG4vKiogT25lIG1lbWJlciBvZiBhbiBhcmNoaXZlLiAqL1xuZXhwb3J0IGludGVyZmFjZSBaaXBFbnRyeSB7XG4gIC8qKiBJdHMgcGF0aCBpbiB0aGUgYXJjaGl2ZSwgJy8nLXNlcGFyYXRlZC4gKi9cbiAgbmFtZTogc3RyaW5nO1xuICAvKiogSXRzIHVuY29tcHJlc3NlZCBzaXplLCBpbiBieXRlcy4gKi9cbiAgc2l6ZTogbnVtYmVyO1xuICBieXRlcygpOiBQcm9taXNlPFVpbnQ4QXJyYXk+O1xufVxuXG4vKiogSW5mbGF0ZSByYXcgREVGTEFURSBkYXRhIChkZWZhdWx0OiB0aGUgcGxhdGZvcm0ncyBgRGVjb21wcmVzc2lvblN0cmVhbSgnZGVmbGF0ZS1yYXcnKWApLiAqL1xuZXhwb3J0IHR5cGUgSW5mbGF0ZVJhdyA9IChieXRlczogVWludDhBcnJheSkgPT4gUHJvbWlzZTxVaW50OEFycmF5PjtcblxuY29uc3QgRU9DRCA9IDB4MDYwNTRiNTA7XG5jb25zdCBaSVA2NF9MT0NBVE9SID0gMHgwNzA2NGI1MDtcbmNvbnN0IFpJUDY0X0VPQ0QgPSAweDA2MDY0YjUwO1xuY29uc3QgQ0VOVFJBTCA9IDB4MDIwMTRiNTA7XG5jb25zdCBMT0NBTCA9IDB4MDQwMzRiNTA7XG5jb25zdCBVMzIgPSAweGZmZmZmZmZmO1xuXG4vKiogV2hldGhlciBhIGZpbGUgbmFtZSBpcyBhIHppcCBhcmNoaXZlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzWmlwTmFtZShuYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIC9cXC56aXAkL2kudGVzdChuYW1lKTtcbn1cblxuLyoqIFRoZSBtZW1iZXJzIG9mIHRoZSBhcmNoaXZlIGluIGBieXRlc2AgKGRpcmVjdG9yaWVzIGFuZCBtYWNPUyBtZXRhZGF0YSBsZWZ0IG91dCkuICovXG5leHBvcnQgZnVuY3Rpb24gcmVhZFppcChieXRlczogVWludDhBcnJheSwgaW5mbGF0ZVJhdzogSW5mbGF0ZVJhdyA9IHBsYXRmb3JtSW5mbGF0ZVJhdyk6IFppcEVudHJ5W10ge1xuICBjb25zdCB2aWV3ID0gbmV3IERhdGFWaWV3KGJ5dGVzLmJ1ZmZlciwgYnl0ZXMuYnl0ZU9mZnNldCwgYnl0ZXMuYnl0ZUxlbmd0aCk7XG4gIGNvbnN0IGVvY2QgPSBmaW5kRW9jZCh2aWV3KTtcbiAgbGV0IGNvdW50ID0gdmlldy5nZXRVaW50MTYoZW9jZCArIDEwLCB0cnVlKTtcbiAgbGV0IGRpck9mZnNldCA9IHZpZXcuZ2V0VWludDMyKGVvY2QgKyAxNiwgdHJ1ZSk7XG4gIGlmIChjb3VudCA9PT0gMHhmZmZmIHx8IGRpck9mZnNldCA9PT0gVTMyKSB7XG4gICAgY29uc3QgbG9jYXRvciA9IGVvY2QgLSAyMDtcbiAgICBpZiAobG9jYXRvciA8IDAgfHwgdmlldy5nZXRVaW50MzIobG9jYXRvciwgdHJ1ZSkgIT09IFpJUDY0X0xPQ0FUT1IpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ppcDogWklQNjQgbG9jYXRvciBtaXNzaW5nJyk7XG4gICAgY29uc3QgejY0ID0gbnVtKHZpZXcsIGxvY2F0b3IgKyA4KTtcbiAgICBpZiAodmlldy5nZXRVaW50MzIoejY0LCB0cnVlKSAhPT0gWklQNjRfRU9DRCkgdGhyb3cgbmV3IEVycm9yKCd6aXA6IFpJUDY0IGRpcmVjdG9yeSBlbmQgbWlzc2luZycpO1xuICAgIGNvdW50ID0gbnVtKHZpZXcsIHo2NCArIDMyKTtcbiAgICBkaXJPZmZzZXQgPSBudW0odmlldywgejY0ICsgNDgpO1xuICB9XG4gIGNvbnN0IGVudHJpZXM6IFppcEVudHJ5W10gPSBbXTtcbiAgbGV0IGF0ID0gZGlyT2Zmc2V0O1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICBpZiAodmlldy5nZXRVaW50MzIoYXQsIHRydWUpICE9PSBDRU5UUkFMKSB0aHJvdyBuZXcgRXJyb3IoJ3ppcDogYmFkIGNlbnRyYWwgZGlyZWN0b3J5Jyk7XG4gICAgY29uc3QgZmxhZ3MgPSB2aWV3LmdldFVpbnQxNihhdCArIDgsIHRydWUpO1xuICAgIGNvbnN0IG1ldGhvZCA9IHZpZXcuZ2V0VWludDE2KGF0ICsgMTAsIHRydWUpO1xuICAgIGNvbnN0IGNyYyA9IHZpZXcuZ2V0VWludDMyKGF0ICsgMTYsIHRydWUpO1xuICAgIGxldCBjb21wcmVzc2VkID0gdmlldy5nZXRVaW50MzIoYXQgKyAyMCwgdHJ1ZSk7XG4gICAgbGV0IHNpemUgPSB2aWV3LmdldFVpbnQzMihhdCArIDI0LCB0cnVlKTtcbiAgICBjb25zdCBuYW1lTGVuID0gdmlldy5nZXRVaW50MTYoYXQgKyAyOCwgdHJ1ZSk7XG4gICAgY29uc3QgZXh0cmFMZW4gPSB2aWV3LmdldFVpbnQxNihhdCArIDMwLCB0cnVlKTtcbiAgICBjb25zdCBjb21tZW50TGVuID0gdmlldy5nZXRVaW50MTYoYXQgKyAzMiwgdHJ1ZSk7XG4gICAgbGV0IGxvY2FsID0gdmlldy5nZXRVaW50MzIoYXQgKyA0MiwgdHJ1ZSk7XG4gICAgY29uc3QgbmFtZUJ5dGVzID0gYnl0ZXMuc3ViYXJyYXkoYXQgKyA0NiwgYXQgKyA0NiArIG5hbWVMZW4pO1xuICAgIGNvbnN0IG5hbWUgPSAoZmxhZ3MgJiAweDgwMCA/IG5ldyBUZXh0RGVjb2RlcigpIDogbmV3IFRleHREZWNvZGVyKCdsYXRpbjEnKSlcbiAgICAgIC5kZWNvZGUobmFtZUJ5dGVzKVxuICAgICAgLnJlcGxhY2UoL1xcXFwvZywgJy8nKTtcbiAgICAvLyBaSVA2NDogdGhlIDMyLWJpdCBmaWVsZHMgdGhhdCBvdmVyZmxvd2VkIGFyZSBpbiB0aGUgZXh0cmEgZmllbGQsIGluIHRoaXMgb3JkZXIuXG4gICAgbGV0IHggPSBhdCArIDQ2ICsgbmFtZUxlbjtcbiAgICBjb25zdCBleHRyYUVuZCA9IHggKyBleHRyYUxlbjtcbiAgICB3aGlsZSAoeCArIDQgPD0gZXh0cmFFbmQpIHtcbiAgICAgIGNvbnN0IGlkID0gdmlldy5nZXRVaW50MTYoeCwgdHJ1ZSk7XG4gICAgICBjb25zdCBsZW4gPSB2aWV3LmdldFVpbnQxNih4ICsgMiwgdHJ1ZSk7XG4gICAgICBpZiAoaWQgPT09IDB4MDAwMSkge1xuICAgICAgICBsZXQgcCA9IHggKyA0O1xuICAgICAgICBpZiAoc2l6ZSA9PT0gVTMyKSAoKHNpemUgPSBudW0odmlldywgcCkpLCAocCArPSA4KSk7XG4gICAgICAgIGlmIChjb21wcmVzc2VkID09PSBVMzIpICgoY29tcHJlc3NlZCA9IG51bSh2aWV3LCBwKSksIChwICs9IDgpKTtcbiAgICAgICAgaWYgKGxvY2FsID09PSBVMzIpIGxvY2FsID0gbnVtKHZpZXcsIHApO1xuICAgICAgfVxuICAgICAgeCArPSA0ICsgbGVuO1xuICAgIH1cbiAgICBhdCA9IGV4dHJhRW5kICsgY29tbWVudExlbjtcbiAgICBpZiAobmFtZS5lbmRzV2l0aCgnLycpIHx8IC8oXnxcXC8pX19NQUNPU1hcXC8vLnRlc3QobmFtZSkgfHwgLyhefFxcLylcXC5EU19TdG9yZSQvLnRlc3QobmFtZSkpIGNvbnRpbnVlO1xuICAgIGNvbnN0IGVudHJ5ID0geyBmbGFncywgbWV0aG9kLCBjcmMsIGNvbXByZXNzZWQsIHNpemUsIGxvY2FsIH07XG4gICAgZW50cmllcy5wdXNoKHsgbmFtZSwgc2l6ZSwgYnl0ZXM6ICgpID0+IHJlYWRNZW1iZXIoYnl0ZXMsIHZpZXcsIG5hbWUsIGVudHJ5LCBpbmZsYXRlUmF3KSB9KTtcbiAgfVxuICByZXR1cm4gZW50cmllcztcbn1cblxuLyoqXG4gKiBgZmlsZXNgIHdpdGggZXZlcnkgYC56aXBgIGFtb25nIHRoZW0gcmVwbGFjZWQgYnkgaXRzIG1lbWJlcnMsIG5hbWVkIGJ5IHRoZWlyIHBhdGhzIGluIGl0IChhXG4gKiBzaW5nbGUgdG9wIGZvbGRlciB0aGUgYXJjaGl2ZSB3cmFwcyBldmVyeXRoaW5nIGluIGlzIGtlcHQsIGFzIGEgZm9sZGVyIHBpY2sgd291bGQga2VlcCBpdCkuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBleHBhbmRaaXBzKFxuICBmaWxlczogcmVhZG9ubHkgUmVnaW9uSW1wb3J0RmlsZVtdLFxuICBpbmZsYXRlUmF3PzogSW5mbGF0ZVJhdyxcbik6IFByb21pc2U8UmVnaW9uSW1wb3J0RmlsZVtdPiB7XG4gIGNvbnN0IG91dDogUmVnaW9uSW1wb3J0RmlsZVtdID0gW107XG4gIGZvciAoY29uc3QgZmlsZSBvZiBmaWxlcykge1xuICAgIGlmICghaXNaaXBOYW1lKGZpbGUubmFtZSkpIHtcbiAgICAgIG91dC5wdXNoKGZpbGUpO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGZvciAoY29uc3QgZW50cnkgb2YgcmVhZFppcChhd2FpdCBmaWxlLmJ5dGVzKCksIGluZmxhdGVSYXcpKSB7XG4gICAgICBvdXQucHVzaCh7XG4gICAgICAgIG5hbWU6IGVudHJ5Lm5hbWUsXG4gICAgICAgIGJ5dGVzOiAoKSA9PiBlbnRyeS5ieXRlcygpLFxuICAgICAgICB0ZXh0OiBhc3luYyAoKSA9PiBuZXcgVGV4dERlY29kZXIoKS5kZWNvZGUoYXdhaXQgZW50cnkuYnl0ZXMoKSksXG4gICAgICB9KTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG91dDtcbn1cblxuaW50ZXJmYWNlIE1lbWJlciB7XG4gIGZsYWdzOiBudW1iZXI7XG4gIG1ldGhvZDogbnVtYmVyO1xuICBjcmM6IG51bWJlcjtcbiAgY29tcHJlc3NlZDogbnVtYmVyO1xuICBzaXplOiBudW1iZXI7XG4gIGxvY2FsOiBudW1iZXI7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlYWRNZW1iZXIoXG4gIGJ5dGVzOiBVaW50OEFycmF5LFxuICB2aWV3OiBEYXRhVmlldyxcbiAgbmFtZTogc3RyaW5nLFxuICBtOiBNZW1iZXIsXG4gIGluZmxhdGVSYXc6IEluZmxhdGVSYXcsXG4pOiBQcm9taXNlPFVpbnQ4QXJyYXk+IHtcbiAgaWYgKG0uZmxhZ3MgJiAweDEpIHRocm93IG5ldyBFcnJvcihgemlwOiAke25hbWV9IGlzIGVuY3J5cHRlZGApO1xuICBpZiAodmlldy5nZXRVaW50MzIobS5sb2NhbCwgdHJ1ZSkgIT09IExPQ0FMKSB0aHJvdyBuZXcgRXJyb3IoYHppcDogJHtuYW1lfTogYmFkIGxvY2FsIGhlYWRlcmApO1xuICBjb25zdCBzdGFydCA9IG0ubG9jYWwgKyAzMCArIHZpZXcuZ2V0VWludDE2KG0ubG9jYWwgKyAyNiwgdHJ1ZSkgKyB2aWV3LmdldFVpbnQxNihtLmxvY2FsICsgMjgsIHRydWUpO1xuICBjb25zdCByYXcgPSBieXRlcy5zdWJhcnJheShzdGFydCwgc3RhcnQgKyBtLmNvbXByZXNzZWQpO1xuICBpZiAocmF3Lmxlbmd0aCAhPT0gbS5jb21wcmVzc2VkKSB0aHJvdyBuZXcgRXJyb3IoYHppcDogJHtuYW1lfSBpcyB0cnVuY2F0ZWRgKTtcbiAgbGV0IG91dDogVWludDhBcnJheTtcbiAgaWYgKG0ubWV0aG9kID09PSAwKSBvdXQgPSByYXc7XG4gIGVsc2UgaWYgKG0ubWV0aG9kID09PSA4KSBvdXQgPSBhd2FpdCBpbmZsYXRlUmF3KHJhdyk7XG4gIGVsc2UgdGhyb3cgbmV3IEVycm9yKGB6aXA6ICR7bmFtZX0gdXNlcyBjb21wcmVzc2lvbiBtZXRob2QgJHttLm1ldGhvZH0sIG5vdCBzdG9yZWQgb3IgZGVmbGF0ZWApO1xuICBpZiAob3V0Lmxlbmd0aCAhPT0gbS5zaXplKSB0aHJvdyBuZXcgRXJyb3IoYHppcDogJHtuYW1lfSBpcyAke291dC5sZW5ndGh9IGJ5dGVzLCBleHBlY3RlZCAke20uc2l6ZX1gKTtcbiAgaWYgKGNyYzMyKG91dCkgIT09IG0uY3JjKSB0aHJvdyBuZXcgRXJyb3IoYHppcDogJHtuYW1lfSBmYWlscyBpdHMgQ1JDIGNoZWNrYCk7XG4gIHJldHVybiBvdXQ7XG59XG5cbi8qKiBUaGUgZW5kLW9mLWNlbnRyYWwtZGlyZWN0b3J5IHJlY29yZDogdGhlIGxhc3Qgb25lLCB3aXRoaW4gdGhlIDY0IEtpQiBhIGNvbW1lbnQgbWF5IHRha2UuICovXG5mdW5jdGlvbiBmaW5kRW9jZCh2aWV3OiBEYXRhVmlldyk6IG51bWJlciB7XG4gIGNvbnN0IHN0b3AgPSBNYXRoLm1heCgwLCB2aWV3LmJ5dGVMZW5ndGggLSAyMiAtIDB4ZmZmZik7XG4gIGZvciAobGV0IGF0ID0gdmlldy5ieXRlTGVuZ3RoIC0gMjI7IGF0ID49IHN0b3A7IGF0LS0pIHtcbiAgICBpZiAodmlldy5nZXRVaW50MzIoYXQsIHRydWUpID09PSBFT0NEKSByZXR1cm4gYXQ7XG4gIH1cbiAgdGhyb3cgbmV3IEVycm9yKCd6aXA6IG5vdCBhIHppcCBhcmNoaXZlIChubyBjZW50cmFsIGRpcmVjdG9yeSknKTtcbn1cblxuLyoqIEEgbGl0dGxlLWVuZGlhbiB1NjQgdGhhdCBmaXRzIGEgZG91YmxlIChhcmNoaXZlcyB1bmRlciA4IFBCKS4gKi9cbmZ1bmN0aW9uIG51bSh2aWV3OiBEYXRhVmlldywgYXQ6IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiB2aWV3LmdldFVpbnQzMihhdCwgdHJ1ZSkgKyB2aWV3LmdldFVpbnQzMihhdCArIDQsIHRydWUpICogMHgxMDAwMDAwMDA7XG59XG5cbmxldCBjcmNUYWJsZTogVWludDMyQXJyYXkgfCBudWxsID0gbnVsbDtcblxuLyoqIENSQy0zMiAoSUVFRSksIGFzIHppcCByZWNvcmRzIGl0LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyYzMyKGRhdGE6IFVpbnQ4QXJyYXkpOiBudW1iZXIge1xuICBpZiAoIWNyY1RhYmxlKSB7XG4gICAgY3JjVGFibGUgPSBuZXcgVWludDMyQXJyYXkoMjU2KTtcbiAgICBmb3IgKGxldCBuID0gMDsgbiA8IDI1NjsgbisrKSB7XG4gICAgICBsZXQgYyA9IG47XG4gICAgICBmb3IgKGxldCBrID0gMDsgayA8IDg7IGsrKykgYyA9IGMgJiAxID8gMHhlZGI4ODMyMCBeIChjID4+PiAxKSA6IGMgPj4+IDE7XG4gICAgICBjcmNUYWJsZVtuXSA9IGMgPj4+IDA7XG4gICAgfVxuICB9XG4gIGxldCBjID0gMHhmZmZmZmZmZjtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSBjID0gY3JjVGFibGVbKGMgXiBkYXRhW2ldKSAmIDB4ZmZdIF4gKGMgPj4+IDgpO1xuICByZXR1cm4gKGMgXiAweGZmZmZmZmZmKSA+Pj4gMDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcGxhdGZvcm1JbmZsYXRlUmF3KGJ5dGVzOiBVaW50OEFycmF5KTogUHJvbWlzZTxVaW50OEFycmF5PiB7XG4gIGlmICh0eXBlb2YgRGVjb21wcmVzc2lvblN0cmVhbSA9PT0gJ3VuZGVmaW5lZCcpXG4gICAgdGhyb3cgbmV3IEVycm9yKCd6aXA6IGRlZmxhdGVkIG1lbWJlcnMgbmVlZCBEZWNvbXByZXNzaW9uU3RyZWFtJyk7XG4gIGxldCBpbmZsYXRlcjogRGVjb21wcmVzc2lvblN0cmVhbTtcbiAgdHJ5IHtcbiAgICAvLyBDb21wcmVzc2lvbiBTdHJlYW1zJyByYXcgREVGTEFURSAoQ2hyb21lIDEwMywgRmlyZWZveCAxMTMsIFNhZmFyaSAxNi40IG9uKS5cbiAgICBpbmZsYXRlciA9IG5ldyBEZWNvbXByZXNzaW9uU3RyZWFtKCdkZWZsYXRlLXJhdycpO1xuICB9IGNhdGNoIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3ppcDogdGhpcyBicm93c2VyIGNhbm5vdCBpbmZsYXRlIHppcCBtZW1iZXJzIChubyBEZWNvbXByZXNzaW9uU3RyZWFtIFwiZGVmbGF0ZS1yYXdcIiknKTtcbiAgfVxuICBjb25zdCBzdHJlYW0gPSBuZXcgQmxvYihbYnl0ZXMgYXMgQmxvYlBhcnRdKS5zdHJlYW0oKS5waXBlVGhyb3VnaChpbmZsYXRlcik7XG4gIHJldHVybiBuZXcgVWludDhBcnJheShhd2FpdCBuZXcgUmVzcG9uc2Uoc3RyZWFtKS5hcnJheUJ1ZmZlcigpKTtcbn1cbiJdfQ==