fable-editor 1.2.7 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,189 @@
1
+ /* Recovers the pictures that desktop Word leaves out of the HTML clipboard flavor.
2
+ Word writes <img src="file:///…/msohtmlclip1/01/clip_image001.png"> — a local temp
3
+ file the browser cannot read — but the same paste also carries a text/rtf flavor
4
+ with every picture embedded as hex inside a {\pict} group. Pairing the two is how
5
+ TinyMCE PowerPaste implements powerpaste_allow_local_images.
6
+
7
+ This runs on the RAW html string BEFORE cleanPastedHTML() sees it: the paste engine
8
+ already allows data: URIs, so it needs no change and its behaviour is unaffected.
9
+ Anything this module cannot recover is left exactly as it was, and still ends up on
10
+ the engine's existing "[local image — paste it separately]" placeholder. */
11
+ /** Total decoded bytes we are willing to inline from one paste. A Word document full
12
+ * of full-page screenshots can run to tens of MB; past this we leave the placeholders
13
+ * rather than freeze the editor building base64 strings. */
14
+ const MAX_TOTAL_BYTES = 10 * 1024 * 1024;
15
+ const USABLE_SRC = /^(https?:|data:image\/|blob:)/i;
16
+ /** Scans for `{\keyword …}` groups, tracking brace depth so nested groups such as
17
+ * `{\*\picprop …}` inside a picture do not terminate the match early (a lazy
18
+ * `/\{\\pict[\s\S]*?\}/` regex gets this wrong and truncates the hex payload). */
19
+ function findGroups(rtf, keyword) {
20
+ const out = [];
21
+ const needle = '{\\' + keyword;
22
+ let i = 0;
23
+ while ((i = rtf.indexOf(needle, i)) !== -1) {
24
+ /* the char after the control word must be a delimiter, so \pict does not also
25
+ match \pictscalex and friends */
26
+ const after = rtf[i + needle.length];
27
+ if (after && /[a-z0-9]/i.test(after)) {
28
+ i += needle.length;
29
+ continue;
30
+ }
31
+ let depth = 0;
32
+ let j = i;
33
+ for (; j < rtf.length; j++) {
34
+ const c = rtf[j];
35
+ if (c === '\\') {
36
+ j++;
37
+ continue;
38
+ }
39
+ if (c === '{')
40
+ depth++;
41
+ else if (c === '}') {
42
+ depth--;
43
+ if (!depth)
44
+ break;
45
+ }
46
+ }
47
+ out.push({ start: i, end: j + 1, body: rtf.slice(i + needle.length, j) });
48
+ i = j + 1;
49
+ }
50
+ return out;
51
+ }
52
+ function hexToBytes(hex) {
53
+ const bytes = new Uint8Array(hex.length / 2);
54
+ for (let i = 0; i < bytes.length; i++)
55
+ bytes[i] = parseInt(hex.substr(i * 2, 2), 16);
56
+ return bytes;
57
+ }
58
+ function toBase64(bytes) {
59
+ let bin = '';
60
+ for (let i = 0; i < bytes.length; i++)
61
+ bin += String.fromCharCode(bytes[i]);
62
+ return btoa(bin);
63
+ }
64
+ function indexOfSig(bytes, sig) {
65
+ outer: for (let i = 0; i + sig.length <= bytes.length; i++) {
66
+ for (let j = 0; j < sig.length; j++)
67
+ if (bytes[i + j] !== sig[j])
68
+ continue outer;
69
+ return i;
70
+ }
71
+ return -1;
72
+ }
73
+ const PNG_SIG = [0x89, 0x50, 0x4e, 0x47];
74
+ const JPG_SIG = [0xff, 0xd8, 0xff];
75
+ function decodePict(body) {
76
+ let kind = null;
77
+ if (/\\pngblip/.test(body))
78
+ kind = 'image/png';
79
+ else if (/\\jpegblip/.test(body))
80
+ kind = 'image/jpeg';
81
+ else if (/\\wmetafile\d*/.test(body) || /\\emfblip/.test(body))
82
+ kind = 'metafile';
83
+ if (!kind)
84
+ return null;
85
+ let hex = body
86
+ .replace(/\{[^{}]*\}/g, '') // nested property groups
87
+ .replace(/\\[a-z]+-?\d*\s?/gi, '') // control words
88
+ .replace(/[^0-9a-fA-F]/g, '');
89
+ if (hex.length % 2)
90
+ hex = hex.slice(0, -1);
91
+ if (!hex)
92
+ return null;
93
+ const bytes = hexToBytes(hex);
94
+ if (kind === 'metafile') {
95
+ /* Word wraps a bitmap in a metafile for compatibility; when there is a real
96
+ PNG/JPEG inside we can use it. A genuine vector metafile we cannot render. */
97
+ const png = indexOfSig(bytes, PNG_SIG);
98
+ if (png >= 0)
99
+ return 'data:image/png;base64,' + toBase64(bytes.slice(png));
100
+ const jpg = indexOfSig(bytes, JPG_SIG);
101
+ if (jpg >= 0)
102
+ return 'data:image/jpeg;base64,' + toBase64(bytes.slice(jpg));
103
+ return null;
104
+ }
105
+ return 'data:' + kind + ';base64,' + toBase64(bytes);
106
+ }
107
+ /** Every picture in the RTF flavor, in document order. */
108
+ export function extractRtfImages(rtf) {
109
+ if (!rtf || rtf.indexOf('\\pict') === -1)
110
+ return [];
111
+ /* Word emits {\*\shppict{\pict …}}{\nonshppict{\pict …}} — the second group is a
112
+ legacy duplicate of the first. Dropping it keeps picture order aligned with the
113
+ <img> tags in the HTML flavor. */
114
+ let cleaned = rtf;
115
+ findGroups(rtf, 'nonshppict')
116
+ .reverse()
117
+ .forEach((g) => {
118
+ cleaned = cleaned.slice(0, g.start) + cleaned.slice(g.end);
119
+ });
120
+ let budget = MAX_TOTAL_BYTES;
121
+ return findGroups(cleaned, 'pict').map((g) => {
122
+ if (budget <= 0)
123
+ return null;
124
+ const data = decodePict(g.body);
125
+ if (data)
126
+ budget -= data.length * 0.75; // base64 -> approximate byte count
127
+ return data;
128
+ });
129
+ }
130
+ /** Rewrites unusable <img src> values in raw pasted HTML with the pictures given, in
131
+ * document order. Images that already have a usable src are left alone and do not
132
+ * consume a slot, so a mixed paste (webmail image + Word image) stays aligned.
133
+ * Anything without a matching picture keeps its original tag. */
134
+ export function injectImages(html, imgs) {
135
+ if (!html || !imgs.length)
136
+ return { html, injected: [] };
137
+ const injected = [];
138
+ let next = 0;
139
+ const out = html.replace(/<img\b[^>]*>/gi, (tag) => {
140
+ const src = (tag.match(/\ssrc\s*=\s*["']?([^"'\s>]+)/i) || [])[1] || '';
141
+ if (USABLE_SRC.test(src))
142
+ return tag;
143
+ const data = imgs[next++];
144
+ if (!data)
145
+ return tag;
146
+ injected.push(data);
147
+ return /\ssrc\s*=\s*["']/i.test(tag)
148
+ ? tag.replace(/(\ssrc\s*=\s*)(["'])[^"']*\2/i, '$1"' + data + '"')
149
+ : tag.replace(/(\ssrc\s*=\s*)[^\s>]+/i, '$1"' + data + '"');
150
+ });
151
+ return { html: out, injected };
152
+ }
153
+ /** Pairs the HTML flavor of a Word paste with the pictures in its RTF flavor. */
154
+ export function injectRtfImages(html, rtf) {
155
+ if (!html || !rtf)
156
+ return { html, injected: [] };
157
+ return injectImages(html, extractRtfImages(rtf));
158
+ }
159
+ /** True when the cleaned HTML still holds images the engine could not resolve — used
160
+ * to decide whether a bitmap sitting in the clipboard is worth falling back to. */
161
+ export function countUnresolvedImages(html) {
162
+ const tags = html.match(/<img\b[^>]*>/gi);
163
+ if (!tags)
164
+ return 0;
165
+ return tags.filter((tag) => {
166
+ const src = (tag.match(/\ssrc\s*=\s*["']?([^"'\s>]+)/i) || [])[1] || '';
167
+ return !USABLE_SRC.test(src);
168
+ }).length;
169
+ }
170
+ /** data: URI -> File, so recovered pictures can go through the host's
171
+ * imageUploadHandler exactly like a picked file does. `baseName` gets the extension
172
+ * that matches the URI's MIME type. */
173
+ export function dataUrlToFile(dataUrl, baseName) {
174
+ const m = dataUrl.match(/^data:([^;,]+);base64,(.*)$/);
175
+ if (!m)
176
+ return null;
177
+ const ext = (m[1].split('/')[1] || 'png').replace(/[^a-z0-9]/gi, '') || 'png';
178
+ try {
179
+ const bin = atob(m[2]);
180
+ const bytes = new Uint8Array(bin.length);
181
+ for (let i = 0; i < bin.length; i++)
182
+ bytes[i] = bin.charCodeAt(i);
183
+ return new File([bytes], baseName + '.' + (ext === 'jpeg' ? 'jpg' : ext), { type: m[1] });
184
+ }
185
+ catch (e) {
186
+ return null;
187
+ }
188
+ }
189
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29yZC1pbWFnZS1wYXN0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb3JlL3dvcmQtaW1hZ2UtcGFzdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs4RUFTOEU7QUFNOUU7OzZEQUU2RDtBQUM3RCxNQUFNLGVBQWUsR0FBRyxFQUFFLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQztBQUV6QyxNQUFNLFVBQVUsR0FBRyxnQ0FBZ0MsQ0FBQztBQUVwRDs7bUZBRW1GO0FBQ25GLFNBQVMsVUFBVSxDQUFDLEdBQVcsRUFBRSxPQUFlO0lBQzlDLE1BQU0sR0FBRyxHQUFtRCxFQUFFLENBQUM7SUFDL0QsTUFBTSxNQUFNLEdBQUcsS0FBSyxHQUFHLE9BQU8sQ0FBQztJQUMvQixJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDVixPQUFPLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUMzQzsyQ0FDbUM7UUFDbkMsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLENBQUMsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDckMsSUFBSSxLQUFLLElBQUksV0FBVyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3JDLENBQUMsSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDO1lBQ25CLFNBQVM7UUFDWCxDQUFDO1FBQ0QsSUFBSSxLQUFLLEdBQUcsQ0FBQyxDQUFDO1FBQ2QsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ1YsT0FBTyxDQUFDLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQzNCLE1BQU0sQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNqQixJQUFJLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FB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LENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbEUsT0FBTyxJQUFJLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFFLFFBQVEsR0FBRyxHQUFHLEdBQUcsQ0FBQyxHQUFHLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDNUYsQ0FBQztJQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDWCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogUmVjb3ZlcnMgdGhlIHBpY3R1cmVzIHRoYXQgZGVza3RvcCBXb3JkIGxlYXZlcyBvdXQgb2YgdGhlIEhUTUwgY2xpcGJvYXJkIGZsYXZvci5cbiAgIFdvcmQgd3JpdGVzIDxpbWcgc3JjPVwiZmlsZTovLy/igKYvbXNvaHRtbGNsaXAxLzAxL2NsaXBfaW1hZ2UwMDEucG5nXCI+IOKAlCBhIGxvY2FsIHRlbXBcbiAgIGZpbGUgdGhlIGJyb3dzZXIgY2Fubm90IHJlYWQg4oCUIGJ1dCB0aGUgc2FtZSBwYXN0ZSBhbHNvIGNhcnJpZXMgYSB0ZXh0L3J0ZiBmbGF2b3JcbiAgIHdpdGggZXZlcnkgcGljdHVyZSBlbWJlZGRlZCBhcyBoZXggaW5zaWRlIGEge1xccGljdH0gZ3JvdXAuIFBhaXJpbmcgdGhlIHR3byBpcyBob3dcbiAgIFRpbnlNQ0UgUG93ZXJQYXN0ZSBpbXBsZW1lbnRzIHBvd2VycGFzdGVfYWxsb3dfbG9jYWxfaW1hZ2VzLlxuXG4gICBUaGlzIHJ1bnMgb24gdGhlIFJBVyBodG1sIHN0cmluZyBCRUZPUkUgY2xlYW5QYXN0ZWRIVE1MKCkgc2VlcyBpdDogdGhlIHBhc3RlIGVuZ2luZVxuICAgYWxyZWFkeSBhbGxvd3MgZGF0YTogVVJJcywgc28gaXQgbmVlZHMgbm8gY2hhbmdlIGFuZCBpdHMgYmVoYXZpb3VyIGlzIHVuYWZmZWN0ZWQuXG4gICBBbnl0aGluZyB0aGlzIG1vZHVsZSBjYW5ub3QgcmVjb3ZlciBpcyBsZWZ0IGV4YWN0bHkgYXMgaXQgd2FzLCBhbmQgc3RpbGwgZW5kcyB1cCBvblxuICAgdGhlIGVuZ2luZSdzIGV4aXN0aW5nIFwiW2xvY2FsIGltYWdlIOKAlCBwYXN0ZSBpdCBzZXBhcmF0ZWx5XVwiIHBsYWNlaG9sZGVyLiAqL1xuXG4vKiogRGVjb2RlZCBwaWN0dXJlcyBpbiBkb2N1bWVudCBvcmRlci4gQSBzbG90IGlzIG51bGwgd2hlbiB0aGUgcGljdHVyZSBleGlzdHMgYnV0XG4gKiAgY2Fubm90IGJlIHR1cm5lZCBpbnRvIHNvbWV0aGluZyB0aGUgYnJvd3NlciBjYW4gc2hvdyAoYSB0cnVlIHZlY3RvciBtZXRhZmlsZSkuICovXG5leHBvcnQgdHlwZSBSdGZJbWFnZXMgPSAoc3RyaW5nIHwgbnVsbClbXTtcblxuLyoqIFRvdGFsIGRlY29kZWQgYnl0ZXMgd2UgYXJlIHdpbGxpbmcgdG8gaW5saW5lIGZyb20gb25lIHBhc3RlLiBBIFdvcmQgZG9jdW1lbnQgZnVsbFxuICogIG9mIGZ1bGwtcGFnZSBzY3JlZW5zaG90cyBjYW4gcnVuIHRvIHRlbnMgb2YgTUI7IHBhc3QgdGhpcyB3ZSBsZWF2ZSB0aGUgcGxhY2Vob2xkZXJzXG4gKiAgcmF0aGVyIHRoYW4gZnJlZXplIHRoZSBlZGl0b3IgYnVpbGRpbmcgYmFzZTY0IHN0cmluZ3MuICovXG5jb25zdCBNQVhfVE9UQUxfQllURVMgPSAxMCAqIDEwMjQgKiAxMDI0O1xuXG5jb25zdCBVU0FCTEVfU1JDID0gL14oaHR0cHM/OnxkYXRhOmltYWdlXFwvfGJsb2I6KS9pO1xuXG4vKiogU2NhbnMgZm9yIGB7XFxrZXl3b3JkIOKApn1gIGdyb3VwcywgdHJhY2tpbmcgYnJhY2UgZGVwdGggc28gbmVzdGVkIGdyb3VwcyBzdWNoIGFzXG4gKiAgYHtcXCpcXHBpY3Byb3Ag4oCmfWAgaW5zaWRlIGEgcGljdHVyZSBkbyBub3QgdGVybWluYXRlIHRoZSBtYXRjaCBlYXJseSAoYSBsYXp5XG4gKiAgYC9cXHtcXFxccGljdFtcXHNcXFNdKj9cXH0vYCByZWdleCBnZXRzIHRoaXMgd3JvbmcgYW5kIHRydW5jYXRlcyB0aGUgaGV4IHBheWxvYWQpLiAqL1xuZnVuY3Rpb24gZmluZEdyb3VwcyhydGY6IHN0cmluZywga2V5d29yZDogc3RyaW5nKTogeyBzdGFydDogbnVtYmVyOyBlbmQ6IG51bWJlcjsgYm9keTogc3RyaW5nIH1bXSB7XG4gIGNvbnN0IG91dDogeyBzdGFydDogbnVtYmVyOyBlbmQ6IG51bWJlcjsgYm9keTogc3RyaW5nIH1bXSA9IFtdO1xuICBjb25zdCBuZWVkbGUgPSAne1xcXFwnICsga2V5d29yZDtcbiAgbGV0IGkgPSAwO1xuICB3aGlsZSAoKGkgPSBydGYuaW5kZXhPZihuZWVkbGUsIGkpKSAhPT0gLTEpIHtcbiAgICAvKiB0aGUgY2hhciBhZnRlciB0aGUgY29udHJvbCB3b3JkIG11c3QgYmUgYSBkZWxpbWl0ZXIsIHNvIFxccGljdCBkb2VzIG5vdCBhbHNvXG4gICAgICAgbWF0Y2ggXFxwaWN0c2NhbGV4IGFuZCBmcmllbmRzICovXG4gICAgY29uc3QgYWZ0ZXIgPSBydGZbaSArIG5lZWRsZS5sZW5ndGhdO1xuICAgIGlmIChhZnRlciAmJiAvW2EtejAtOV0vaS50ZXN0KGFmdGVyKSkge1xuICAgICAgaSArPSBuZWVkbGUubGVuZ3RoO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGxldCBkZXB0aCA9IDA7XG4gICAgbGV0IGogPSBpO1xuICAgIGZvciAoOyBqIDwgcnRmLmxlbmd0aDsgaisrKSB7XG4gICAgICBjb25zdCBjID0gcnRmW2pdO1xuICAgICAgaWYgKGMgPT09ICdcXFxcJykge1xuICAgICAgICBqKys7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaWYgKGMgPT09ICd7JykgZGVwdGgrKztcbiAgICAgIGVsc2UgaWYgKGMgPT09ICd9Jykge1xuICAgICAgICBkZXB0aC0tO1xuICAgICAgICBpZiAoIWRlcHRoKSBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgb3V0LnB1c2goeyBzdGFydDogaSwgZW5kOiBqICsgMSwgYm9keTogcnRmLnNsaWNlKGkgKyBuZWVkbGUubGVuZ3RoLCBqKSB9KTtcbiAgICBpID0gaiArIDE7XG4gIH1cbiAgcmV0dXJuIG91dDtcbn1cblxuZnVuY3Rpb24gaGV4VG9CeXRlcyhoZXg6IHN0cmluZyk6IFVpbnQ4QXJyYXkge1xuICBjb25zdCBieXRlcyA9IG5ldyBVaW50OEFycmF5KGhleC5sZW5ndGggLyAyKTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkrKykgYnl0ZXNbaV0gPSBwYXJzZUludChoZXguc3Vic3RyKGkgKiAyLCAyKSwgMTYpO1xuICByZXR1cm4gYnl0ZXM7XG59XG5cbmZ1bmN0aW9uIHRvQmFzZTY0KGJ5dGVzOiBVaW50OEFycmF5KTogc3RyaW5nIHtcbiAgbGV0IGJpbiA9ICcnO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGJ5dGVzLmxlbmd0aDsgaSsrKSBiaW4gKz0gU3RyaW5nLmZyb21DaGFyQ29kZShieXRlc1tpXSk7XG4gIHJldHVybiBidG9hKGJpbik7XG59XG5cbmZ1bmN0aW9uIGluZGV4T2ZTaWcoYnl0ZXM6IFVpbnQ4QXJyYXksIHNpZzogbnVtYmVyW10pOiBudW1iZXIge1xuICBvdXRlcjogZm9yIChsZXQgaSA9IDA7IGkgKyBzaWcubGVuZ3RoIDw9IGJ5dGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBzaWcubGVuZ3RoOyBqKyspIGlmIChieXRlc1tpICsgal0gIT09IHNpZ1tqXSkgY29udGludWUgb3V0ZXI7XG4gICAgcmV0dXJuIGk7XG4gIH1cbiAgcmV0dXJuIC0xO1xufVxuXG5jb25zdCBQTkdfU0lHID0gWzB4ODksIDB4NTAsIDB4NGUsIDB4NDddO1xuY29uc3QgSlBHX1NJRyA9IFsweGZmLCAweGQ4LCAweGZmXTtcblxuZnVuY3Rpb24gZGVjb2RlUGljdChib2R5OiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsIHtcbiAgbGV0IGtpbmQ6ICdpbWFnZS9wbmcnIHwgJ2ltYWdlL2pwZWcnIHwgJ21ldGFmaWxlJyB8IG51bGwgPSBudWxsO1xuICBpZiAoL1xcXFxwbmdibGlwLy50ZXN0KGJvZHkpKSBraW5kID0gJ2ltYWdlL3BuZyc7XG4gIGVsc2UgaWYgKC9cXFxcanBlZ2JsaXAvLnRlc3QoYm9keSkpIGtpbmQgPSAnaW1hZ2UvanBlZyc7XG4gIGVsc2UgaWYgKC9cXFxcd21ldGFmaWxlXFxkKi8udGVzdChib2R5KSB8fCAvXFxcXGVtZmJsaXAvLnRlc3QoYm9keSkpIGtpbmQgPSAnbWV0YWZpbGUnO1xuICBpZiAoIWtpbmQpIHJldHVybiBudWxsO1xuXG4gIGxldCBoZXggPSBib2R5XG4gICAgLnJlcGxhY2UoL1xce1tee31dKlxcfS9nLCAnJykgLy8gbmVzdGVkIHByb3BlcnR5IGdyb3Vwc1xuICAgIC5yZXBsYWNlKC9cXFxcW2Etel0rLT9cXGQqXFxzPy9naSwgJycpIC8vIGNvbnRyb2wgd29yZHNcbiAgICAucmVwbGFjZSgvW14wLTlhLWZBLUZdL2csICcnKTtcbiAgaWYgKGhleC5sZW5ndGggJSAyKSBoZXggPSBoZXguc2xpY2UoMCwgLTEpO1xuICBpZiAoIWhleCkgcmV0dXJuIG51bGw7XG5cbiAgY29uc3QgYnl0ZXMgPSBoZXhUb0J5dGVzKGhleCk7XG4gIGlmIChraW5kID09PSAnbWV0YWZpbGUnKSB7XG4gICAgLyogV29yZCB3cmFwcyBhIGJpdG1hcCBpbiBhIG1ldGFmaWxlIGZvciBjb21wYXRpYmlsaXR5OyB3aGVuIHRoZXJlIGlzIGEgcmVhbFxuICAgICAgIFBORy9KUEVHIGluc2lkZSB3ZSBjYW4gdXNlIGl0LiBBIGdlbnVpbmUgdmVjdG9yIG1ldGFmaWxlIHdlIGNhbm5vdCByZW5kZXIuICovXG4gICAgY29uc3QgcG5nID0gaW5kZXhPZlNpZyhieXRlcywgUE5HX1NJRyk7XG4gICAgaWYgKHBuZyA+PSAwKSByZXR1cm4gJ2RhdGE6aW1hZ2UvcG5nO2Jhc2U2NCwnICsgdG9CYXNlNjQoYnl0ZXMuc2xpY2UocG5nKSk7XG4gICAgY29uc3QganBnID0gaW5kZXhPZlNpZyhieXRlcywgSlBHX1NJRyk7XG4gICAgaWYgKGpwZyA+PSAwKSByZXR1cm4gJ2RhdGE6aW1hZ2UvanBlZztiYXNlNjQsJyArIHRvQmFzZTY0KGJ5dGVzLnNsaWNlKGpwZykpO1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIHJldHVybiAnZGF0YTonICsga2luZCArICc7YmFzZTY0LCcgKyB0b0Jhc2U2NChieXRlcyk7XG59XG5cbi8qKiBFdmVyeSBwaWN0dXJlIGluIHRoZSBSVEYgZmxhdm9yLCBpbiBkb2N1bWVudCBvcmRlci4gKi9cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0UnRmSW1hZ2VzKHJ0Zjogc3RyaW5nKTogUnRmSW1hZ2VzIHtcbiAgaWYgKCFydGYgfHwgcnRmLmluZGV4T2YoJ1xcXFxwaWN0JykgPT09IC0xKSByZXR1cm4gW107XG4gIC8qIFdvcmQgZW1pdHMge1xcKlxcc2hwcGljdHtcXHBpY3Qg4oCmfX17XFxub25zaHBwaWN0e1xccGljdCDigKZ9fSDigJQgdGhlIHNlY29uZCBncm91cCBpcyBhXG4gICAgIGxlZ2FjeSBkdXBsaWNhdGUgb2YgdGhlIGZpcnN0LiBEcm9wcGluZyBpdCBrZWVwcyBwaWN0dXJlIG9yZGVyIGFsaWduZWQgd2l0aCB0aGVcbiAgICAgPGltZz4gdGFncyBpbiB0aGUgSFRNTCBmbGF2b3IuICovXG4gIGxldCBjbGVhbmVkID0gcnRmO1xuICBmaW5kR3JvdXBzKHJ0ZiwgJ25vbnNocHBpY3QnKVxuICAgIC5yZXZlcnNlKClcbiAgICAuZm9yRWFjaCgoZykgPT4ge1xuICAgICAgY2xlYW5lZCA9IGNsZWFuZWQuc2xpY2UoMCwgZy5zdGFydCkgKyBjbGVhbmVkLnNsaWNlKGcuZW5kKTtcbiAgICB9KTtcblxuICBsZXQgYnVkZ2V0ID0gTUFYX1RPVEFMX0JZVEVTO1xuICByZXR1cm4gZmluZEdyb3VwcyhjbGVhbmVkLCAncGljdCcpLm1hcCgoZykgPT4ge1xuICAgIGlmIChidWRnZXQgPD0gMCkgcmV0dXJuIG51bGw7XG4gICAgY29uc3QgZGF0YSA9IGRlY29kZVBpY3QoZy5ib2R5KTtcbiAgICBpZiAoZGF0YSkgYnVkZ2V0IC09IGRhdGEubGVuZ3RoICogMC43NTsgLy8gYmFzZTY0IC0+IGFwcHJveGltYXRlIGJ5dGUgY291bnRcbiAgICByZXR1cm4gZGF0YTtcbiAgfSk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSW5qZWN0UmVzdWx0IHtcbiAgaHRtbDogc3RyaW5nO1xuICAvKiogVGhlIGRhdGEgVVJJcyB0aGlzIGNhbGwgcHV0IGludG8gdGhlIEhUTUwsIGluIHRoZSBvcmRlciB0aGV5IHdlcmUgdXNlZC4gT25seVxuICAgKiAgdGhlc2UgYXJlIGNhbmRpZGF0ZXMgZm9yIHRoZSBob3N0J3MgaW1hZ2VVcGxvYWRIYW5kbGVyIOKAlCBkYXRhIFVSSXMgdGhhdCB3ZXJlXG4gICAqICBhbHJlYWR5IGluIHRoZSBwYXN0ZWQgSFRNTCBhcmUgbGVmdCBhbG9uZSwgc28gZXhpc3RpbmcgcGFzdGUgYmVoYXZpb3VyIGlzXG4gICAqICB1bmNoYW5nZWQuICovXG4gIGluamVjdGVkOiBzdHJpbmdbXTtcbn1cblxuLyoqIFJld3JpdGVzIHVudXNhYmxlIDxpbWcgc3JjPiB2YWx1ZXMgaW4gcmF3IHBhc3RlZCBIVE1MIHdpdGggdGhlIHBpY3R1cmVzIGdpdmVuLCBpblxuICogIGRvY3VtZW50IG9yZGVyLiBJbWFnZXMgdGhhdCBhbHJlYWR5IGhhdmUgYSB1c2FibGUgc3JjIGFyZSBsZWZ0IGFsb25lIGFuZCBkbyBub3RcbiAqICBjb25zdW1lIGEgc2xvdCwgc28gYSBtaXhlZCBwYXN0ZSAod2VibWFpbCBpbWFnZSArIFdvcmQgaW1hZ2UpIHN0YXlzIGFsaWduZWQuXG4gKiAgQW55dGhpbmcgd2l0aG91dCBhIG1hdGNoaW5nIHBpY3R1cmUga2VlcHMgaXRzIG9yaWdpbmFsIHRhZy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmplY3RJbWFnZXMoaHRtbDogc3RyaW5nLCBpbWdzOiBSdGZJbWFnZXMpOiBJbmplY3RSZXN1bHQge1xuICBpZiAoIWh0bWwgfHwgIWltZ3MubGVuZ3RoKSByZXR1cm4geyBodG1sLCBpbmplY3RlZDogW10gfTtcbiAgY29uc3QgaW5qZWN0ZWQ6IHN0cmluZ1tdID0gW107XG4gIGxldCBuZXh0ID0gMDtcbiAgY29uc3Qgb3V0ID0gaHRtbC5yZXBsYWNlKC88aW1nXFxiW14+XSo+L2dpLCAodGFnKSA9PiB7XG4gICAgY29uc3Qgc3JjID0gKHRhZy5tYXRjaCgvXFxzc3JjXFxzKj1cXHMqW1wiJ10/KFteXCInXFxzPl0rKS9pKSB8fCBbXSlbMV0gfHwgJyc7XG4gICAgaWYgKFVTQUJMRV9TUkMudGVzdChzcmMpKSByZXR1cm4gdGFnO1xuICAgIGNvbnN0IGRhdGEgPSBpbWdzW25leHQrK107XG4gICAgaWYgKCFkYXRhKSByZXR1cm4gdGFnO1xuICAgIGluamVjdGVkLnB1c2goZGF0YSk7XG4gICAgcmV0dXJuIC9cXHNzcmNcXHMqPVxccypbXCInXS9pLnRlc3QodGFnKVxuICAgICAgPyB0YWcucmVwbGFjZSgvKFxcc3NyY1xccyo9XFxzKikoW1wiJ10pW15cIiddKlxcMi9pLCAnJDFcIicgKyBkYXRhICsgJ1wiJylcbiAgICAgIDogdGFnLnJlcGxhY2UoLyhcXHNzcmNcXHMqPVxccyopW15cXHM+XSsvaSwgJyQxXCInICsgZGF0YSArICdcIicpO1xuICB9KTtcbiAgcmV0dXJuIHsgaHRtbDogb3V0LCBpbmplY3RlZCB9O1xufVxuXG4vKiogUGFpcnMgdGhlIEhUTUwgZmxhdm9yIG9mIGEgV29yZCBwYXN0ZSB3aXRoIHRoZSBwaWN0dXJlcyBpbiBpdHMgUlRGIGZsYXZvci4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmplY3RSdGZJbWFnZXMoaHRtbDogc3RyaW5nLCBydGY6IHN0cmluZyk6IEluamVjdFJlc3VsdCB7XG4gIGlmICghaHRtbCB8fCAhcnRmKSByZXR1cm4geyBodG1sLCBpbmplY3RlZDogW10gfTtcbiAgcmV0dXJuIGluamVjdEltYWdlcyhodG1sLCBleHRyYWN0UnRmSW1hZ2VzKHJ0ZikpO1xufVxuXG4vKiogVHJ1ZSB3aGVuIHRoZSBjbGVhbmVkIEhUTUwgc3RpbGwgaG9sZHMgaW1hZ2VzIHRoZSBlbmdpbmUgY291bGQgbm90IHJlc29sdmUg4oCUIHVzZWRcbiAqICB0byBkZWNpZGUgd2hldGhlciBhIGJpdG1hcCBzaXR0aW5nIGluIHRoZSBjbGlwYm9hcmQgaXMgd29ydGggZmFsbGluZyBiYWNrIHRvLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvdW50VW5yZXNvbHZlZEltYWdlcyhodG1sOiBzdHJpbmcpOiBudW1iZXIge1xuICBjb25zdCB0YWdzID0gaHRtbC5tYXRjaCgvPGltZ1xcYltePl0qPi9naSk7XG4gIGlmICghdGFncykgcmV0dXJuIDA7XG4gIHJldHVybiB0YWdzLmZpbHRlcigodGFnKSA9PiB7XG4gICAgY29uc3Qgc3JjID0gKHRhZy5tYXRjaCgvXFxzc3JjXFxzKj1cXHMqW1wiJ10/KFteXCInXFxzPl0rKS9pKSB8fCBbXSlbMV0gfHwgJyc7XG4gICAgcmV0dXJuICFVU0FCTEVfU1JDLnRlc3Qoc3JjKTtcbiAgfSkubGVuZ3RoO1xufVxuXG4vKiogZGF0YTogVVJJIC0+IEZpbGUsIHNvIHJlY292ZXJlZCBwaWN0dXJlcyBjYW4gZ28gdGhyb3VnaCB0aGUgaG9zdCdzXG4gKiAgaW1hZ2VVcGxvYWRIYW5kbGVyIGV4YWN0bHkgbGlrZSBhIHBpY2tlZCBmaWxlIGRvZXMuIGBiYXNlTmFtZWAgZ2V0cyB0aGUgZXh0ZW5zaW9uXG4gKiAgdGhhdCBtYXRjaGVzIHRoZSBVUkkncyBNSU1FIHR5cGUuICovXG5leHBvcnQgZnVuY3Rpb24gZGF0YVVybFRvRmlsZShkYXRhVXJsOiBzdHJpbmcsIGJhc2VOYW1lOiBzdHJpbmcpOiBGaWxlIHwgbnVsbCB7XG4gIGNvbnN0IG0gPSBkYXRhVXJsLm1hdGNoKC9eZGF0YTooW147LF0rKTtiYXNlNjQsKC4qKSQvKTtcbiAgaWYgKCFtKSByZXR1cm4gbnVsbDtcbiAgY29uc3QgZXh0ID0gKG1bMV0uc3BsaXQoJy8nKVsxXSB8fCAncG5nJykucmVwbGFjZSgvW15hLXowLTldL2dpLCAnJykgfHwgJ3BuZyc7XG4gIHRyeSB7XG4gICAgY29uc3QgYmluID0gYXRvYihtWzJdKTtcbiAgICBjb25zdCBieXRlcyA9IG5ldyBVaW50OEFycmF5KGJpbi5sZW5ndGgpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYmluLmxlbmd0aDsgaSsrKSBieXRlc1tpXSA9IGJpbi5jaGFyQ29kZUF0KGkpO1xuICAgIHJldHVybiBuZXcgRmlsZShbYnl0ZXNdLCBiYXNlTmFtZSArICcuJyArIChleHQgPT09ICdqcGVnJyA/ICdqcGcnIDogZXh0KSwgeyB0eXBlOiBtWzFdIH0pO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn1cbiJdfQ==