fable-editor 1.3.0 → 1.3.2

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.
@@ -82,9 +82,14 @@ function decodePict(body) {
82
82
  kind = 'metafile';
83
83
  if (!kind)
84
84
  return null;
85
+ /* Each removal leaves a space behind. Deleting outright would glue what surrounded
86
+ it together, and Word ends the picture header with `\bliptagN{\*\blipuid …}`
87
+ hard against the payload: dropping the uid group would let the \bliptag
88
+ parameter's `\d*` run straight on into the hex and eat its leading digits
89
+ (89504e47… -> e470…), which silently corrupts every picture Word sends. */
85
90
  let hex = body
86
- .replace(/\{[^{}]*\}/g, '') // nested property groups
87
- .replace(/\\[a-z]+-?\d*\s?/gi, '') // control words
91
+ .replace(/\{[^{}]*\}/g, ' ') // nested property groups
92
+ .replace(/\\[a-z]+-?\d*\s?/gi, ' ') // control words
88
93
  .replace(/[^0-9a-fA-F]/g, '');
89
94
  if (hex.length % 2)
90
95
  hex = hex.slice(0, -1);
@@ -127,6 +132,70 @@ export function extractRtfImages(rtf) {
127
132
  return data;
128
133
  });
129
134
  }
135
+ /** CSS length -> px, so a VML shape's size survives as the <img> width/height the
136
+ * paste engine allows. Unknown units are left for the caller to skip. */
137
+ function cssPx(value) {
138
+ const m = value.match(/^\s*(-?[\d.]+)\s*(pt|px|in|cm|mm)?\s*$/i);
139
+ if (!m)
140
+ return null;
141
+ const n = parseFloat(m[1]);
142
+ if (!isFinite(n) || n <= 0)
143
+ return null;
144
+ const unit = (m[2] || 'px').toLowerCase();
145
+ const px = unit === 'pt' ? (n * 4) / 3 : unit === 'in' ? n * 96 : unit === 'cm' ? (n * 96) / 2.54 : unit === 'mm' ? (n * 96) / 25.4 : n;
146
+ return Math.round(px);
147
+ }
148
+ function attrOf(tag, name) {
149
+ const m = tag.match(new RegExp('\\s' + name + '\\s*=\\s*(?:"([^"]*)"|\'([^\']*)\'|([^\\s>]+))', 'i'));
150
+ return m ? m[1] ?? m[2] ?? m[3] ?? '' : '';
151
+ }
152
+ /** Word describes a picture twice: as a VML shape inside a downlevel-hidden
153
+ * conditional comment, and as a plain <img> fallback after it. With RelyOnVML on —
154
+ * which is what a cropped picture gets — it writes only the shape, and the paste
155
+ * engine drops conditional comments, so the picture has no tag left to land on and
156
+ * disappears. Give those shapes the <img> Word withheld, keeping the shape's size.
157
+ * Pictures that do have the fallback are recognised by their src and left alone.
158
+ *
159
+ * The shape's crop attributes are not applied: the picture appears uncropped. */
160
+ export function unwrapVmlImages(html) {
161
+ if (!/<v:imagedata\b/i.test(html))
162
+ return html;
163
+ /** The <img> Word withheld, or null when it did supply one (recognised by its src)
164
+ * and the shape is therefore only the duplicate description of the same picture.
165
+ * `sizing` is whatever markup the shape's style attribute can be read from. */
166
+ const imgFor = (imagedata, sizing) => {
167
+ const src = attrOf(imagedata, 'src');
168
+ if (!src)
169
+ return null;
170
+ const quoted = src.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
171
+ if (new RegExp('<img\\b[^>]*\\bsrc\\s*=\\s*["\']?' + quoted, 'i').test(html))
172
+ return null;
173
+ const style = (sizing.match(/<v:shape\b[^>]*\sstyle\s*=\s*(?:"([^"]*)"|'([^']*)')/i) || []).slice(1).find(Boolean) || '';
174
+ const w = cssPx((style.match(/(?:^|;)\s*width\s*:\s*([^;]+)/i) || [])[1] || '');
175
+ const h = cssPx((style.match(/(?:^|;)\s*height\s*:\s*([^;]+)/i) || [])[1] || '');
176
+ return ('<img src="' +
177
+ src.replace(/"/g, '&quot;') +
178
+ '"' +
179
+ (w ? ' width="' + w + '"' : '') +
180
+ (h ? ' height="' + h + '"' : '') +
181
+ '>');
182
+ };
183
+ /* Downlevel-hidden shape: an <img> put inside would stay inside a comment and never
184
+ reach the DOM, so the whole block has to go. */
185
+ let out = html.replace(/<!--\[if [^\]]*\]>([\s\S]*?)<!\[endif\]-->/gi, (block, inner) => {
186
+ const data = inner.match(/<v:imagedata\b[^>]*>/i);
187
+ return (data && imgFor(data[0], inner)) || block;
188
+ });
189
+ /* Live shape: with RelyOnVML on, Word writes the shape into the document itself
190
+ (bare, or inside a downlevel-revealed <![if gte vml 1]> that the parser drops),
191
+ counting on the v\:*{behavior:url(#default#VML)} rule it ships in <head>. */
192
+ out = out.replace(/<v:shape\b[^>]*>[\s\S]*?<\/v:shape\s*>/gi, (shape) => {
193
+ const data = shape.match(/<v:imagedata\b[^>]*>/i);
194
+ return (data && imgFor(data[0], shape)) || shape;
195
+ });
196
+ /* An imagedata with no shape left to take its size from. */
197
+ return out.replace(/<v:imagedata\b[^>]*>/gi, (data) => imgFor(data, '') || data);
198
+ }
130
199
  /** Rewrites unusable <img src> values in raw pasted HTML with the pictures given, in
131
200
  * document order. Images that already have a usable src are left alone and do not
132
201
  * consume a slot, so a mixed paste (webmail image + Word image) stays aligned.
@@ -136,7 +205,7 @@ export function injectImages(html, imgs) {
136
205
  return { html, injected: [] };
137
206
  const injected = [];
138
207
  let next = 0;
139
- const out = html.replace(/<img\b[^>]*>/gi, (tag) => {
208
+ const out = unwrapVmlImages(html).replace(/<img\b[^>]*>/gi, (tag) => {
140
209
  const src = (tag.match(/\ssrc\s*=\s*["']?([^"'\s>]+)/i) || [])[1] || '';
141
210
  if (USABLE_SRC.test(src))
142
211
  return tag;
@@ -186,4 +255,4 @@ export function dataUrlToFile(dataUrl, baseName) {
186
255
  return null;
187
256
  }
188
257
  }
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==
258
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29yZC1pbWFnZS1wYXN0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb3JlL3dvcmQtaW1hZ2UtcGFzdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs4RUFTOEU7QUFNOUU7OzZEQUU2RDtBQUM3RCxNQUFNLGVBQWUsR0FBRyxFQUFFLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQztBQUV6QyxNQUFNLFVBQVUsR0FBRyxnQ0FBZ0MsQ0FBQztBQUVwRDs7bUZBRW1GO0FBQ25GLFNBQVMsVUFBVSxDQUFDLEdBQVcsRUFBRSxPQUFlO0lBQzlDLE1BQU0sR0FBRyxHQUFtRCxFQUFFLENBQUM7SUFDL0QsTUFBTSxNQUFNLEdBQUcsS0FBSyxHQUFHLE9BQU8sQ0FBQztJQUMvQixJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDVixPQUFPLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUMzQzsyQ0FDbUM7UUFDbkMsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLENBQUMsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDckMsSUFBSSxLQUFLLElBQUksV0FBVyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3JDLENBQUMsSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDO1lBQ25CLFNBQVM7UUFDWCxDQUFDO1FBQ0QsSUFBSSxLQUFLLEdBQUcsQ0FBQyxDQUFDO1FBQ2QsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ1YsT0FBTyxDQUFDLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQzNCLE1BQU0sQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNqQixJQUFJLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FB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LENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3pDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRTtZQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xFLE9BQU8sSUFBSSxJQUFJLENBQUMsQ0FBQyxLQUFLLENBQUMsRUFBRSxRQUFRLEdBQUcsR0FBRyxHQUFHLENBQUMsR0FBRyxLQUFLLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzVGLENBQUM7SUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ1gsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIFJlY292ZXJzIHRoZSBwaWN0dXJlcyB0aGF0IGRlc2t0b3AgV29yZCBsZWF2ZXMgb3V0IG9mIHRoZSBIVE1MIGNsaXBib2FyZCBmbGF2b3IuXG4gICBXb3JkIHdyaXRlcyA8aW1nIHNyYz1cImZpbGU6Ly8v4oCmL21zb2h0bWxjbGlwMS8wMS9jbGlwX2ltYWdlMDAxLnBuZ1wiPiDigJQgYSBsb2NhbCB0ZW1wXG4gICBmaWxlIHRoZSBicm93c2VyIGNhbm5vdCByZWFkIOKAlCBidXQgdGhlIHNhbWUgcGFzdGUgYWxzbyBjYXJyaWVzIGEgdGV4dC9ydGYgZmxhdm9yXG4gICB3aXRoIGV2ZXJ5IHBpY3R1cmUgZW1iZWRkZWQgYXMgaGV4IGluc2lkZSBhIHtcXHBpY3R9IGdyb3VwLiBQYWlyaW5nIHRoZSB0d28gaXMgaG93XG4gICBUaW55TUNFIFBvd2VyUGFzdGUgaW1wbGVtZW50cyBwb3dlcnBhc3RlX2FsbG93X2xvY2FsX2ltYWdlcy5cblxuICAgVGhpcyBydW5zIG9uIHRoZSBSQVcgaHRtbCBzdHJpbmcgQkVGT1JFIGNsZWFuUGFzdGVkSFRNTCgpIHNlZXMgaXQ6IHRoZSBwYXN0ZSBlbmdpbmVcbiAgIGFscmVhZHkgYWxsb3dzIGRhdGE6IFVSSXMsIHNvIGl0IG5lZWRzIG5vIGNoYW5nZSBhbmQgaXRzIGJlaGF2aW91ciBpcyB1bmFmZmVjdGVkLlxuICAgQW55dGhpbmcgdGhpcyBtb2R1bGUgY2Fubm90IHJlY292ZXIgaXMgbGVmdCBleGFjdGx5IGFzIGl0IHdhcywgYW5kIHN0aWxsIGVuZHMgdXAgb25cbiAgIHRoZSBlbmdpbmUncyBleGlzdGluZyBcIltsb2NhbCBpbWFnZSDigJQgcGFzdGUgaXQgc2VwYXJhdGVseV1cIiBwbGFjZWhvbGRlci4gKi9cblxuLyoqIERlY29kZWQgcGljdHVyZXMgaW4gZG9jdW1lbnQgb3JkZXIuIEEgc2xvdCBpcyBudWxsIHdoZW4gdGhlIHBpY3R1cmUgZXhpc3RzIGJ1dFxuICogIGNhbm5vdCBiZSB0dXJuZWQgaW50byBzb21ldGhpbmcgdGhlIGJyb3dzZXIgY2FuIHNob3cgKGEgdHJ1ZSB2ZWN0b3IgbWV0YWZpbGUpLiAqL1xuZXhwb3J0IHR5cGUgUnRmSW1hZ2VzID0gKHN0cmluZyB8IG51bGwpW107XG5cbi8qKiBUb3RhbCBkZWNvZGVkIGJ5dGVzIHdlIGFyZSB3aWxsaW5nIHRvIGlubGluZSBmcm9tIG9uZSBwYXN0ZS4gQSBXb3JkIGRvY3VtZW50IGZ1bGxcbiAqICBvZiBmdWxsLXBhZ2Ugc2NyZWVuc2hvdHMgY2FuIHJ1biB0byB0ZW5zIG9mIE1COyBwYXN0IHRoaXMgd2UgbGVhdmUgdGhlIHBsYWNlaG9sZGVyc1xuICogIHJhdGhlciB0aGFuIGZyZWV6ZSB0aGUgZWRpdG9yIGJ1aWxkaW5nIGJhc2U2NCBzdHJpbmdzLiAqL1xuY29uc3QgTUFYX1RPVEFMX0JZVEVTID0gMTAgKiAxMDI0ICogMTAyNDtcblxuY29uc3QgVVNBQkxFX1NSQyA9IC9eKGh0dHBzPzp8ZGF0YTppbWFnZVxcL3xibG9iOikvaTtcblxuLyoqIFNjYW5zIGZvciBge1xca2V5d29yZCDigKZ9YCBncm91cHMsIHRyYWNraW5nIGJyYWNlIGRlcHRoIHNvIG5lc3RlZCBncm91cHMgc3VjaCBhc1xuICogIGB7XFwqXFxwaWNwcm9wIOKApn1gIGluc2lkZSBhIHBpY3R1cmUgZG8gbm90IHRlcm1pbmF0ZSB0aGUgbWF0Y2ggZWFybHkgKGEgbGF6eVxuICogIGAvXFx7XFxcXHBpY3RbXFxzXFxTXSo/XFx9L2AgcmVnZXggZ2V0cyB0aGlzIHdyb25nIGFuZCB0cnVuY2F0ZXMgdGhlIGhleCBwYXlsb2FkKS4gKi9cbmZ1bmN0aW9uIGZpbmRHcm91cHMocnRmOiBzdHJpbmcsIGtleXdvcmQ6IHN0cmluZyk6IHsgc3RhcnQ6IG51bWJlcjsgZW5kOiBudW1iZXI7IGJvZHk6IHN0cmluZyB9W10ge1xuICBjb25zdCBvdXQ6IHsgc3RhcnQ6IG51bWJlcjsgZW5kOiBudW1iZXI7IGJvZHk6IHN0cmluZyB9W10gPSBbXTtcbiAgY29uc3QgbmVlZGxlID0gJ3tcXFxcJyArIGtleXdvcmQ7XG4gIGxldCBpID0gMDtcbiAgd2hpbGUgKChpID0gcnRmLmluZGV4T2YobmVlZGxlLCBpKSkgIT09IC0xKSB7XG4gICAgLyogdGhlIGNoYXIgYWZ0ZXIgdGhlIGNvbnRyb2wgd29yZCBtdXN0IGJlIGEgZGVsaW1pdGVyLCBzbyBcXHBpY3QgZG9lcyBub3QgYWxzb1xuICAgICAgIG1hdGNoIFxccGljdHNjYWxleCBhbmQgZnJpZW5kcyAqL1xuICAgIGNvbnN0IGFmdGVyID0gcnRmW2kgKyBuZWVkbGUubGVuZ3RoXTtcbiAgICBpZiAoYWZ0ZXIgJiYgL1thLXowLTldL2kudGVzdChhZnRlcikpIHtcbiAgICAgIGkgKz0gbmVlZGxlLmxlbmd0aDtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBsZXQgZGVwdGggPSAwO1xuICAgIGxldCBqID0gaTtcbiAgICBmb3IgKDsgaiA8IHJ0Zi5sZW5ndGg7IGorKykge1xuICAgICAgY29uc3QgYyA9IHJ0ZltqXTtcbiAgICAgIGlmIChjID09PSAnXFxcXCcpIHtcbiAgICAgICAgaisrO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGlmIChjID09PSAneycpIGRlcHRoKys7XG4gICAgICBlbHNlIGlmIChjID09PSAnfScpIHtcbiAgICAgICAgZGVwdGgtLTtcbiAgICAgICAgaWYgKCFkZXB0aCkgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIG91dC5wdXNoKHsgc3RhcnQ6IGksIGVuZDogaiArIDEsIGJvZHk6IHJ0Zi5zbGljZShpICsgbmVlZGxlLmxlbmd0aCwgaikgfSk7XG4gICAgaSA9IGogKyAxO1xuICB9XG4gIHJldHVybiBvdXQ7XG59XG5cbmZ1bmN0aW9uIGhleFRvQnl0ZXMoaGV4OiBzdHJpbmcpOiBVaW50OEFycmF5IHtcbiAgY29uc3QgYnl0ZXMgPSBuZXcgVWludDhBcnJheShoZXgubGVuZ3RoIC8gMik7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgYnl0ZXMubGVuZ3RoOyBpKyspIGJ5dGVzW2ldID0gcGFyc2VJbnQoaGV4LnN1YnN0cihpICogMiwgMiksIDE2KTtcbiAgcmV0dXJuIGJ5dGVzO1xufVxuXG5mdW5jdGlvbiB0b0Jhc2U2NChieXRlczogVWludDhBcnJheSk6IHN0cmluZyB7XG4gIGxldCBiaW4gPSAnJztcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkrKykgYmluICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoYnl0ZXNbaV0pO1xuICByZXR1cm4gYnRvYShiaW4pO1xufVxuXG5mdW5jdGlvbiBpbmRleE9mU2lnKGJ5dGVzOiBVaW50OEFycmF5LCBzaWc6IG51bWJlcltdKTogbnVtYmVyIHtcbiAgb3V0ZXI6IGZvciAobGV0IGkgPSAwOyBpICsgc2lnLmxlbmd0aCA8PSBieXRlcy5sZW5ndGg7IGkrKykge1xuICAgIGZvciAobGV0IGogPSAwOyBqIDwgc2lnLmxlbmd0aDsgaisrKSBpZiAoYnl0ZXNbaSArIGpdICE9PSBzaWdbal0pIGNvbnRpbnVlIG91dGVyO1xuICAgIHJldHVybiBpO1xuICB9XG4gIHJldHVybiAtMTtcbn1cblxuY29uc3QgUE5HX1NJRyA9IFsweDg5LCAweDUwLCAweDRlLCAweDQ3XTtcbmNvbnN0IEpQR19TSUcgPSBbMHhmZiwgMHhkOCwgMHhmZl07XG5cbmZ1bmN0aW9uIGRlY29kZVBpY3QoYm9keTogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gIGxldCBraW5kOiAnaW1hZ2UvcG5nJyB8ICdpbWFnZS9qcGVnJyB8ICdtZXRhZmlsZScgfCBudWxsID0gbnVsbDtcbiAgaWYgKC9cXFxccG5nYmxpcC8udGVzdChib2R5KSkga2luZCA9ICdpbWFnZS9wbmcnO1xuICBlbHNlIGlmICgvXFxcXGpwZWdibGlwLy50ZXN0KGJvZHkpKSBraW5kID0gJ2ltYWdlL2pwZWcnO1xuICBlbHNlIGlmICgvXFxcXHdtZXRhZmlsZVxcZCovLnRlc3QoYm9keSkgfHwgL1xcXFxlbWZibGlwLy50ZXN0KGJvZHkpKSBraW5kID0gJ21ldGFmaWxlJztcbiAgaWYgKCFraW5kKSByZXR1cm4gbnVsbDtcblxuICAvKiBFYWNoIHJlbW92YWwgbGVhdmVzIGEgc3BhY2UgYmVoaW5kLiBEZWxldGluZyBvdXRyaWdodCB3b3VsZCBnbHVlIHdoYXQgc3Vycm91bmRlZFxuICAgICBpdCB0b2dldGhlciwgYW5kIFdvcmQgZW5kcyB0aGUgcGljdHVyZSBoZWFkZXIgd2l0aCBgXFxibGlwdGFnTntcXCpcXGJsaXB1aWQg4oCmfWBcbiAgICAgaGFyZCBhZ2FpbnN0IHRoZSBwYXlsb2FkOiBkcm9wcGluZyB0aGUgdWlkIGdyb3VwIHdvdWxkIGxldCB0aGUgXFxibGlwdGFnXG4gICAgIHBhcmFtZXRlcidzIGBcXGQqYCBydW4gc3RyYWlnaHQgb24gaW50byB0aGUgaGV4IGFuZCBlYXQgaXRzIGxlYWRpbmcgZGlnaXRzXG4gICAgICg4OTUwNGU0N+KApiAtPiBlNDcw4oCmKSwgd2hpY2ggc2lsZW50bHkgY29ycnVwdHMgZXZlcnkgcGljdHVyZSBXb3JkIHNlbmRzLiAqL1xuICBsZXQgaGV4ID0gYm9keVxuICAgIC5yZXBsYWNlKC9cXHtbXnt9XSpcXH0vZywgJyAnKSAvLyBuZXN0ZWQgcHJvcGVydHkgZ3JvdXBzXG4gICAgLnJlcGxhY2UoL1xcXFxbYS16XSstP1xcZCpcXHM/L2dpLCAnICcpIC8vIGNvbnRyb2wgd29yZHNcbiAgICAucmVwbGFjZSgvW14wLTlhLWZBLUZdL2csICcnKTtcbiAgaWYgKGhleC5sZW5ndGggJSAyKSBoZXggPSBoZXguc2xpY2UoMCwgLTEpO1xuICBpZiAoIWhleCkgcmV0dXJuIG51bGw7XG5cbiAgY29uc3QgYnl0ZXMgPSBoZXhUb0J5dGVzKGhleCk7XG4gIGlmIChraW5kID09PSAnbWV0YWZpbGUnKSB7XG4gICAgLyogV29yZCB3cmFwcyBhIGJpdG1hcCBpbiBhIG1ldGFmaWxlIGZvciBjb21wYXRpYmlsaXR5OyB3aGVuIHRoZXJlIGlzIGEgcmVhbFxuICAgICAgIFBORy9KUEVHIGluc2lkZSB3ZSBjYW4gdXNlIGl0LiBBIGdlbnVpbmUgdmVjdG9yIG1ldGFmaWxlIHdlIGNhbm5vdCByZW5kZXIuICovXG4gICAgY29uc3QgcG5nID0gaW5kZXhPZlNpZyhieXRlcywgUE5HX1NJRyk7XG4gICAgaWYgKHBuZyA+PSAwKSByZXR1cm4gJ2RhdGE6aW1hZ2UvcG5nO2Jhc2U2NCwnICsgdG9CYXNlNjQoYnl0ZXMuc2xpY2UocG5nKSk7XG4gICAgY29uc3QganBnID0gaW5kZXhPZlNpZyhieXRlcywgSlBHX1NJRyk7XG4gICAgaWYgKGpwZyA+PSAwKSByZXR1cm4gJ2RhdGE6aW1hZ2UvanBlZztiYXNlNjQsJyArIHRvQmFzZTY0KGJ5dGVzLnNsaWNlKGpwZykpO1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIHJldHVybiAnZGF0YTonICsga2luZCArICc7YmFzZTY0LCcgKyB0b0Jhc2U2NChieXRlcyk7XG59XG5cbi8qKiBFdmVyeSBwaWN0dXJlIGluIHRoZSBSVEYgZmxhdm9yLCBpbiBkb2N1bWVudCBvcmRlci4gKi9cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0UnRmSW1hZ2VzKHJ0Zjogc3RyaW5nKTogUnRmSW1hZ2VzIHtcbiAgaWYgKCFydGYgfHwgcnRmLmluZGV4T2YoJ1xcXFxwaWN0JykgPT09IC0xKSByZXR1cm4gW107XG4gIC8qIFdvcmQgZW1pdHMge1xcKlxcc2hwcGljdHtcXHBpY3Qg4oCmfX17XFxub25zaHBwaWN0e1xccGljdCDigKZ9fSDigJQgdGhlIHNlY29uZCBncm91cCBpcyBhXG4gICAgIGxlZ2FjeSBkdXBsaWNhdGUgb2YgdGhlIGZpcnN0LiBEcm9wcGluZyBpdCBrZWVwcyBwaWN0dXJlIG9yZGVyIGFsaWduZWQgd2l0aCB0aGVcbiAgICAgPGltZz4gdGFncyBpbiB0aGUgSFRNTCBmbGF2b3IuICovXG4gIGxldCBjbGVhbmVkID0gcnRmO1xuICBmaW5kR3JvdXBzKHJ0ZiwgJ25vbnNocHBpY3QnKVxuICAgIC5yZXZlcnNlKClcbiAgICAuZm9yRWFjaCgoZykgPT4ge1xuICAgICAgY2xlYW5lZCA9IGNsZWFuZWQuc2xpY2UoMCwgZy5zdGFydCkgKyBjbGVhbmVkLnNsaWNlKGcuZW5kKTtcbiAgICB9KTtcblxuICBsZXQgYnVkZ2V0ID0gTUFYX1RPVEFMX0JZVEVTO1xuICByZXR1cm4gZmluZEdyb3VwcyhjbGVhbmVkLCAncGljdCcpLm1hcCgoZykgPT4ge1xuICAgIGlmIChidWRnZXQgPD0gMCkgcmV0dXJuIG51bGw7XG4gICAgY29uc3QgZGF0YSA9IGRlY29kZVBpY3QoZy5ib2R5KTtcbiAgICBpZiAoZGF0YSkgYnVkZ2V0IC09IGRhdGEubGVuZ3RoICogMC43NTsgLy8gYmFzZTY0IC0+IGFwcHJveGltYXRlIGJ5dGUgY291bnRcbiAgICByZXR1cm4gZGF0YTtcbiAgfSk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSW5qZWN0UmVzdWx0IHtcbiAgaHRtbDogc3RyaW5nO1xuICAvKiogVGhlIGRhdGEgVVJJcyB0aGlzIGNhbGwgcHV0IGludG8gdGhlIEhUTUwsIGluIHRoZSBvcmRlciB0aGV5IHdlcmUgdXNlZC4gT25seVxuICAgKiAgdGhlc2UgYXJlIGNhbmRpZGF0ZXMgZm9yIHRoZSBob3N0J3MgaW1hZ2VVcGxvYWRIYW5kbGVyIOKAlCBkYXRhIFVSSXMgdGhhdCB3ZXJlXG4gICAqICBhbHJlYWR5IGluIHRoZSBwYXN0ZWQgSFRNTCBhcmUgbGVmdCBhbG9uZSwgc28gZXhpc3RpbmcgcGFzdGUgYmVoYXZpb3VyIGlzXG4gICAqICB1bmNoYW5nZWQuICovXG4gIGluamVjdGVkOiBzdHJpbmdbXTtcbn1cblxuLyoqIENTUyBsZW5ndGggLT4gcHgsIHNvIGEgVk1MIHNoYXBlJ3Mgc2l6ZSBzdXJ2aXZlcyBhcyB0aGUgPGltZz4gd2lkdGgvaGVpZ2h0IHRoZVxuICogIHBhc3RlIGVuZ2luZSBhbGxvd3MuIFVua25vd24gdW5pdHMgYXJlIGxlZnQgZm9yIHRoZSBjYWxsZXIgdG8gc2tpcC4gKi9cbmZ1bmN0aW9uIGNzc1B4KHZhbHVlOiBzdHJpbmcpOiBudW1iZXIgfCBudWxsIHtcbiAgY29uc3QgbSA9IHZhbHVlLm1hdGNoKC9eXFxzKigtP1tcXGQuXSspXFxzKihwdHxweHxpbnxjbXxtbSk/XFxzKiQvaSk7XG4gIGlmICghbSkgcmV0dXJuIG51bGw7XG4gIGNvbnN0IG4gPSBwYXJzZUZsb2F0KG1bMV0pO1xuICBpZiAoIWlzRmluaXRlKG4pIHx8IG4gPD0gMCkgcmV0dXJuIG51bGw7XG4gIGNvbnN0IHVuaXQgPSAobVsyXSB8fCAncHgnKS50b0xvd2VyQ2FzZSgpO1xuICBjb25zdCBweCA9XG4gICAgdW5pdCA9PT0gJ3B0JyA/IChuICogNCkgLyAzIDogdW5pdCA9PT0gJ2luJyA/IG4gKiA5NiA6IHVuaXQgPT09ICdjbScgPyAobiAqIDk2KSAvIDIuNTQgOiB1bml0ID09PSAnbW0nID8gKG4gKiA5NikgLyAyNS40IDogbjtcbiAgcmV0dXJuIE1hdGgucm91bmQocHgpO1xufVxuXG5mdW5jdGlvbiBhdHRyT2YodGFnOiBzdHJpbmcsIG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IG0gPSB0YWcubWF0Y2gobmV3IFJlZ0V4cCgnXFxcXHMnICsgbmFtZSArICdcXFxccyo9XFxcXHMqKD86XCIoW15cIl0qKVwifFxcJyhbXlxcJ10qKVxcJ3woW15cXFxccz5dKykpJywgJ2knKSk7XG4gIHJldHVybiBtID8gbVsxXSA/PyBtWzJdID8/IG1bM10gPz8gJycgOiAnJztcbn1cblxuLyoqIFdvcmQgZGVzY3JpYmVzIGEgcGljdHVyZSB0d2ljZTogYXMgYSBWTUwgc2hhcGUgaW5zaWRlIGEgZG93bmxldmVsLWhpZGRlblxuICogIGNvbmRpdGlvbmFsIGNvbW1lbnQsIGFuZCBhcyBhIHBsYWluIDxpbWc+IGZhbGxiYWNrIGFmdGVyIGl0LiBXaXRoIFJlbHlPblZNTCBvbiDigJRcbiAqICB3aGljaCBpcyB3aGF0IGEgY3JvcHBlZCBwaWN0dXJlIGdldHMg4oCUIGl0IHdyaXRlcyBvbmx5IHRoZSBzaGFwZSwgYW5kIHRoZSBwYXN0ZVxuICogIGVuZ2luZSBkcm9wcyBjb25kaXRpb25hbCBjb21tZW50cywgc28gdGhlIHBpY3R1cmUgaGFzIG5vIHRhZyBsZWZ0IHRvIGxhbmQgb24gYW5kXG4gKiAgZGlzYXBwZWFycy4gR2l2ZSB0aG9zZSBzaGFwZXMgdGhlIDxpbWc+IFdvcmQgd2l0aGhlbGQsIGtlZXBpbmcgdGhlIHNoYXBlJ3Mgc2l6ZS5cbiAqICBQaWN0dXJlcyB0aGF0IGRvIGhhdmUgdGhlIGZhbGxiYWNrIGFyZSByZWNvZ25pc2VkIGJ5IHRoZWlyIHNyYyBhbmQgbGVmdCBhbG9uZS5cbiAqXG4gKiAgVGhlIHNoYXBlJ3MgY3JvcCBhdHRyaWJ1dGVzIGFyZSBub3QgYXBwbGllZDogdGhlIHBpY3R1cmUgYXBwZWFycyB1bmNyb3BwZWQuICovXG5leHBvcnQgZnVuY3Rpb24gdW53cmFwVm1sSW1hZ2VzKGh0bWw6IHN0cmluZyk6IHN0cmluZyB7XG4gIGlmICghLzx2OmltYWdlZGF0YVxcYi9pLnRlc3QoaHRtbCkpIHJldHVybiBodG1sO1xuXG4gIC8qKiBUaGUgPGltZz4gV29yZCB3aXRoaGVsZCwgb3IgbnVsbCB3aGVuIGl0IGRpZCBzdXBwbHkgb25lIChyZWNvZ25pc2VkIGJ5IGl0cyBzcmMpXG4gICAqICBhbmQgdGhlIHNoYXBlIGlzIHRoZXJlZm9yZSBvbmx5IHRoZSBkdXBsaWNhdGUgZGVzY3JpcHRpb24gb2YgdGhlIHNhbWUgcGljdHVyZS5cbiAgICogIGBzaXppbmdgIGlzIHdoYXRldmVyIG1hcmt1cCB0aGUgc2hhcGUncyBzdHlsZSBhdHRyaWJ1dGUgY2FuIGJlIHJlYWQgZnJvbS4gKi9cbiAgY29uc3QgaW1nRm9yID0gKGltYWdlZGF0YTogc3RyaW5nLCBzaXppbmc6IHN0cmluZyk6IHN0cmluZyB8IG51bGwgPT4ge1xuICAgIGNvbnN0IHNyYyA9IGF0dHJPZihpbWFnZWRhdGEsICdzcmMnKTtcbiAgICBpZiAoIXNyYykgcmV0dXJuIG51bGw7XG4gICAgY29uc3QgcXVvdGVkID0gc3JjLnJlcGxhY2UoL1suKis/XiR7fSgpfFtcXF1cXFxcXS9nLCAnXFxcXCQmJyk7XG4gICAgaWYgKG5ldyBSZWdFeHAoJzxpbWdcXFxcYltePl0qXFxcXGJzcmNcXFxccyo9XFxcXHMqW1wiXFwnXT8nICsgcXVvdGVkLCAnaScpLnRlc3QoaHRtbCkpIHJldHVybiBudWxsO1xuICAgIGNvbnN0IHN0eWxlID0gKHNpemluZy5tYXRjaCgvPHY6c2hhcGVcXGJbXj5dKlxcc3N0eWxlXFxzKj1cXHMqKD86XCIoW15cIl0qKVwifCcoW14nXSopJykvaSkgfHwgW10pLnNsaWNlKDEpLmZpbmQoQm9vbGVhbikgfHwgJyc7XG4gICAgY29uc3QgdyA9IGNzc1B4KChzdHlsZS5tYXRjaCgvKD86Xnw7KVxccyp3aWR0aFxccyo6XFxzKihbXjtdKykvaSkgfHwgW10pWzFdIHx8ICcnKTtcbiAgICBjb25zdCBoID0gY3NzUHgoKHN0eWxlLm1hdGNoKC8oPzpefDspXFxzKmhlaWdodFxccyo6XFxzKihbXjtdKykvaSkgfHwgW10pWzFdIHx8ICcnKTtcbiAgICByZXR1cm4gKFxuICAgICAgJzxpbWcgc3JjPVwiJyArXG4gICAgICBzcmMucmVwbGFjZSgvXCIvZywgJyZxdW90OycpICtcbiAgICAgICdcIicgK1xuICAgICAgKHcgPyAnIHdpZHRoPVwiJyArIHcgKyAnXCInIDogJycpICtcbiAgICAgIChoID8gJyBoZWlnaHQ9XCInICsgaCArICdcIicgOiAnJykgK1xuICAgICAgJz4nXG4gICAgKTtcbiAgfTtcblxuICAvKiBEb3dubGV2ZWwtaGlkZGVuIHNoYXBlOiBhbiA8aW1nPiBwdXQgaW5zaWRlIHdvdWxkIHN0YXkgaW5zaWRlIGEgY29tbWVudCBhbmQgbmV2ZXJcbiAgICAgcmVhY2ggdGhlIERPTSwgc28gdGhlIHdob2xlIGJsb2NrIGhhcyB0byBnby4gKi9cbiAgbGV0IG91dCA9IGh0bWwucmVwbGFjZSgvPCEtLVxcW2lmIFteXFxdXSpcXF0+KFtcXHNcXFNdKj8pPCFcXFtlbmRpZlxcXS0tPi9naSwgKGJsb2NrLCBpbm5lcjogc3RyaW5nKSA9PiB7XG4gICAgY29uc3QgZGF0YSA9IGlubmVyLm1hdGNoKC88djppbWFnZWRhdGFcXGJbXj5dKj4vaSk7XG4gICAgcmV0dXJuIChkYXRhICYmIGltZ0ZvcihkYXRhWzBdLCBpbm5lcikpIHx8IGJsb2NrO1xuICB9KTtcblxuICAvKiBMaXZlIHNoYXBlOiB3aXRoIFJlbHlPblZNTCBvbiwgV29yZCB3cml0ZXMgdGhlIHNoYXBlIGludG8gdGhlIGRvY3VtZW50IGl0c2VsZlxuICAgICAoYmFyZSwgb3IgaW5zaWRlIGEgZG93bmxldmVsLXJldmVhbGVkIDwhW2lmIGd0ZSB2bWwgMV0+IHRoYXQgdGhlIHBhcnNlciBkcm9wcyksXG4gICAgIGNvdW50aW5nIG9uIHRoZSB2XFw6KntiZWhhdmlvcjp1cmwoI2RlZmF1bHQjVk1MKX0gcnVsZSBpdCBzaGlwcyBpbiA8aGVhZD4uICovXG4gIG91dCA9IG91dC5yZXBsYWNlKC88djpzaGFwZVxcYltePl0qPltcXHNcXFNdKj88XFwvdjpzaGFwZVxccyo+L2dpLCAoc2hhcGUpID0+IHtcbiAgICBjb25zdCBkYXRhID0gc2hhcGUubWF0Y2goLzx2OmltYWdlZGF0YVxcYltePl0qPi9pKTtcbiAgICByZXR1cm4gKGRhdGEgJiYgaW1nRm9yKGRhdGFbMF0sIHNoYXBlKSkgfHwgc2hhcGU7XG4gIH0pO1xuXG4gIC8qIEFuIGltYWdlZGF0YSB3aXRoIG5vIHNoYXBlIGxlZnQgdG8gdGFrZSBpdHMgc2l6ZSBmcm9tLiAqL1xuICByZXR1cm4gb3V0LnJlcGxhY2UoLzx2OmltYWdlZGF0YVxcYltePl0qPi9naSwgKGRhdGEpID0+IGltZ0ZvcihkYXRhLCAnJykgfHwgZGF0YSk7XG59XG5cbi8qKiBSZXdyaXRlcyB1bnVzYWJsZSA8aW1nIHNyYz4gdmFsdWVzIGluIHJhdyBwYXN0ZWQgSFRNTCB3aXRoIHRoZSBwaWN0dXJlcyBnaXZlbiwgaW5cbiAqICBkb2N1bWVudCBvcmRlci4gSW1hZ2VzIHRoYXQgYWxyZWFkeSBoYXZlIGEgdXNhYmxlIHNyYyBhcmUgbGVmdCBhbG9uZSBhbmQgZG8gbm90XG4gKiAgY29uc3VtZSBhIHNsb3QsIHNvIGEgbWl4ZWQgcGFzdGUgKHdlYm1haWwgaW1hZ2UgKyBXb3JkIGltYWdlKSBzdGF5cyBhbGlnbmVkLlxuICogIEFueXRoaW5nIHdpdGhvdXQgYSBtYXRjaGluZyBwaWN0dXJlIGtlZXBzIGl0cyBvcmlnaW5hbCB0YWcuICovXG5leHBvcnQgZnVuY3Rpb24gaW5qZWN0SW1hZ2VzKGh0bWw6IHN0cmluZywgaW1nczogUnRmSW1hZ2VzKTogSW5qZWN0UmVzdWx0IHtcbiAgaWYgKCFodG1sIHx8ICFpbWdzLmxlbmd0aCkgcmV0dXJuIHsgaHRtbCwgaW5qZWN0ZWQ6IFtdIH07XG4gIGNvbnN0IGluamVjdGVkOiBzdHJpbmdbXSA9IFtdO1xuICBsZXQgbmV4dCA9IDA7XG4gIGNvbnN0IG91dCA9IHVud3JhcFZtbEltYWdlcyhodG1sKS5yZXBsYWNlKC88aW1nXFxiW14+XSo+L2dpLCAodGFnKSA9PiB7XG4gICAgY29uc3Qgc3JjID0gKHRhZy5tYXRjaCgvXFxzc3JjXFxzKj1cXHMqW1wiJ10/KFteXCInXFxzPl0rKS9pKSB8fCBbXSlbMV0gfHwgJyc7XG4gICAgaWYgKFVTQUJMRV9TUkMudGVzdChzcmMpKSByZXR1cm4gdGFnO1xuICAgIGNvbnN0IGRhdGEgPSBpbWdzW25leHQrK107XG4gICAgaWYgKCFkYXRhKSByZXR1cm4gdGFnO1xuICAgIGluamVjdGVkLnB1c2goZGF0YSk7XG4gICAgcmV0dXJuIC9cXHNzcmNcXHMqPVxccypbXCInXS9pLnRlc3QodGFnKVxuICAgICAgPyB0YWcucmVwbGFjZSgvKFxcc3NyY1xccyo9XFxzKikoW1wiJ10pW15cIiddKlxcMi9pLCAnJDFcIicgKyBkYXRhICsgJ1wiJylcbiAgICAgIDogdGFnLnJlcGxhY2UoLyhcXHNzcmNcXHMqPVxccyopW15cXHM+XSsvaSwgJyQxXCInICsgZGF0YSArICdcIicpO1xuICB9KTtcbiAgcmV0dXJuIHsgaHRtbDogb3V0LCBpbmplY3RlZCB9O1xufVxuXG4vKiogUGFpcnMgdGhlIEhUTUwgZmxhdm9yIG9mIGEgV29yZCBwYXN0ZSB3aXRoIHRoZSBwaWN0dXJlcyBpbiBpdHMgUlRGIGZsYXZvci4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmplY3RSdGZJbWFnZXMoaHRtbDogc3RyaW5nLCBydGY6IHN0cmluZyk6IEluamVjdFJlc3VsdCB7XG4gIGlmICghaHRtbCB8fCAhcnRmKSByZXR1cm4geyBodG1sLCBpbmplY3RlZDogW10gfTtcbiAgcmV0dXJuIGluamVjdEltYWdlcyhodG1sLCBleHRyYWN0UnRmSW1hZ2VzKHJ0ZikpO1xufVxuXG4vKiogVHJ1ZSB3aGVuIHRoZSBjbGVhbmVkIEhUTUwgc3RpbGwgaG9sZHMgaW1hZ2VzIHRoZSBlbmdpbmUgY291bGQgbm90IHJlc29sdmUg4oCUIHVzZWRcbiAqICB0byBkZWNpZGUgd2hldGhlciBhIGJpdG1hcCBzaXR0aW5nIGluIHRoZSBjbGlwYm9hcmQgaXMgd29ydGggZmFsbGluZyBiYWNrIHRvLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvdW50VW5yZXNvbHZlZEltYWdlcyhodG1sOiBzdHJpbmcpOiBudW1iZXIge1xuICBjb25zdCB0YWdzID0gaHRtbC5tYXRjaCgvPGltZ1xcYltePl0qPi9naSk7XG4gIGlmICghdGFncykgcmV0dXJuIDA7XG4gIHJldHVybiB0YWdzLmZpbHRlcigodGFnKSA9PiB7XG4gICAgY29uc3Qgc3JjID0gKHRhZy5tYXRjaCgvXFxzc3JjXFxzKj1cXHMqW1wiJ10/KFteXCInXFxzPl0rKS9pKSB8fCBbXSlbMV0gfHwgJyc7XG4gICAgcmV0dXJuICFVU0FCTEVfU1JDLnRlc3Qoc3JjKTtcbiAgfSkubGVuZ3RoO1xufVxuXG4vKiogZGF0YTogVVJJIC0+IEZpbGUsIHNvIHJlY292ZXJlZCBwaWN0dXJlcyBjYW4gZ28gdGhyb3VnaCB0aGUgaG9zdCdzXG4gKiAgaW1hZ2VVcGxvYWRIYW5kbGVyIGV4YWN0bHkgbGlrZSBhIHBpY2tlZCBmaWxlIGRvZXMuIGBiYXNlTmFtZWAgZ2V0cyB0aGUgZXh0ZW5zaW9uXG4gKiAgdGhhdCBtYXRjaGVzIHRoZSBVUkkncyBNSU1FIHR5cGUuICovXG5leHBvcnQgZnVuY3Rpb24gZGF0YVVybFRvRmlsZShkYXRhVXJsOiBzdHJpbmcsIGJhc2VOYW1lOiBzdHJpbmcpOiBGaWxlIHwgbnVsbCB7XG4gIGNvbnN0IG0gPSBkYXRhVXJsLm1hdGNoKC9eZGF0YTooW147LF0rKTtiYXNlNjQsKC4qKSQvKTtcbiAgaWYgKCFtKSByZXR1cm4gbnVsbDtcbiAgY29uc3QgZXh0ID0gKG1bMV0uc3BsaXQoJy8nKVsxXSB8fCAncG5nJykucmVwbGFjZSgvW15hLXowLTldL2dpLCAnJykgfHwgJ3BuZyc7XG4gIHRyeSB7XG4gICAgY29uc3QgYmluID0gYXRvYihtWzJdKTtcbiAgICBjb25zdCBieXRlcyA9IG5ldyBVaW50OEFycmF5KGJpbi5sZW5ndGgpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYmluLmxlbmd0aDsgaSsrKSBieXRlc1tpXSA9IGJpbi5jaGFyQ29kZUF0KGkpO1xuICAgIHJldHVybiBuZXcgRmlsZShbYnl0ZXNdLCBiYXNlTmFtZSArICcuJyArIChleHQgPT09ICdqcGVnJyA/ICdqcGcnIDogZXh0KSwgeyB0eXBlOiBtWzFdIH0pO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn1cbiJdfQ==
@@ -1374,9 +1374,14 @@ function decodePict(body) {
1374
1374
  kind = 'metafile';
1375
1375
  if (!kind)
1376
1376
  return null;
1377
+ /* Each removal leaves a space behind. Deleting outright would glue what surrounded
1378
+ it together, and Word ends the picture header with `\bliptagN{\*\blipuid …}`
1379
+ hard against the payload: dropping the uid group would let the \bliptag
1380
+ parameter's `\d*` run straight on into the hex and eat its leading digits
1381
+ (89504e47… -> e470…), which silently corrupts every picture Word sends. */
1377
1382
  let hex = body
1378
- .replace(/\{[^{}]*\}/g, '') // nested property groups
1379
- .replace(/\\[a-z]+-?\d*\s?/gi, '') // control words
1383
+ .replace(/\{[^{}]*\}/g, ' ') // nested property groups
1384
+ .replace(/\\[a-z]+-?\d*\s?/gi, ' ') // control words
1380
1385
  .replace(/[^0-9a-fA-F]/g, '');
1381
1386
  if (hex.length % 2)
1382
1387
  hex = hex.slice(0, -1);
@@ -1419,6 +1424,70 @@ function extractRtfImages(rtf) {
1419
1424
  return data;
1420
1425
  });
1421
1426
  }
1427
+ /** CSS length -> px, so a VML shape's size survives as the <img> width/height the
1428
+ * paste engine allows. Unknown units are left for the caller to skip. */
1429
+ function cssPx(value) {
1430
+ const m = value.match(/^\s*(-?[\d.]+)\s*(pt|px|in|cm|mm)?\s*$/i);
1431
+ if (!m)
1432
+ return null;
1433
+ const n = parseFloat(m[1]);
1434
+ if (!isFinite(n) || n <= 0)
1435
+ return null;
1436
+ const unit = (m[2] || 'px').toLowerCase();
1437
+ const px = unit === 'pt' ? (n * 4) / 3 : unit === 'in' ? n * 96 : unit === 'cm' ? (n * 96) / 2.54 : unit === 'mm' ? (n * 96) / 25.4 : n;
1438
+ return Math.round(px);
1439
+ }
1440
+ function attrOf(tag, name) {
1441
+ const m = tag.match(new RegExp('\\s' + name + '\\s*=\\s*(?:"([^"]*)"|\'([^\']*)\'|([^\\s>]+))', 'i'));
1442
+ return m ? m[1] ?? m[2] ?? m[3] ?? '' : '';
1443
+ }
1444
+ /** Word describes a picture twice: as a VML shape inside a downlevel-hidden
1445
+ * conditional comment, and as a plain <img> fallback after it. With RelyOnVML on —
1446
+ * which is what a cropped picture gets — it writes only the shape, and the paste
1447
+ * engine drops conditional comments, so the picture has no tag left to land on and
1448
+ * disappears. Give those shapes the <img> Word withheld, keeping the shape's size.
1449
+ * Pictures that do have the fallback are recognised by their src and left alone.
1450
+ *
1451
+ * The shape's crop attributes are not applied: the picture appears uncropped. */
1452
+ function unwrapVmlImages(html) {
1453
+ if (!/<v:imagedata\b/i.test(html))
1454
+ return html;
1455
+ /** The <img> Word withheld, or null when it did supply one (recognised by its src)
1456
+ * and the shape is therefore only the duplicate description of the same picture.
1457
+ * `sizing` is whatever markup the shape's style attribute can be read from. */
1458
+ const imgFor = (imagedata, sizing) => {
1459
+ const src = attrOf(imagedata, 'src');
1460
+ if (!src)
1461
+ return null;
1462
+ const quoted = src.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1463
+ if (new RegExp('<img\\b[^>]*\\bsrc\\s*=\\s*["\']?' + quoted, 'i').test(html))
1464
+ return null;
1465
+ const style = (sizing.match(/<v:shape\b[^>]*\sstyle\s*=\s*(?:"([^"]*)"|'([^']*)')/i) || []).slice(1).find(Boolean) || '';
1466
+ const w = cssPx((style.match(/(?:^|;)\s*width\s*:\s*([^;]+)/i) || [])[1] || '');
1467
+ const h = cssPx((style.match(/(?:^|;)\s*height\s*:\s*([^;]+)/i) || [])[1] || '');
1468
+ return ('<img src="' +
1469
+ src.replace(/"/g, '&quot;') +
1470
+ '"' +
1471
+ (w ? ' width="' + w + '"' : '') +
1472
+ (h ? ' height="' + h + '"' : '') +
1473
+ '>');
1474
+ };
1475
+ /* Downlevel-hidden shape: an <img> put inside would stay inside a comment and never
1476
+ reach the DOM, so the whole block has to go. */
1477
+ let out = html.replace(/<!--\[if [^\]]*\]>([\s\S]*?)<!\[endif\]-->/gi, (block, inner) => {
1478
+ const data = inner.match(/<v:imagedata\b[^>]*>/i);
1479
+ return (data && imgFor(data[0], inner)) || block;
1480
+ });
1481
+ /* Live shape: with RelyOnVML on, Word writes the shape into the document itself
1482
+ (bare, or inside a downlevel-revealed <![if gte vml 1]> that the parser drops),
1483
+ counting on the v\:*{behavior:url(#default#VML)} rule it ships in <head>. */
1484
+ out = out.replace(/<v:shape\b[^>]*>[\s\S]*?<\/v:shape\s*>/gi, (shape) => {
1485
+ const data = shape.match(/<v:imagedata\b[^>]*>/i);
1486
+ return (data && imgFor(data[0], shape)) || shape;
1487
+ });
1488
+ /* An imagedata with no shape left to take its size from. */
1489
+ return out.replace(/<v:imagedata\b[^>]*>/gi, (data) => imgFor(data, '') || data);
1490
+ }
1422
1491
  /** Rewrites unusable <img src> values in raw pasted HTML with the pictures given, in
1423
1492
  * document order. Images that already have a usable src are left alone and do not
1424
1493
  * consume a slot, so a mixed paste (webmail image + Word image) stays aligned.
@@ -1428,7 +1497,7 @@ function injectImages(html, imgs) {
1428
1497
  return { html, injected: [] };
1429
1498
  const injected = [];
1430
1499
  let next = 0;
1431
- const out = html.replace(/<img\b[^>]*>/gi, (tag) => {
1500
+ const out = unwrapVmlImages(html).replace(/<img\b[^>]*>/gi, (tag) => {
1432
1501
  const src = (tag.match(/\ssrc\s*=\s*["']?([^"'\s>]+)/i) || [])[1] || '';
1433
1502
  if (USABLE_SRC.test(src))
1434
1503
  return tag;
@@ -1980,6 +2049,152 @@ function firstStrongDir(text) {
1980
2049
  }
1981
2050
  return null;
1982
2051
  }
2052
+ /* ---------------------------------------------------------- email-export table
2053
+ borders — used only by getContentForEmail(). Word describes a cell's borders
2054
+ as three parallel longhands (`border-color` / `border-style` / `border-width`),
2055
+ one value per side, and a browser re-copy of Word content keeps that split.
2056
+ Mail pipelines allowlist CSS one property at a time, and any of them that
2057
+ keeps `border-color` and `border-width` while dropping `border-style` erases
2058
+ the border outright — the initial `border-style` is `none`, so a width and a
2059
+ colour on their own draw nothing. Re-emitting every side as a single
2060
+ `border-<side>: <width> <style> <colour>` (collapsed to one `border:` when all
2061
+ four agree) makes a side survive or vanish as a unit instead. A side left with
2062
+ a width or a colour but no style is read back as `solid`, which also repairs
2063
+ content that was already flattened that way before it came back into the
2064
+ editor, and `windowtext` — a deprecated system colour Word still emits —
2065
+ becomes plain black. */
2066
+ const BORDER_SIDES = ['top', 'right', 'bottom', 'left'];
2067
+ const BORDER_STYLE_KEYWORD = /^(none|hidden|dotted|dashed|solid|double|groove|ridge|inset|outset)$/i;
2068
+ const BORDER_WIDTH_VALUE = /^(thin|medium|thick|[+-]?(\d+\.?\d*|\.\d+)(px|pt|em|rem|ex|ch|cm|mm|in|pc|q)?)$/i;
2069
+ const BORDER_ZERO_WIDTH = /^[+-]?0*(\.0*)?(px|pt|em|rem|ex|ch|cm|mm|in|pc|q)?$/i;
2070
+ /* border-* properties that describe something other than one of the four sides,
2071
+ plus the CSS-wide keywords a shorthand cannot express. */
2072
+ const BORDER_NOT_A_SIDE = /^border-(collapse|spacing|radius|image|block|inline|start|end)/i;
2073
+ const BORDER_SIDE_PROP = /^border(?:-(top|right|bottom|left))?(?:-(width|style|color))?$/;
2074
+ const CSS_WIDE_KEYWORD = /^(inherit|initial|unset|revert|revert-layer)$/i;
2075
+ /* Split on top-level whitespace, so `rgb(0, 0, 0) solid` stays two values. */
2076
+ function splitCssValues(value) {
2077
+ const out = [];
2078
+ let depth = 0;
2079
+ let cur = '';
2080
+ for (const ch of value) {
2081
+ if (ch === '(')
2082
+ depth++;
2083
+ else if (ch === ')')
2084
+ depth--;
2085
+ if (depth === 0 && /\s/.test(ch)) {
2086
+ if (cur)
2087
+ out.push(cur);
2088
+ cur = '';
2089
+ }
2090
+ else
2091
+ cur += ch;
2092
+ }
2093
+ if (cur)
2094
+ out.push(cur);
2095
+ return out;
2096
+ }
2097
+ /* 1–4 values in CSS box order → an explicit [top, right, bottom, left]. */
2098
+ function boxSides(parts) {
2099
+ const [t, r = t, b = t, l = r] = parts;
2100
+ return [t, r, b, l];
2101
+ }
2102
+ /* `1pt solid windowtext` in any order; whatever the author left out falls back
2103
+ to its initial value, exactly as the real shorthand resets it. */
2104
+ function parseBorderShorthand(value) {
2105
+ const side = { width: 'medium', style: 'none', color: '' };
2106
+ splitCssValues(value).forEach((part) => {
2107
+ if (BORDER_STYLE_KEYWORD.test(part))
2108
+ side.style = part.toLowerCase();
2109
+ else if (BORDER_WIDTH_VALUE.test(part))
2110
+ side.width = part;
2111
+ else
2112
+ side.color = part;
2113
+ });
2114
+ return side;
2115
+ }
2116
+ function emailBorderColor(color) {
2117
+ if (!color || /^currentcolor$/i.test(color))
2118
+ return '';
2119
+ return /^windowtext$/i.test(color) ? '#000000' : color;
2120
+ }
2121
+ /* One side's declaration value, or '' when that side was never mentioned. */
2122
+ function sideBorderValue(side) {
2123
+ if (side.width === null && side.style === null && side.color === null)
2124
+ return '';
2125
+ const style = side.style ?? 'solid';
2126
+ if (style === 'none' || style === 'hidden')
2127
+ return 'none';
2128
+ if (side.width && BORDER_ZERO_WIDTH.test(side.width))
2129
+ return 'none';
2130
+ const width = side.width && side.width !== 'medium' ? side.width : '';
2131
+ return [width, style, emailBorderColor(side.color || '')].filter(Boolean).join(' ');
2132
+ }
2133
+ function hardenTableBorders(root) {
2134
+ root.querySelectorAll('table,td,th').forEach((el) => {
2135
+ const raw = el.getAttribute('style') || '';
2136
+ if (!/border/i.test(raw))
2137
+ return;
2138
+ const sides = {
2139
+ top: { width: null, style: null, color: null },
2140
+ right: { width: null, style: null, color: null },
2141
+ bottom: { width: null, style: null, color: null },
2142
+ left: { width: null, style: null, color: null }
2143
+ };
2144
+ const rest = [];
2145
+ let sawBorder = false;
2146
+ let bail = false;
2147
+ raw.split(';').forEach((decl) => {
2148
+ const i = decl.indexOf(':');
2149
+ if (i < 1) {
2150
+ if (decl.trim())
2151
+ rest.push(decl.trim());
2152
+ return;
2153
+ }
2154
+ const prop = decl.slice(0, i).trim().toLowerCase();
2155
+ const value = decl.slice(i + 1).trim();
2156
+ const m = BORDER_SIDE_PROP.exec(prop);
2157
+ if (!m || BORDER_NOT_A_SIDE.test(prop)) {
2158
+ rest.push(prop + ':' + value);
2159
+ return;
2160
+ }
2161
+ /* `border-color:inherit` and friends only mean anything against a
2162
+ parent this export has no say over — leave the cell untouched. */
2163
+ if (CSS_WIDE_KEYWORD.test(value)) {
2164
+ bail = true;
2165
+ return;
2166
+ }
2167
+ sawBorder = true;
2168
+ const one = m[1];
2169
+ const part = m[2];
2170
+ if (!part) {
2171
+ /* `border` / `border-<side>` resets all three components. */
2172
+ const parsed = parseBorderShorthand(value);
2173
+ (one ? [one] : BORDER_SIDES.slice()).forEach((s) => {
2174
+ sides[s] = { ...parsed };
2175
+ });
2176
+ }
2177
+ else if (one) {
2178
+ sides[one][part] = value;
2179
+ }
2180
+ else {
2181
+ const per = boxSides(splitCssValues(value));
2182
+ BORDER_SIDES.forEach((s, n) => {
2183
+ sides[s][part] = per[n];
2184
+ });
2185
+ }
2186
+ });
2187
+ if (bail || !sawBorder)
2188
+ return;
2189
+ const values = BORDER_SIDES.map((s) => sideBorderValue(sides[s]));
2190
+ const out = rest.slice();
2191
+ if (values.every((v) => v && v === values[0]))
2192
+ out.push('border:' + values[0]);
2193
+ else
2194
+ BORDER_SIDES.forEach((s, n) => values[n] && out.push(`border-${s}:` + values[n]));
2195
+ el.setAttribute('style', out.join(';'));
2196
+ });
2197
+ }
1983
2198
  /* Text belonging to el itself, skipping subtrees rooted at a descendant that
1984
2199
  already carries its own explicit rtl/ltr dir — that subtree's direction is
1985
2200
  already independently decided and shouldn't sway el's own detection. */
@@ -2559,6 +2774,19 @@ class FableEditor {
2559
2774
  if (!/(^|;)\s*height\s*:/i.test(img.getAttribute('style') || ''))
2560
2775
  setStyle(img, 'height:auto');
2561
2776
  });
2777
+ /* Borders last, so the per-side shorthands it writes are the final word on
2778
+ every cell. Also pin border-collapse inline and mirror it onto the legacy
2779
+ cellspacing attribute: a mail pipeline that drops border-collapse leaves
2780
+ the table in `separate` mode, where any cellspacing of its own would open
2781
+ gaps between Word's deliberately shared cell edges. */
2782
+ hardenTableBorders(box);
2783
+ box.querySelectorAll('table').forEach((tbl) => {
2784
+ const style = tbl.getAttribute('style') || '';
2785
+ if (!/border-collapse\s*:/i.test(style))
2786
+ setStyle(tbl, 'border-collapse:collapse');
2787
+ if (!/border-spacing\s*:/i.test(style) && !tbl.hasAttribute('cellspacing'))
2788
+ tbl.setAttribute('cellspacing', '0');
2789
+ });
2562
2790
  const dir = found || this.ed.getAttribute('dir') || this.dir();
2563
2791
  box.querySelectorAll('table:not([dir])').forEach((tbl) => {
2564
2792
  tbl.setAttribute('dir', dir);