marksmith 0.0.12 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2449 @@
1
+ /*!
2
+ Marksmith 0.0.15
3
+ */
4
+ var MarksmithController = (function (stimulus) {
5
+ 'use strict';
6
+
7
+ var __classPrivateFieldGet = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
12
+ var _MarkdownHeaderButtonElement_instances, _MarkdownHeaderButtonElement_setLevelStyle;
13
+ const buttonSelectors = [
14
+ '[data-md-button]',
15
+ 'md-header',
16
+ 'md-bold',
17
+ 'md-italic',
18
+ 'md-quote',
19
+ 'md-code',
20
+ 'md-link',
21
+ 'md-image',
22
+ 'md-unordered-list',
23
+ 'md-ordered-list',
24
+ 'md-task-list',
25
+ 'md-mention',
26
+ 'md-ref',
27
+ 'md-strikethrough'
28
+ ];
29
+ function getButtons(toolbar) {
30
+ const els = [];
31
+ for (const button of toolbar.querySelectorAll(buttonSelectors.join(', '))) {
32
+ if (button.hidden || (button.offsetWidth <= 0 && button.offsetHeight <= 0))
33
+ continue;
34
+ if (button.closest('markdown-toolbar') === toolbar)
35
+ els.push(button);
36
+ }
37
+ return els;
38
+ }
39
+ function keydown(fn) {
40
+ return function (event) {
41
+ if (event.key === ' ' || event.key === 'Enter') {
42
+ fn(event);
43
+ }
44
+ };
45
+ }
46
+ const styles = new WeakMap();
47
+ const manualStyles = {
48
+ 'header-1': { prefix: '# ' },
49
+ 'header-2': { prefix: '## ' },
50
+ 'header-3': { prefix: '### ' },
51
+ 'header-4': { prefix: '#### ' },
52
+ 'header-5': { prefix: '##### ' },
53
+ 'header-6': { prefix: '###### ' },
54
+ bold: { prefix: '**', suffix: '**', trimFirst: true },
55
+ italic: { prefix: '_', suffix: '_', trimFirst: true },
56
+ quote: { prefix: '> ', multiline: true, surroundWithNewlines: true },
57
+ code: {
58
+ prefix: '`',
59
+ suffix: '`',
60
+ blockPrefix: '```',
61
+ blockSuffix: '```'
62
+ },
63
+ link: { prefix: '[', suffix: '](url)', replaceNext: 'url', scanFor: 'https?://' },
64
+ image: { prefix: '![', suffix: '](url)', replaceNext: 'url', scanFor: 'https?://' },
65
+ 'unordered-list': {
66
+ prefix: '- ',
67
+ multiline: true,
68
+ unorderedList: true
69
+ },
70
+ 'ordered-list': {
71
+ prefix: '1. ',
72
+ multiline: true,
73
+ orderedList: true
74
+ },
75
+ 'task-list': { prefix: '- [ ] ', multiline: true, surroundWithNewlines: true },
76
+ mention: { prefix: '@', prefixSpace: true },
77
+ ref: { prefix: '#', prefixSpace: true },
78
+ strikethrough: { prefix: '~~', suffix: '~~', trimFirst: true }
79
+ };
80
+ class MarkdownButtonElement extends HTMLElement {
81
+ constructor() {
82
+ super();
83
+ const apply = (event) => {
84
+ const style = styles.get(this);
85
+ if (!style)
86
+ return;
87
+ event.preventDefault();
88
+ applyStyle(this, style);
89
+ };
90
+ this.addEventListener('keydown', keydown(apply));
91
+ this.addEventListener('click', apply);
92
+ }
93
+ connectedCallback() {
94
+ if (!this.hasAttribute('role')) {
95
+ this.setAttribute('role', 'button');
96
+ }
97
+ }
98
+ click() {
99
+ const style = styles.get(this);
100
+ if (!style)
101
+ return;
102
+ applyStyle(this, style);
103
+ }
104
+ }
105
+ class MarkdownHeaderButtonElement extends MarkdownButtonElement {
106
+ constructor() {
107
+ super(...arguments);
108
+ _MarkdownHeaderButtonElement_instances.add(this);
109
+ }
110
+ connectedCallback() {
111
+ const level = parseInt(this.getAttribute('level') || '3', 10);
112
+ __classPrivateFieldGet(this, _MarkdownHeaderButtonElement_instances, "m", _MarkdownHeaderButtonElement_setLevelStyle).call(this, level);
113
+ }
114
+ static get observedAttributes() {
115
+ return ['level'];
116
+ }
117
+ attributeChangedCallback(name, oldValue, newValue) {
118
+ if (name !== 'level')
119
+ return;
120
+ const level = parseInt(newValue || '3', 10);
121
+ __classPrivateFieldGet(this, _MarkdownHeaderButtonElement_instances, "m", _MarkdownHeaderButtonElement_setLevelStyle).call(this, level);
122
+ }
123
+ }
124
+ _MarkdownHeaderButtonElement_instances = new WeakSet(), _MarkdownHeaderButtonElement_setLevelStyle = function _MarkdownHeaderButtonElement_setLevelStyle(level) {
125
+ if (level < 1 || level > 6) {
126
+ return;
127
+ }
128
+ const prefix = `${'#'.repeat(level)} `;
129
+ styles.set(this, {
130
+ prefix
131
+ });
132
+ };
133
+ if (!window.customElements.get('md-header')) {
134
+ window.MarkdownHeaderButtonElement = MarkdownHeaderButtonElement;
135
+ window.customElements.define('md-header', MarkdownHeaderButtonElement);
136
+ }
137
+ class MarkdownBoldButtonElement extends MarkdownButtonElement {
138
+ connectedCallback() {
139
+ styles.set(this, { prefix: '**', suffix: '**', trimFirst: true });
140
+ }
141
+ }
142
+ if (!window.customElements.get('md-bold')) {
143
+ window.MarkdownBoldButtonElement = MarkdownBoldButtonElement;
144
+ window.customElements.define('md-bold', MarkdownBoldButtonElement);
145
+ }
146
+ class MarkdownItalicButtonElement extends MarkdownButtonElement {
147
+ connectedCallback() {
148
+ styles.set(this, { prefix: '_', suffix: '_', trimFirst: true });
149
+ }
150
+ }
151
+ if (!window.customElements.get('md-italic')) {
152
+ window.MarkdownItalicButtonElement = MarkdownItalicButtonElement;
153
+ window.customElements.define('md-italic', MarkdownItalicButtonElement);
154
+ }
155
+ class MarkdownQuoteButtonElement extends MarkdownButtonElement {
156
+ connectedCallback() {
157
+ styles.set(this, { prefix: '> ', multiline: true, surroundWithNewlines: true });
158
+ }
159
+ }
160
+ if (!window.customElements.get('md-quote')) {
161
+ window.MarkdownQuoteButtonElement = MarkdownQuoteButtonElement;
162
+ window.customElements.define('md-quote', MarkdownQuoteButtonElement);
163
+ }
164
+ class MarkdownCodeButtonElement extends MarkdownButtonElement {
165
+ connectedCallback() {
166
+ styles.set(this, { prefix: '`', suffix: '`', blockPrefix: '```', blockSuffix: '```' });
167
+ }
168
+ }
169
+ if (!window.customElements.get('md-code')) {
170
+ window.MarkdownCodeButtonElement = MarkdownCodeButtonElement;
171
+ window.customElements.define('md-code', MarkdownCodeButtonElement);
172
+ }
173
+ class MarkdownLinkButtonElement extends MarkdownButtonElement {
174
+ connectedCallback() {
175
+ styles.set(this, { prefix: '[', suffix: '](url)', replaceNext: 'url', scanFor: 'https?://' });
176
+ }
177
+ }
178
+ if (!window.customElements.get('md-link')) {
179
+ window.MarkdownLinkButtonElement = MarkdownLinkButtonElement;
180
+ window.customElements.define('md-link', MarkdownLinkButtonElement);
181
+ }
182
+ class MarkdownImageButtonElement extends MarkdownButtonElement {
183
+ connectedCallback() {
184
+ styles.set(this, { prefix: '![', suffix: '](url)', replaceNext: 'url', scanFor: 'https?://' });
185
+ }
186
+ }
187
+ if (!window.customElements.get('md-image')) {
188
+ window.MarkdownImageButtonElement = MarkdownImageButtonElement;
189
+ window.customElements.define('md-image', MarkdownImageButtonElement);
190
+ }
191
+ class MarkdownUnorderedListButtonElement extends MarkdownButtonElement {
192
+ connectedCallback() {
193
+ styles.set(this, { prefix: '- ', multiline: true, unorderedList: true });
194
+ }
195
+ }
196
+ if (!window.customElements.get('md-unordered-list')) {
197
+ window.MarkdownUnorderedListButtonElement = MarkdownUnorderedListButtonElement;
198
+ window.customElements.define('md-unordered-list', MarkdownUnorderedListButtonElement);
199
+ }
200
+ class MarkdownOrderedListButtonElement extends MarkdownButtonElement {
201
+ connectedCallback() {
202
+ styles.set(this, { prefix: '1. ', multiline: true, orderedList: true });
203
+ }
204
+ }
205
+ if (!window.customElements.get('md-ordered-list')) {
206
+ window.MarkdownOrderedListButtonElement = MarkdownOrderedListButtonElement;
207
+ window.customElements.define('md-ordered-list', MarkdownOrderedListButtonElement);
208
+ }
209
+ class MarkdownTaskListButtonElement extends MarkdownButtonElement {
210
+ connectedCallback() {
211
+ styles.set(this, { prefix: '- [ ] ', multiline: true, surroundWithNewlines: true });
212
+ }
213
+ }
214
+ if (!window.customElements.get('md-task-list')) {
215
+ window.MarkdownTaskListButtonElement = MarkdownTaskListButtonElement;
216
+ window.customElements.define('md-task-list', MarkdownTaskListButtonElement);
217
+ }
218
+ class MarkdownMentionButtonElement extends MarkdownButtonElement {
219
+ connectedCallback() {
220
+ styles.set(this, { prefix: '@', prefixSpace: true });
221
+ }
222
+ }
223
+ if (!window.customElements.get('md-mention')) {
224
+ window.MarkdownMentionButtonElement = MarkdownMentionButtonElement;
225
+ window.customElements.define('md-mention', MarkdownMentionButtonElement);
226
+ }
227
+ class MarkdownRefButtonElement extends MarkdownButtonElement {
228
+ connectedCallback() {
229
+ styles.set(this, { prefix: '#', prefixSpace: true });
230
+ }
231
+ }
232
+ if (!window.customElements.get('md-ref')) {
233
+ window.MarkdownRefButtonElement = MarkdownRefButtonElement;
234
+ window.customElements.define('md-ref', MarkdownRefButtonElement);
235
+ }
236
+ class MarkdownStrikethroughButtonElement extends MarkdownButtonElement {
237
+ connectedCallback() {
238
+ styles.set(this, { prefix: '~~', suffix: '~~', trimFirst: true });
239
+ }
240
+ }
241
+ if (!window.customElements.get('md-strikethrough')) {
242
+ window.MarkdownStrikethroughButtonElement = MarkdownStrikethroughButtonElement;
243
+ window.customElements.define('md-strikethrough', MarkdownStrikethroughButtonElement);
244
+ }
245
+ function applyFromToolbar(event) {
246
+ const { target, currentTarget } = event;
247
+ if (!(target instanceof Element))
248
+ return;
249
+ const mdButton = target.closest('[data-md-button]');
250
+ if (!mdButton || mdButton.closest('markdown-toolbar') !== currentTarget)
251
+ return;
252
+ const mdButtonStyle = mdButton.getAttribute('data-md-button');
253
+ const style = manualStyles[mdButtonStyle];
254
+ if (!style)
255
+ return;
256
+ event.preventDefault();
257
+ applyStyle(target, style);
258
+ }
259
+ function setFocusManagement(toolbar) {
260
+ toolbar.addEventListener('keydown', focusKeydown);
261
+ toolbar.setAttribute('tabindex', '0');
262
+ toolbar.addEventListener('focus', onToolbarFocus, { once: true });
263
+ }
264
+ function unsetFocusManagement(toolbar) {
265
+ toolbar.removeEventListener('keydown', focusKeydown);
266
+ toolbar.removeAttribute('tabindex');
267
+ toolbar.removeEventListener('focus', onToolbarFocus);
268
+ }
269
+ class MarkdownToolbarElement extends HTMLElement {
270
+ connectedCallback() {
271
+ if (!this.hasAttribute('role')) {
272
+ this.setAttribute('role', 'toolbar');
273
+ }
274
+ if (!this.hasAttribute('data-no-focus')) {
275
+ setFocusManagement(this);
276
+ }
277
+ this.addEventListener('keydown', keydown(applyFromToolbar));
278
+ this.addEventListener('click', applyFromToolbar);
279
+ }
280
+ attributeChangedCallback(name, oldValue, newValue) {
281
+ if (name !== 'data-no-focus')
282
+ return;
283
+ if (newValue === null) {
284
+ setFocusManagement(this);
285
+ }
286
+ else {
287
+ unsetFocusManagement(this);
288
+ }
289
+ }
290
+ disconnectedCallback() {
291
+ unsetFocusManagement(this);
292
+ }
293
+ get field() {
294
+ const id = this.getAttribute('for');
295
+ if (!id)
296
+ return null;
297
+ const root = 'getRootNode' in this ? this.getRootNode() : document;
298
+ let field;
299
+ if (root instanceof Document || root instanceof ShadowRoot) {
300
+ field = root.getElementById(id);
301
+ }
302
+ return field instanceof HTMLTextAreaElement ? field : null;
303
+ }
304
+ }
305
+ MarkdownToolbarElement.observedAttributes = ['data-no-focus'];
306
+ function onToolbarFocus({ target }) {
307
+ if (!(target instanceof Element))
308
+ return;
309
+ target.removeAttribute('tabindex');
310
+ let tabindex = '0';
311
+ for (const button of getButtons(target)) {
312
+ button.setAttribute('tabindex', tabindex);
313
+ if (tabindex === '0') {
314
+ button.focus();
315
+ tabindex = '-1';
316
+ }
317
+ }
318
+ }
319
+ function focusKeydown(event) {
320
+ const key = event.key;
321
+ if (key !== 'ArrowRight' && key !== 'ArrowLeft' && key !== 'Home' && key !== 'End')
322
+ return;
323
+ const toolbar = event.currentTarget;
324
+ if (!(toolbar instanceof HTMLElement))
325
+ return;
326
+ const buttons = getButtons(toolbar);
327
+ const index = buttons.indexOf(event.target);
328
+ const length = buttons.length;
329
+ if (index === -1)
330
+ return;
331
+ let n = 0;
332
+ if (key === 'ArrowLeft')
333
+ n = index - 1;
334
+ if (key === 'ArrowRight')
335
+ n = index + 1;
336
+ if (key === 'End')
337
+ n = length - 1;
338
+ if (n < 0)
339
+ n = length - 1;
340
+ if (n > length - 1)
341
+ n = 0;
342
+ for (let i = 0; i < length; i += 1) {
343
+ buttons[i].setAttribute('tabindex', i === n ? '0' : '-1');
344
+ }
345
+ event.preventDefault();
346
+ buttons[n].focus();
347
+ }
348
+ if (!window.customElements.get('markdown-toolbar')) {
349
+ window.MarkdownToolbarElement = MarkdownToolbarElement;
350
+ window.customElements.define('markdown-toolbar', MarkdownToolbarElement);
351
+ }
352
+ function isMultipleLines(string) {
353
+ return string.trim().split('\n').length > 1;
354
+ }
355
+ function repeat(string, n) {
356
+ return Array(n + 1).join(string);
357
+ }
358
+ function wordSelectionStart(text, i) {
359
+ let index = i;
360
+ while (text[index] && text[index - 1] != null && !text[index - 1].match(/\s/)) {
361
+ index--;
362
+ }
363
+ return index;
364
+ }
365
+ function wordSelectionEnd(text, i, multiline) {
366
+ let index = i;
367
+ const breakpoint = multiline ? /\n/ : /\s/;
368
+ while (text[index] && !text[index].match(breakpoint)) {
369
+ index++;
370
+ }
371
+ return index;
372
+ }
373
+ let canInsertText = null;
374
+ function insertText$1(textarea, { text, selectionStart, selectionEnd }) {
375
+ const originalSelectionStart = textarea.selectionStart;
376
+ const before = textarea.value.slice(0, originalSelectionStart);
377
+ const after = textarea.value.slice(textarea.selectionEnd);
378
+ if (canInsertText === null || canInsertText === true) {
379
+ textarea.contentEditable = 'true';
380
+ try {
381
+ canInsertText = document.execCommand('insertText', false, text);
382
+ }
383
+ catch (error) {
384
+ canInsertText = false;
385
+ }
386
+ textarea.contentEditable = 'false';
387
+ }
388
+ if (canInsertText && !textarea.value.slice(0, textarea.selectionStart).endsWith(text)) {
389
+ canInsertText = false;
390
+ }
391
+ if (!canInsertText) {
392
+ try {
393
+ document.execCommand('ms-beginUndoUnit');
394
+ }
395
+ catch (e) {
396
+ }
397
+ textarea.value = before + text + after;
398
+ try {
399
+ document.execCommand('ms-endUndoUnit');
400
+ }
401
+ catch (e) {
402
+ }
403
+ textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }));
404
+ }
405
+ if (selectionStart != null && selectionEnd != null) {
406
+ textarea.setSelectionRange(selectionStart, selectionEnd);
407
+ }
408
+ else {
409
+ textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd);
410
+ }
411
+ }
412
+ function styleSelectedText(textarea, styleArgs) {
413
+ const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
414
+ let result;
415
+ if (styleArgs.orderedList || styleArgs.unorderedList) {
416
+ result = listStyle(textarea, styleArgs);
417
+ }
418
+ else if (styleArgs.multiline && isMultipleLines(text)) {
419
+ result = multilineStyle(textarea, styleArgs);
420
+ }
421
+ else {
422
+ result = blockStyle(textarea, styleArgs);
423
+ }
424
+ insertText$1(textarea, result);
425
+ }
426
+ function expandSelectionToLine(textarea) {
427
+ const lines = textarea.value.split('\n');
428
+ let counter = 0;
429
+ for (let index = 0; index < lines.length; index++) {
430
+ const lineLength = lines[index].length + 1;
431
+ if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {
432
+ textarea.selectionStart = counter;
433
+ }
434
+ if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {
435
+ textarea.selectionEnd = counter + lineLength - 1;
436
+ }
437
+ counter += lineLength;
438
+ }
439
+ }
440
+ function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {
441
+ if (textarea.selectionStart === textarea.selectionEnd) {
442
+ textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart);
443
+ textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline);
444
+ }
445
+ else {
446
+ const expandedSelectionStart = textarea.selectionStart - prefixToUse.length;
447
+ const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length;
448
+ const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse;
449
+ const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse;
450
+ if (beginsWithPrefix && endsWithSuffix) {
451
+ textarea.selectionStart = expandedSelectionStart;
452
+ textarea.selectionEnd = expandedSelectionEnd;
453
+ }
454
+ }
455
+ return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
456
+ }
457
+ function newlinesToSurroundSelectedText(textarea) {
458
+ const beforeSelection = textarea.value.slice(0, textarea.selectionStart);
459
+ const afterSelection = textarea.value.slice(textarea.selectionEnd);
460
+ const breaksBefore = beforeSelection.match(/\n*$/);
461
+ const breaksAfter = afterSelection.match(/^\n*/);
462
+ const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0;
463
+ const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0;
464
+ let newlinesToAppend;
465
+ let newlinesToPrepend;
466
+ if (beforeSelection.match(/\S/) && newlinesBeforeSelection < 2) {
467
+ newlinesToAppend = repeat('\n', 2 - newlinesBeforeSelection);
468
+ }
469
+ if (afterSelection.match(/\S/) && newlinesAfterSelection < 2) {
470
+ newlinesToPrepend = repeat('\n', 2 - newlinesAfterSelection);
471
+ }
472
+ if (newlinesToAppend == null) {
473
+ newlinesToAppend = '';
474
+ }
475
+ if (newlinesToPrepend == null) {
476
+ newlinesToPrepend = '';
477
+ }
478
+ return { newlinesToAppend, newlinesToPrepend };
479
+ }
480
+ function blockStyle(textarea, arg) {
481
+ let newlinesToAppend;
482
+ let newlinesToPrepend;
483
+ const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines } = arg;
484
+ const originalSelectionStart = textarea.selectionStart;
485
+ const originalSelectionEnd = textarea.selectionEnd;
486
+ let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
487
+ let prefixToUse = isMultipleLines(selectedText) && blockPrefix.length > 0 ? `${blockPrefix}\n` : prefix;
488
+ let suffixToUse = isMultipleLines(selectedText) && blockSuffix.length > 0 ? `\n${blockSuffix}` : suffix;
489
+ if (prefixSpace) {
490
+ const beforeSelection = textarea.value[textarea.selectionStart - 1];
491
+ if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\s/)) {
492
+ prefixToUse = ` ${prefixToUse}`;
493
+ }
494
+ }
495
+ selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, arg.multiline);
496
+ let selectionStart = textarea.selectionStart;
497
+ let selectionEnd = textarea.selectionEnd;
498
+ const hasReplaceNext = replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0;
499
+ if (surroundWithNewlines) {
500
+ const ref = newlinesToSurroundSelectedText(textarea);
501
+ newlinesToAppend = ref.newlinesToAppend;
502
+ newlinesToPrepend = ref.newlinesToPrepend;
503
+ prefixToUse = newlinesToAppend + prefix;
504
+ suffixToUse += newlinesToPrepend;
505
+ }
506
+ if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {
507
+ const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length);
508
+ if (originalSelectionStart === originalSelectionEnd) {
509
+ let position = originalSelectionStart - prefixToUse.length;
510
+ position = Math.max(position, selectionStart);
511
+ position = Math.min(position, selectionStart + replacementText.length);
512
+ selectionStart = selectionEnd = position;
513
+ }
514
+ else {
515
+ selectionEnd = selectionStart + replacementText.length;
516
+ }
517
+ return { text: replacementText, selectionStart, selectionEnd };
518
+ }
519
+ else if (!hasReplaceNext) {
520
+ let replacementText = prefixToUse + selectedText + suffixToUse;
521
+ selectionStart = originalSelectionStart + prefixToUse.length;
522
+ selectionEnd = originalSelectionEnd + prefixToUse.length;
523
+ const whitespaceEdges = selectedText.match(/^\s*|\s*$/g);
524
+ if (arg.trimFirst && whitespaceEdges) {
525
+ const leadingWhitespace = whitespaceEdges[0] || '';
526
+ const trailingWhitespace = whitespaceEdges[1] || '';
527
+ replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace;
528
+ selectionStart += leadingWhitespace.length;
529
+ selectionEnd -= trailingWhitespace.length;
530
+ }
531
+ return { text: replacementText, selectionStart, selectionEnd };
532
+ }
533
+ else if (scanFor.length > 0 && selectedText.match(scanFor)) {
534
+ suffixToUse = suffixToUse.replace(replaceNext, selectedText);
535
+ const replacementText = prefixToUse + suffixToUse;
536
+ selectionStart = selectionEnd = selectionStart + prefixToUse.length;
537
+ return { text: replacementText, selectionStart, selectionEnd };
538
+ }
539
+ else {
540
+ const replacementText = prefixToUse + selectedText + suffixToUse;
541
+ selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext);
542
+ selectionEnd = selectionStart + replaceNext.length;
543
+ return { text: replacementText, selectionStart, selectionEnd };
544
+ }
545
+ }
546
+ function multilineStyle(textarea, arg) {
547
+ const { prefix, suffix, surroundWithNewlines } = arg;
548
+ let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
549
+ let selectionStart = textarea.selectionStart;
550
+ let selectionEnd = textarea.selectionEnd;
551
+ const lines = text.split('\n');
552
+ const undoStyle = lines.every(line => line.startsWith(prefix) && line.endsWith(suffix));
553
+ if (undoStyle) {
554
+ text = lines.map(line => line.slice(prefix.length, line.length - suffix.length)).join('\n');
555
+ selectionEnd = selectionStart + text.length;
556
+ }
557
+ else {
558
+ text = lines.map(line => prefix + line + suffix).join('\n');
559
+ if (surroundWithNewlines) {
560
+ const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea);
561
+ selectionStart += newlinesToAppend.length;
562
+ selectionEnd = selectionStart + text.length;
563
+ text = newlinesToAppend + text + newlinesToPrepend;
564
+ }
565
+ }
566
+ return { text, selectionStart, selectionEnd };
567
+ }
568
+ function undoOrderedListStyle(text) {
569
+ const lines = text.split('\n');
570
+ const orderedListRegex = /^\d+\.\s+/;
571
+ const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line));
572
+ let result = lines;
573
+ if (shouldUndoOrderedList) {
574
+ result = lines.map(line => line.replace(orderedListRegex, ''));
575
+ }
576
+ return {
577
+ text: result.join('\n'),
578
+ processed: shouldUndoOrderedList
579
+ };
580
+ }
581
+ function undoUnorderedListStyle(text) {
582
+ const lines = text.split('\n');
583
+ const unorderedListPrefix = '- ';
584
+ const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix));
585
+ let result = lines;
586
+ if (shouldUndoUnorderedList) {
587
+ result = lines.map(line => line.slice(unorderedListPrefix.length, line.length));
588
+ }
589
+ return {
590
+ text: result.join('\n'),
591
+ processed: shouldUndoUnorderedList
592
+ };
593
+ }
594
+ function makePrefix(index, unorderedList) {
595
+ if (unorderedList) {
596
+ return '- ';
597
+ }
598
+ else {
599
+ return `${index + 1}. `;
600
+ }
601
+ }
602
+ function clearExistingListStyle(style, selectedText) {
603
+ let undoResultOpositeList;
604
+ let undoResult;
605
+ let pristineText;
606
+ if (style.orderedList) {
607
+ undoResult = undoOrderedListStyle(selectedText);
608
+ undoResultOpositeList = undoUnorderedListStyle(undoResult.text);
609
+ pristineText = undoResultOpositeList.text;
610
+ }
611
+ else {
612
+ undoResult = undoUnorderedListStyle(selectedText);
613
+ undoResultOpositeList = undoOrderedListStyle(undoResult.text);
614
+ pristineText = undoResultOpositeList.text;
615
+ }
616
+ return [undoResult, undoResultOpositeList, pristineText];
617
+ }
618
+ function listStyle(textarea, style) {
619
+ const noInitialSelection = textarea.selectionStart === textarea.selectionEnd;
620
+ let selectionStart = textarea.selectionStart;
621
+ let selectionEnd = textarea.selectionEnd;
622
+ expandSelectionToLine(textarea);
623
+ const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
624
+ const [undoResult, undoResultOpositeList, pristineText] = clearExistingListStyle(style, selectedText);
625
+ const prefixedLines = pristineText.split('\n').map((value, index) => {
626
+ return `${makePrefix(index, style.unorderedList)}${value}`;
627
+ });
628
+ const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {
629
+ return previousValue + makePrefix(currentIndex, style.unorderedList).length;
630
+ }, 0);
631
+ const totalPrefixLengthOpositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {
632
+ return previousValue + makePrefix(currentIndex, !style.unorderedList).length;
633
+ }, 0);
634
+ if (undoResult.processed) {
635
+ if (noInitialSelection) {
636
+ selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0);
637
+ selectionEnd = selectionStart;
638
+ }
639
+ else {
640
+ selectionStart = textarea.selectionStart;
641
+ selectionEnd = textarea.selectionEnd - totalPrefixLength;
642
+ }
643
+ return { text: pristineText, selectionStart, selectionEnd };
644
+ }
645
+ const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea);
646
+ const text = newlinesToAppend + prefixedLines.join('\n') + newlinesToPrepend;
647
+ if (noInitialSelection) {
648
+ selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0);
649
+ selectionEnd = selectionStart;
650
+ }
651
+ else {
652
+ if (undoResultOpositeList.processed) {
653
+ selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0);
654
+ selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOpositeList;
655
+ }
656
+ else {
657
+ selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0);
658
+ selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength;
659
+ }
660
+ }
661
+ return { text, selectionStart, selectionEnd };
662
+ }
663
+ function applyStyle(button, stylesToApply) {
664
+ const toolbar = button.closest('markdown-toolbar');
665
+ if (!(toolbar instanceof MarkdownToolbarElement))
666
+ return;
667
+ const defaults = {
668
+ prefix: '',
669
+ suffix: '',
670
+ blockPrefix: '',
671
+ blockSuffix: '',
672
+ multiline: false,
673
+ replaceNext: '',
674
+ prefixSpace: false,
675
+ scanFor: '',
676
+ surroundWithNewlines: false,
677
+ orderedList: false,
678
+ unorderedList: false,
679
+ trimFirst: false
680
+ };
681
+ const style = Object.assign(Object.assign({}, defaults), stylesToApply);
682
+ const field = toolbar.field;
683
+ if (field) {
684
+ field.focus();
685
+ styleSelectedText(field, style);
686
+ }
687
+ }
688
+
689
+ var sparkMd5 = {
690
+ exports: {}
691
+ };
692
+
693
+ (function(module, exports) {
694
+ (function(factory) {
695
+ {
696
+ module.exports = factory();
697
+ }
698
+ })((function(undefined$1) {
699
+ var hex_chr = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" ];
700
+ function md5cycle(x, k) {
701
+ var a = x[0], b = x[1], c = x[2], d = x[3];
702
+ a += (b & c | ~b & d) + k[0] - 680876936 | 0;
703
+ a = (a << 7 | a >>> 25) + b | 0;
704
+ d += (a & b | ~a & c) + k[1] - 389564586 | 0;
705
+ d = (d << 12 | d >>> 20) + a | 0;
706
+ c += (d & a | ~d & b) + k[2] + 606105819 | 0;
707
+ c = (c << 17 | c >>> 15) + d | 0;
708
+ b += (c & d | ~c & a) + k[3] - 1044525330 | 0;
709
+ b = (b << 22 | b >>> 10) + c | 0;
710
+ a += (b & c | ~b & d) + k[4] - 176418897 | 0;
711
+ a = (a << 7 | a >>> 25) + b | 0;
712
+ d += (a & b | ~a & c) + k[5] + 1200080426 | 0;
713
+ d = (d << 12 | d >>> 20) + a | 0;
714
+ c += (d & a | ~d & b) + k[6] - 1473231341 | 0;
715
+ c = (c << 17 | c >>> 15) + d | 0;
716
+ b += (c & d | ~c & a) + k[7] - 45705983 | 0;
717
+ b = (b << 22 | b >>> 10) + c | 0;
718
+ a += (b & c | ~b & d) + k[8] + 1770035416 | 0;
719
+ a = (a << 7 | a >>> 25) + b | 0;
720
+ d += (a & b | ~a & c) + k[9] - 1958414417 | 0;
721
+ d = (d << 12 | d >>> 20) + a | 0;
722
+ c += (d & a | ~d & b) + k[10] - 42063 | 0;
723
+ c = (c << 17 | c >>> 15) + d | 0;
724
+ b += (c & d | ~c & a) + k[11] - 1990404162 | 0;
725
+ b = (b << 22 | b >>> 10) + c | 0;
726
+ a += (b & c | ~b & d) + k[12] + 1804603682 | 0;
727
+ a = (a << 7 | a >>> 25) + b | 0;
728
+ d += (a & b | ~a & c) + k[13] - 40341101 | 0;
729
+ d = (d << 12 | d >>> 20) + a | 0;
730
+ c += (d & a | ~d & b) + k[14] - 1502002290 | 0;
731
+ c = (c << 17 | c >>> 15) + d | 0;
732
+ b += (c & d | ~c & a) + k[15] + 1236535329 | 0;
733
+ b = (b << 22 | b >>> 10) + c | 0;
734
+ a += (b & d | c & ~d) + k[1] - 165796510 | 0;
735
+ a = (a << 5 | a >>> 27) + b | 0;
736
+ d += (a & c | b & ~c) + k[6] - 1069501632 | 0;
737
+ d = (d << 9 | d >>> 23) + a | 0;
738
+ c += (d & b | a & ~b) + k[11] + 643717713 | 0;
739
+ c = (c << 14 | c >>> 18) + d | 0;
740
+ b += (c & a | d & ~a) + k[0] - 373897302 | 0;
741
+ b = (b << 20 | b >>> 12) + c | 0;
742
+ a += (b & d | c & ~d) + k[5] - 701558691 | 0;
743
+ a = (a << 5 | a >>> 27) + b | 0;
744
+ d += (a & c | b & ~c) + k[10] + 38016083 | 0;
745
+ d = (d << 9 | d >>> 23) + a | 0;
746
+ c += (d & b | a & ~b) + k[15] - 660478335 | 0;
747
+ c = (c << 14 | c >>> 18) + d | 0;
748
+ b += (c & a | d & ~a) + k[4] - 405537848 | 0;
749
+ b = (b << 20 | b >>> 12) + c | 0;
750
+ a += (b & d | c & ~d) + k[9] + 568446438 | 0;
751
+ a = (a << 5 | a >>> 27) + b | 0;
752
+ d += (a & c | b & ~c) + k[14] - 1019803690 | 0;
753
+ d = (d << 9 | d >>> 23) + a | 0;
754
+ c += (d & b | a & ~b) + k[3] - 187363961 | 0;
755
+ c = (c << 14 | c >>> 18) + d | 0;
756
+ b += (c & a | d & ~a) + k[8] + 1163531501 | 0;
757
+ b = (b << 20 | b >>> 12) + c | 0;
758
+ a += (b & d | c & ~d) + k[13] - 1444681467 | 0;
759
+ a = (a << 5 | a >>> 27) + b | 0;
760
+ d += (a & c | b & ~c) + k[2] - 51403784 | 0;
761
+ d = (d << 9 | d >>> 23) + a | 0;
762
+ c += (d & b | a & ~b) + k[7] + 1735328473 | 0;
763
+ c = (c << 14 | c >>> 18) + d | 0;
764
+ b += (c & a | d & ~a) + k[12] - 1926607734 | 0;
765
+ b = (b << 20 | b >>> 12) + c | 0;
766
+ a += (b ^ c ^ d) + k[5] - 378558 | 0;
767
+ a = (a << 4 | a >>> 28) + b | 0;
768
+ d += (a ^ b ^ c) + k[8] - 2022574463 | 0;
769
+ d = (d << 11 | d >>> 21) + a | 0;
770
+ c += (d ^ a ^ b) + k[11] + 1839030562 | 0;
771
+ c = (c << 16 | c >>> 16) + d | 0;
772
+ b += (c ^ d ^ a) + k[14] - 35309556 | 0;
773
+ b = (b << 23 | b >>> 9) + c | 0;
774
+ a += (b ^ c ^ d) + k[1] - 1530992060 | 0;
775
+ a = (a << 4 | a >>> 28) + b | 0;
776
+ d += (a ^ b ^ c) + k[4] + 1272893353 | 0;
777
+ d = (d << 11 | d >>> 21) + a | 0;
778
+ c += (d ^ a ^ b) + k[7] - 155497632 | 0;
779
+ c = (c << 16 | c >>> 16) + d | 0;
780
+ b += (c ^ d ^ a) + k[10] - 1094730640 | 0;
781
+ b = (b << 23 | b >>> 9) + c | 0;
782
+ a += (b ^ c ^ d) + k[13] + 681279174 | 0;
783
+ a = (a << 4 | a >>> 28) + b | 0;
784
+ d += (a ^ b ^ c) + k[0] - 358537222 | 0;
785
+ d = (d << 11 | d >>> 21) + a | 0;
786
+ c += (d ^ a ^ b) + k[3] - 722521979 | 0;
787
+ c = (c << 16 | c >>> 16) + d | 0;
788
+ b += (c ^ d ^ a) + k[6] + 76029189 | 0;
789
+ b = (b << 23 | b >>> 9) + c | 0;
790
+ a += (b ^ c ^ d) + k[9] - 640364487 | 0;
791
+ a = (a << 4 | a >>> 28) + b | 0;
792
+ d += (a ^ b ^ c) + k[12] - 421815835 | 0;
793
+ d = (d << 11 | d >>> 21) + a | 0;
794
+ c += (d ^ a ^ b) + k[15] + 530742520 | 0;
795
+ c = (c << 16 | c >>> 16) + d | 0;
796
+ b += (c ^ d ^ a) + k[2] - 995338651 | 0;
797
+ b = (b << 23 | b >>> 9) + c | 0;
798
+ a += (c ^ (b | ~d)) + k[0] - 198630844 | 0;
799
+ a = (a << 6 | a >>> 26) + b | 0;
800
+ d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0;
801
+ d = (d << 10 | d >>> 22) + a | 0;
802
+ c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0;
803
+ c = (c << 15 | c >>> 17) + d | 0;
804
+ b += (d ^ (c | ~a)) + k[5] - 57434055 | 0;
805
+ b = (b << 21 | b >>> 11) + c | 0;
806
+ a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0;
807
+ a = (a << 6 | a >>> 26) + b | 0;
808
+ d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0;
809
+ d = (d << 10 | d >>> 22) + a | 0;
810
+ c += (a ^ (d | ~b)) + k[10] - 1051523 | 0;
811
+ c = (c << 15 | c >>> 17) + d | 0;
812
+ b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0;
813
+ b = (b << 21 | b >>> 11) + c | 0;
814
+ a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0;
815
+ a = (a << 6 | a >>> 26) + b | 0;
816
+ d += (b ^ (a | ~c)) + k[15] - 30611744 | 0;
817
+ d = (d << 10 | d >>> 22) + a | 0;
818
+ c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0;
819
+ c = (c << 15 | c >>> 17) + d | 0;
820
+ b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0;
821
+ b = (b << 21 | b >>> 11) + c | 0;
822
+ a += (c ^ (b | ~d)) + k[4] - 145523070 | 0;
823
+ a = (a << 6 | a >>> 26) + b | 0;
824
+ d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0;
825
+ d = (d << 10 | d >>> 22) + a | 0;
826
+ c += (a ^ (d | ~b)) + k[2] + 718787259 | 0;
827
+ c = (c << 15 | c >>> 17) + d | 0;
828
+ b += (d ^ (c | ~a)) + k[9] - 343485551 | 0;
829
+ b = (b << 21 | b >>> 11) + c | 0;
830
+ x[0] = a + x[0] | 0;
831
+ x[1] = b + x[1] | 0;
832
+ x[2] = c + x[2] | 0;
833
+ x[3] = d + x[3] | 0;
834
+ }
835
+ function md5blk(s) {
836
+ var md5blks = [], i;
837
+ for (i = 0; i < 64; i += 4) {
838
+ md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
839
+ }
840
+ return md5blks;
841
+ }
842
+ function md5blk_array(a) {
843
+ var md5blks = [], i;
844
+ for (i = 0; i < 64; i += 4) {
845
+ md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);
846
+ }
847
+ return md5blks;
848
+ }
849
+ function md51(s) {
850
+ var n = s.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;
851
+ for (i = 64; i <= n; i += 64) {
852
+ md5cycle(state, md5blk(s.substring(i - 64, i)));
853
+ }
854
+ s = s.substring(i - 64);
855
+ length = s.length;
856
+ tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
857
+ for (i = 0; i < length; i += 1) {
858
+ tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3);
859
+ }
860
+ tail[i >> 2] |= 128 << (i % 4 << 3);
861
+ if (i > 55) {
862
+ md5cycle(state, tail);
863
+ for (i = 0; i < 16; i += 1) {
864
+ tail[i] = 0;
865
+ }
866
+ }
867
+ tmp = n * 8;
868
+ tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
869
+ lo = parseInt(tmp[2], 16);
870
+ hi = parseInt(tmp[1], 16) || 0;
871
+ tail[14] = lo;
872
+ tail[15] = hi;
873
+ md5cycle(state, tail);
874
+ return state;
875
+ }
876
+ function md51_array(a) {
877
+ var n = a.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;
878
+ for (i = 64; i <= n; i += 64) {
879
+ md5cycle(state, md5blk_array(a.subarray(i - 64, i)));
880
+ }
881
+ a = i - 64 < n ? a.subarray(i - 64) : new Uint8Array(0);
882
+ length = a.length;
883
+ tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
884
+ for (i = 0; i < length; i += 1) {
885
+ tail[i >> 2] |= a[i] << (i % 4 << 3);
886
+ }
887
+ tail[i >> 2] |= 128 << (i % 4 << 3);
888
+ if (i > 55) {
889
+ md5cycle(state, tail);
890
+ for (i = 0; i < 16; i += 1) {
891
+ tail[i] = 0;
892
+ }
893
+ }
894
+ tmp = n * 8;
895
+ tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
896
+ lo = parseInt(tmp[2], 16);
897
+ hi = parseInt(tmp[1], 16) || 0;
898
+ tail[14] = lo;
899
+ tail[15] = hi;
900
+ md5cycle(state, tail);
901
+ return state;
902
+ }
903
+ function rhex(n) {
904
+ var s = "", j;
905
+ for (j = 0; j < 4; j += 1) {
906
+ s += hex_chr[n >> j * 8 + 4 & 15] + hex_chr[n >> j * 8 & 15];
907
+ }
908
+ return s;
909
+ }
910
+ function hex(x) {
911
+ var i;
912
+ for (i = 0; i < x.length; i += 1) {
913
+ x[i] = rhex(x[i]);
914
+ }
915
+ return x.join("");
916
+ }
917
+ if (hex(md51("hello")) !== "5d41402abc4b2a76b9719d911017c592") ;
918
+ if (typeof ArrayBuffer !== "undefined" && !ArrayBuffer.prototype.slice) {
919
+ (function() {
920
+ function clamp(val, length) {
921
+ val = val | 0 || 0;
922
+ if (val < 0) {
923
+ return Math.max(val + length, 0);
924
+ }
925
+ return Math.min(val, length);
926
+ }
927
+ ArrayBuffer.prototype.slice = function(from, to) {
928
+ var length = this.byteLength, begin = clamp(from, length), end = length, num, target, targetArray, sourceArray;
929
+ if (to !== undefined$1) {
930
+ end = clamp(to, length);
931
+ }
932
+ if (begin > end) {
933
+ return new ArrayBuffer(0);
934
+ }
935
+ num = end - begin;
936
+ target = new ArrayBuffer(num);
937
+ targetArray = new Uint8Array(target);
938
+ sourceArray = new Uint8Array(this, begin, num);
939
+ targetArray.set(sourceArray);
940
+ return target;
941
+ };
942
+ })();
943
+ }
944
+ function toUtf8(str) {
945
+ if (/[\u0080-\uFFFF]/.test(str)) {
946
+ str = unescape(encodeURIComponent(str));
947
+ }
948
+ return str;
949
+ }
950
+ function utf8Str2ArrayBuffer(str, returnUInt8Array) {
951
+ var length = str.length, buff = new ArrayBuffer(length), arr = new Uint8Array(buff), i;
952
+ for (i = 0; i < length; i += 1) {
953
+ arr[i] = str.charCodeAt(i);
954
+ }
955
+ return returnUInt8Array ? arr : buff;
956
+ }
957
+ function arrayBuffer2Utf8Str(buff) {
958
+ return String.fromCharCode.apply(null, new Uint8Array(buff));
959
+ }
960
+ function concatenateArrayBuffers(first, second, returnUInt8Array) {
961
+ var result = new Uint8Array(first.byteLength + second.byteLength);
962
+ result.set(new Uint8Array(first));
963
+ result.set(new Uint8Array(second), first.byteLength);
964
+ return result ;
965
+ }
966
+ function hexToBinaryString(hex) {
967
+ var bytes = [], length = hex.length, x;
968
+ for (x = 0; x < length - 1; x += 2) {
969
+ bytes.push(parseInt(hex.substr(x, 2), 16));
970
+ }
971
+ return String.fromCharCode.apply(String, bytes);
972
+ }
973
+ function SparkMD5() {
974
+ this.reset();
975
+ }
976
+ SparkMD5.prototype.append = function(str) {
977
+ this.appendBinary(toUtf8(str));
978
+ return this;
979
+ };
980
+ SparkMD5.prototype.appendBinary = function(contents) {
981
+ this._buff += contents;
982
+ this._length += contents.length;
983
+ var length = this._buff.length, i;
984
+ for (i = 64; i <= length; i += 64) {
985
+ md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i)));
986
+ }
987
+ this._buff = this._buff.substring(i - 64);
988
+ return this;
989
+ };
990
+ SparkMD5.prototype.end = function(raw) {
991
+ var buff = this._buff, length = buff.length, i, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], ret;
992
+ for (i = 0; i < length; i += 1) {
993
+ tail[i >> 2] |= buff.charCodeAt(i) << (i % 4 << 3);
994
+ }
995
+ this._finish(tail, length);
996
+ ret = hex(this._hash);
997
+ if (raw) {
998
+ ret = hexToBinaryString(ret);
999
+ }
1000
+ this.reset();
1001
+ return ret;
1002
+ };
1003
+ SparkMD5.prototype.reset = function() {
1004
+ this._buff = "";
1005
+ this._length = 0;
1006
+ this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];
1007
+ return this;
1008
+ };
1009
+ SparkMD5.prototype.getState = function() {
1010
+ return {
1011
+ buff: this._buff,
1012
+ length: this._length,
1013
+ hash: this._hash.slice()
1014
+ };
1015
+ };
1016
+ SparkMD5.prototype.setState = function(state) {
1017
+ this._buff = state.buff;
1018
+ this._length = state.length;
1019
+ this._hash = state.hash;
1020
+ return this;
1021
+ };
1022
+ SparkMD5.prototype.destroy = function() {
1023
+ delete this._hash;
1024
+ delete this._buff;
1025
+ delete this._length;
1026
+ };
1027
+ SparkMD5.prototype._finish = function(tail, length) {
1028
+ var i = length, tmp, lo, hi;
1029
+ tail[i >> 2] |= 128 << (i % 4 << 3);
1030
+ if (i > 55) {
1031
+ md5cycle(this._hash, tail);
1032
+ for (i = 0; i < 16; i += 1) {
1033
+ tail[i] = 0;
1034
+ }
1035
+ }
1036
+ tmp = this._length * 8;
1037
+ tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
1038
+ lo = parseInt(tmp[2], 16);
1039
+ hi = parseInt(tmp[1], 16) || 0;
1040
+ tail[14] = lo;
1041
+ tail[15] = hi;
1042
+ md5cycle(this._hash, tail);
1043
+ };
1044
+ SparkMD5.hash = function(str, raw) {
1045
+ return SparkMD5.hashBinary(toUtf8(str), raw);
1046
+ };
1047
+ SparkMD5.hashBinary = function(content, raw) {
1048
+ var hash = md51(content), ret = hex(hash);
1049
+ return raw ? hexToBinaryString(ret) : ret;
1050
+ };
1051
+ SparkMD5.ArrayBuffer = function() {
1052
+ this.reset();
1053
+ };
1054
+ SparkMD5.ArrayBuffer.prototype.append = function(arr) {
1055
+ var buff = concatenateArrayBuffers(this._buff.buffer, arr), length = buff.length, i;
1056
+ this._length += arr.byteLength;
1057
+ for (i = 64; i <= length; i += 64) {
1058
+ md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i)));
1059
+ }
1060
+ this._buff = i - 64 < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0);
1061
+ return this;
1062
+ };
1063
+ SparkMD5.ArrayBuffer.prototype.end = function(raw) {
1064
+ var buff = this._buff, length = buff.length, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], i, ret;
1065
+ for (i = 0; i < length; i += 1) {
1066
+ tail[i >> 2] |= buff[i] << (i % 4 << 3);
1067
+ }
1068
+ this._finish(tail, length);
1069
+ ret = hex(this._hash);
1070
+ if (raw) {
1071
+ ret = hexToBinaryString(ret);
1072
+ }
1073
+ this.reset();
1074
+ return ret;
1075
+ };
1076
+ SparkMD5.ArrayBuffer.prototype.reset = function() {
1077
+ this._buff = new Uint8Array(0);
1078
+ this._length = 0;
1079
+ this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];
1080
+ return this;
1081
+ };
1082
+ SparkMD5.ArrayBuffer.prototype.getState = function() {
1083
+ var state = SparkMD5.prototype.getState.call(this);
1084
+ state.buff = arrayBuffer2Utf8Str(state.buff);
1085
+ return state;
1086
+ };
1087
+ SparkMD5.ArrayBuffer.prototype.setState = function(state) {
1088
+ state.buff = utf8Str2ArrayBuffer(state.buff, true);
1089
+ return SparkMD5.prototype.setState.call(this, state);
1090
+ };
1091
+ SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;
1092
+ SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;
1093
+ SparkMD5.ArrayBuffer.hash = function(arr, raw) {
1094
+ var hash = md51_array(new Uint8Array(arr)), ret = hex(hash);
1095
+ return raw ? hexToBinaryString(ret) : ret;
1096
+ };
1097
+ return SparkMD5;
1098
+ }));
1099
+ })(sparkMd5);
1100
+
1101
+ var SparkMD5 = sparkMd5.exports;
1102
+
1103
+ const fileSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
1104
+
1105
+ class FileChecksum {
1106
+ static create(file, callback) {
1107
+ const instance = new FileChecksum(file);
1108
+ instance.create(callback);
1109
+ }
1110
+ constructor(file) {
1111
+ this.file = file;
1112
+ this.chunkSize = 2097152;
1113
+ this.chunkCount = Math.ceil(this.file.size / this.chunkSize);
1114
+ this.chunkIndex = 0;
1115
+ }
1116
+ create(callback) {
1117
+ this.callback = callback;
1118
+ this.md5Buffer = new SparkMD5.ArrayBuffer;
1119
+ this.fileReader = new FileReader;
1120
+ this.fileReader.addEventListener("load", (event => this.fileReaderDidLoad(event)));
1121
+ this.fileReader.addEventListener("error", (event => this.fileReaderDidError(event)));
1122
+ this.readNextChunk();
1123
+ }
1124
+ fileReaderDidLoad(event) {
1125
+ this.md5Buffer.append(event.target.result);
1126
+ if (!this.readNextChunk()) {
1127
+ const binaryDigest = this.md5Buffer.end(true);
1128
+ const base64digest = btoa(binaryDigest);
1129
+ this.callback(null, base64digest);
1130
+ }
1131
+ }
1132
+ fileReaderDidError(event) {
1133
+ this.callback(`Error reading ${this.file.name}`);
1134
+ }
1135
+ readNextChunk() {
1136
+ if (this.chunkIndex < this.chunkCount || this.chunkIndex == 0 && this.chunkCount == 0) {
1137
+ const start = this.chunkIndex * this.chunkSize;
1138
+ const end = Math.min(start + this.chunkSize, this.file.size);
1139
+ const bytes = fileSlice.call(this.file, start, end);
1140
+ this.fileReader.readAsArrayBuffer(bytes);
1141
+ this.chunkIndex++;
1142
+ return true;
1143
+ } else {
1144
+ return false;
1145
+ }
1146
+ }
1147
+ }
1148
+
1149
+ function getMetaValue(name) {
1150
+ const element = findElement(document.head, `meta[name="${name}"]`);
1151
+ if (element) {
1152
+ return element.getAttribute("content");
1153
+ }
1154
+ }
1155
+
1156
+ function findElements(root, selector) {
1157
+ if (typeof root == "string") {
1158
+ selector = root;
1159
+ root = document;
1160
+ }
1161
+ const elements = root.querySelectorAll(selector);
1162
+ return toArray(elements);
1163
+ }
1164
+
1165
+ function findElement(root, selector) {
1166
+ if (typeof root == "string") {
1167
+ selector = root;
1168
+ root = document;
1169
+ }
1170
+ return root.querySelector(selector);
1171
+ }
1172
+
1173
+ function dispatchEvent(element, type, eventInit = {}) {
1174
+ const {disabled: disabled} = element;
1175
+ const {bubbles: bubbles, cancelable: cancelable, detail: detail} = eventInit;
1176
+ const event = document.createEvent("Event");
1177
+ event.initEvent(type, bubbles || true, cancelable || true);
1178
+ event.detail = detail || {};
1179
+ try {
1180
+ element.disabled = false;
1181
+ element.dispatchEvent(event);
1182
+ } finally {
1183
+ element.disabled = disabled;
1184
+ }
1185
+ return event;
1186
+ }
1187
+
1188
+ function toArray(value) {
1189
+ if (Array.isArray(value)) {
1190
+ return value;
1191
+ } else if (Array.from) {
1192
+ return Array.from(value);
1193
+ } else {
1194
+ return [].slice.call(value);
1195
+ }
1196
+ }
1197
+
1198
+ class BlobRecord {
1199
+ constructor(file, checksum, url, customHeaders = {}) {
1200
+ this.file = file;
1201
+ this.attributes = {
1202
+ filename: file.name,
1203
+ content_type: file.type || "application/octet-stream",
1204
+ byte_size: file.size,
1205
+ checksum: checksum
1206
+ };
1207
+ this.xhr = new XMLHttpRequest;
1208
+ this.xhr.open("POST", url, true);
1209
+ this.xhr.responseType = "json";
1210
+ this.xhr.setRequestHeader("Content-Type", "application/json");
1211
+ this.xhr.setRequestHeader("Accept", "application/json");
1212
+ this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
1213
+ Object.keys(customHeaders).forEach((headerKey => {
1214
+ this.xhr.setRequestHeader(headerKey, customHeaders[headerKey]);
1215
+ }));
1216
+ const csrfToken = getMetaValue("csrf-token");
1217
+ if (csrfToken != undefined) {
1218
+ this.xhr.setRequestHeader("X-CSRF-Token", csrfToken);
1219
+ }
1220
+ this.xhr.addEventListener("load", (event => this.requestDidLoad(event)));
1221
+ this.xhr.addEventListener("error", (event => this.requestDidError(event)));
1222
+ }
1223
+ get status() {
1224
+ return this.xhr.status;
1225
+ }
1226
+ get response() {
1227
+ const {responseType: responseType, response: response} = this.xhr;
1228
+ if (responseType == "json") {
1229
+ return response;
1230
+ } else {
1231
+ return JSON.parse(response);
1232
+ }
1233
+ }
1234
+ create(callback) {
1235
+ this.callback = callback;
1236
+ this.xhr.send(JSON.stringify({
1237
+ blob: this.attributes
1238
+ }));
1239
+ }
1240
+ requestDidLoad(event) {
1241
+ if (this.status >= 200 && this.status < 300) {
1242
+ const {response: response} = this;
1243
+ const {direct_upload: direct_upload} = response;
1244
+ delete response.direct_upload;
1245
+ this.attributes = response;
1246
+ this.directUploadData = direct_upload;
1247
+ this.callback(null, this.toJSON());
1248
+ } else {
1249
+ this.requestDidError(event);
1250
+ }
1251
+ }
1252
+ requestDidError(event) {
1253
+ this.callback(`Error creating Blob for "${this.file.name}". Status: ${this.status}`);
1254
+ }
1255
+ toJSON() {
1256
+ const result = {};
1257
+ for (const key in this.attributes) {
1258
+ result[key] = this.attributes[key];
1259
+ }
1260
+ return result;
1261
+ }
1262
+ }
1263
+
1264
+ class BlobUpload {
1265
+ constructor(blob) {
1266
+ this.blob = blob;
1267
+ this.file = blob.file;
1268
+ const {url: url, headers: headers} = blob.directUploadData;
1269
+ this.xhr = new XMLHttpRequest;
1270
+ this.xhr.open("PUT", url, true);
1271
+ this.xhr.responseType = "text";
1272
+ for (const key in headers) {
1273
+ this.xhr.setRequestHeader(key, headers[key]);
1274
+ }
1275
+ this.xhr.addEventListener("load", (event => this.requestDidLoad(event)));
1276
+ this.xhr.addEventListener("error", (event => this.requestDidError(event)));
1277
+ }
1278
+ create(callback) {
1279
+ this.callback = callback;
1280
+ this.xhr.send(this.file.slice());
1281
+ }
1282
+ requestDidLoad(event) {
1283
+ const {status: status, response: response} = this.xhr;
1284
+ if (status >= 200 && status < 300) {
1285
+ this.callback(null, response);
1286
+ } else {
1287
+ this.requestDidError(event);
1288
+ }
1289
+ }
1290
+ requestDidError(event) {
1291
+ this.callback(`Error storing "${this.file.name}". Status: ${this.xhr.status}`);
1292
+ }
1293
+ }
1294
+
1295
+ let id = 0;
1296
+
1297
+ class DirectUpload {
1298
+ constructor(file, url, delegate, customHeaders = {}) {
1299
+ this.id = ++id;
1300
+ this.file = file;
1301
+ this.url = url;
1302
+ this.delegate = delegate;
1303
+ this.customHeaders = customHeaders;
1304
+ }
1305
+ create(callback) {
1306
+ FileChecksum.create(this.file, ((error, checksum) => {
1307
+ if (error) {
1308
+ callback(error);
1309
+ return;
1310
+ }
1311
+ const blob = new BlobRecord(this.file, checksum, this.url, this.customHeaders);
1312
+ notify(this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr);
1313
+ blob.create((error => {
1314
+ if (error) {
1315
+ callback(error);
1316
+ } else {
1317
+ const upload = new BlobUpload(blob);
1318
+ notify(this.delegate, "directUploadWillStoreFileWithXHR", upload.xhr);
1319
+ upload.create((error => {
1320
+ if (error) {
1321
+ callback(error);
1322
+ } else {
1323
+ callback(null, blob.toJSON());
1324
+ }
1325
+ }));
1326
+ }
1327
+ }));
1328
+ }));
1329
+ }
1330
+ }
1331
+
1332
+ function notify(object, methodName, ...messages) {
1333
+ if (object && typeof object[methodName] == "function") {
1334
+ return object[methodName](...messages);
1335
+ }
1336
+ }
1337
+
1338
+ class DirectUploadController {
1339
+ constructor(input, file) {
1340
+ this.input = input;
1341
+ this.file = file;
1342
+ this.directUpload = new DirectUpload(this.file, this.url, this);
1343
+ this.dispatch("initialize");
1344
+ }
1345
+ start(callback) {
1346
+ const hiddenInput = document.createElement("input");
1347
+ hiddenInput.type = "hidden";
1348
+ hiddenInput.name = this.input.name;
1349
+ this.input.insertAdjacentElement("beforebegin", hiddenInput);
1350
+ this.dispatch("start");
1351
+ this.directUpload.create(((error, attributes) => {
1352
+ if (error) {
1353
+ hiddenInput.parentNode.removeChild(hiddenInput);
1354
+ this.dispatchError(error);
1355
+ } else {
1356
+ hiddenInput.value = attributes.signed_id;
1357
+ }
1358
+ this.dispatch("end");
1359
+ callback(error);
1360
+ }));
1361
+ }
1362
+ uploadRequestDidProgress(event) {
1363
+ const progress = event.loaded / event.total * 100;
1364
+ if (progress) {
1365
+ this.dispatch("progress", {
1366
+ progress: progress
1367
+ });
1368
+ }
1369
+ }
1370
+ get url() {
1371
+ return this.input.getAttribute("data-direct-upload-url");
1372
+ }
1373
+ dispatch(name, detail = {}) {
1374
+ detail.file = this.file;
1375
+ detail.id = this.directUpload.id;
1376
+ return dispatchEvent(this.input, `direct-upload:${name}`, {
1377
+ detail: detail
1378
+ });
1379
+ }
1380
+ dispatchError(error) {
1381
+ const event = this.dispatch("error", {
1382
+ error: error
1383
+ });
1384
+ if (!event.defaultPrevented) {
1385
+ alert(error);
1386
+ }
1387
+ }
1388
+ directUploadWillCreateBlobWithXHR(xhr) {
1389
+ this.dispatch("before-blob-request", {
1390
+ xhr: xhr
1391
+ });
1392
+ }
1393
+ directUploadWillStoreFileWithXHR(xhr) {
1394
+ this.dispatch("before-storage-request", {
1395
+ xhr: xhr
1396
+ });
1397
+ xhr.upload.addEventListener("progress", (event => this.uploadRequestDidProgress(event)));
1398
+ }
1399
+ }
1400
+
1401
+ const inputSelector = "input[type=file][data-direct-upload-url]:not([disabled])";
1402
+
1403
+ class DirectUploadsController {
1404
+ constructor(form) {
1405
+ this.form = form;
1406
+ this.inputs = findElements(form, inputSelector).filter((input => input.files.length));
1407
+ }
1408
+ start(callback) {
1409
+ const controllers = this.createDirectUploadControllers();
1410
+ const startNextController = () => {
1411
+ const controller = controllers.shift();
1412
+ if (controller) {
1413
+ controller.start((error => {
1414
+ if (error) {
1415
+ callback(error);
1416
+ this.dispatch("end");
1417
+ } else {
1418
+ startNextController();
1419
+ }
1420
+ }));
1421
+ } else {
1422
+ callback();
1423
+ this.dispatch("end");
1424
+ }
1425
+ };
1426
+ this.dispatch("start");
1427
+ startNextController();
1428
+ }
1429
+ createDirectUploadControllers() {
1430
+ const controllers = [];
1431
+ this.inputs.forEach((input => {
1432
+ toArray(input.files).forEach((file => {
1433
+ const controller = new DirectUploadController(input, file);
1434
+ controllers.push(controller);
1435
+ }));
1436
+ }));
1437
+ return controllers;
1438
+ }
1439
+ dispatch(name, detail = {}) {
1440
+ return dispatchEvent(this.form, `direct-uploads:${name}`, {
1441
+ detail: detail
1442
+ });
1443
+ }
1444
+ }
1445
+
1446
+ const processingAttribute = "data-direct-uploads-processing";
1447
+
1448
+ const submitButtonsByForm = new WeakMap;
1449
+
1450
+ let started = false;
1451
+
1452
+ function start() {
1453
+ if (!started) {
1454
+ started = true;
1455
+ document.addEventListener("click", didClick, true);
1456
+ document.addEventListener("submit", didSubmitForm, true);
1457
+ document.addEventListener("ajax:before", didSubmitRemoteElement);
1458
+ }
1459
+ }
1460
+
1461
+ function didClick(event) {
1462
+ const button = event.target.closest("button, input");
1463
+ if (button && button.type === "submit" && button.form) {
1464
+ submitButtonsByForm.set(button.form, button);
1465
+ }
1466
+ }
1467
+
1468
+ function didSubmitForm(event) {
1469
+ handleFormSubmissionEvent(event);
1470
+ }
1471
+
1472
+ function didSubmitRemoteElement(event) {
1473
+ if (event.target.tagName == "FORM") {
1474
+ handleFormSubmissionEvent(event);
1475
+ }
1476
+ }
1477
+
1478
+ function handleFormSubmissionEvent(event) {
1479
+ const form = event.target;
1480
+ if (form.hasAttribute(processingAttribute)) {
1481
+ event.preventDefault();
1482
+ return;
1483
+ }
1484
+ const controller = new DirectUploadsController(form);
1485
+ const {inputs: inputs} = controller;
1486
+ if (inputs.length) {
1487
+ event.preventDefault();
1488
+ form.setAttribute(processingAttribute, "");
1489
+ inputs.forEach(disable);
1490
+ controller.start((error => {
1491
+ form.removeAttribute(processingAttribute);
1492
+ if (error) {
1493
+ inputs.forEach(enable);
1494
+ } else {
1495
+ submitForm(form);
1496
+ }
1497
+ }));
1498
+ }
1499
+ }
1500
+
1501
+ function submitForm(form) {
1502
+ let button = submitButtonsByForm.get(form) || findElement(form, "input[type=submit], button[type=submit]");
1503
+ if (button) {
1504
+ const {disabled: disabled} = button;
1505
+ button.disabled = false;
1506
+ button.focus();
1507
+ button.click();
1508
+ button.disabled = disabled;
1509
+ } else {
1510
+ button = document.createElement("input");
1511
+ button.type = "submit";
1512
+ button.style.display = "none";
1513
+ form.appendChild(button);
1514
+ button.click();
1515
+ form.removeChild(button);
1516
+ }
1517
+ submitButtonsByForm.delete(form);
1518
+ }
1519
+
1520
+ function disable(input) {
1521
+ input.disabled = true;
1522
+ }
1523
+
1524
+ function enable(input) {
1525
+ input.disabled = false;
1526
+ }
1527
+
1528
+ function autostart() {
1529
+ if (window.ActiveStorage) {
1530
+ start();
1531
+ }
1532
+ }
1533
+
1534
+ setTimeout(autostart, 1);
1535
+
1536
+ class FetchResponse {
1537
+ constructor (response) {
1538
+ this.response = response;
1539
+ }
1540
+
1541
+ get statusCode () {
1542
+ return this.response.status
1543
+ }
1544
+
1545
+ get redirected () {
1546
+ return this.response.redirected
1547
+ }
1548
+
1549
+ get ok () {
1550
+ return this.response.ok
1551
+ }
1552
+
1553
+ get unauthenticated () {
1554
+ return this.statusCode === 401
1555
+ }
1556
+
1557
+ get unprocessableEntity () {
1558
+ return this.statusCode === 422
1559
+ }
1560
+
1561
+ get authenticationURL () {
1562
+ return this.response.headers.get('WWW-Authenticate')
1563
+ }
1564
+
1565
+ get contentType () {
1566
+ const contentType = this.response.headers.get('Content-Type') || '';
1567
+
1568
+ return contentType.replace(/;.*$/, '')
1569
+ }
1570
+
1571
+ get headers () {
1572
+ return this.response.headers
1573
+ }
1574
+
1575
+ get html () {
1576
+ if (this.contentType.match(/^(application|text)\/(html|xhtml\+xml)$/)) {
1577
+ return this.text
1578
+ }
1579
+
1580
+ return Promise.reject(new Error(`Expected an HTML response but got "${this.contentType}" instead`))
1581
+ }
1582
+
1583
+ get json () {
1584
+ if (this.contentType.match(/^application\/.*json$/)) {
1585
+ return this.responseJson || (this.responseJson = this.response.json())
1586
+ }
1587
+
1588
+ return Promise.reject(new Error(`Expected a JSON response but got "${this.contentType}" instead`))
1589
+ }
1590
+
1591
+ get text () {
1592
+ return this.responseText || (this.responseText = this.response.text())
1593
+ }
1594
+
1595
+ get isTurboStream () {
1596
+ return this.contentType.match(/^text\/vnd\.turbo-stream\.html/)
1597
+ }
1598
+
1599
+ get isScript () {
1600
+ return this.contentType.match(/\b(?:java|ecma)script\b/)
1601
+ }
1602
+
1603
+ async renderTurboStream () {
1604
+ if (this.isTurboStream) {
1605
+ if (window.Turbo) {
1606
+ await window.Turbo.renderStreamMessage(await this.text);
1607
+ } else {
1608
+ console.warn('You must set `window.Turbo = Turbo` to automatically process Turbo Stream events with request.js');
1609
+ }
1610
+ } else {
1611
+ return Promise.reject(new Error(`Expected a Turbo Stream response but got "${this.contentType}" instead`))
1612
+ }
1613
+ }
1614
+
1615
+ async activeScript () {
1616
+ if (this.isScript) {
1617
+ const script = document.createElement('script');
1618
+ const metaTag = document.querySelector('meta[name=csp-nonce]');
1619
+ const nonce = metaTag && metaTag.content;
1620
+ if (nonce) { script.setAttribute('nonce', nonce); }
1621
+ script.innerHTML = await this.text;
1622
+ document.body.appendChild(script);
1623
+ } else {
1624
+ return Promise.reject(new Error(`Expected a Script response but got "${this.contentType}" instead`))
1625
+ }
1626
+ }
1627
+ }
1628
+
1629
+ class RequestInterceptor {
1630
+ static register (interceptor) {
1631
+ this.interceptor = interceptor;
1632
+ }
1633
+
1634
+ static get () {
1635
+ return this.interceptor
1636
+ }
1637
+
1638
+ static reset () {
1639
+ this.interceptor = undefined;
1640
+ }
1641
+ }
1642
+
1643
+ function getCookie (name) {
1644
+ const cookies = document.cookie ? document.cookie.split('; ') : [];
1645
+ const prefix = `${encodeURIComponent(name)}=`;
1646
+ const cookie = cookies.find(cookie => cookie.startsWith(prefix));
1647
+
1648
+ if (cookie) {
1649
+ const value = cookie.split('=').slice(1).join('=');
1650
+
1651
+ if (value) {
1652
+ return decodeURIComponent(value)
1653
+ }
1654
+ }
1655
+ }
1656
+
1657
+ function compact (object) {
1658
+ const result = {};
1659
+
1660
+ for (const key in object) {
1661
+ const value = object[key];
1662
+ if (value !== undefined) {
1663
+ result[key] = value;
1664
+ }
1665
+ }
1666
+
1667
+ return result
1668
+ }
1669
+
1670
+ function metaContent (name) {
1671
+ const element = document.head.querySelector(`meta[name="${name}"]`);
1672
+ return element && element.content
1673
+ }
1674
+
1675
+ function stringEntriesFromFormData (formData) {
1676
+ return [...formData].reduce((entries, [name, value]) => {
1677
+ return entries.concat(typeof value === 'string' ? [[name, value]] : [])
1678
+ }, [])
1679
+ }
1680
+
1681
+ function mergeEntries (searchParams, entries) {
1682
+ for (const [name, value] of entries) {
1683
+ if (value instanceof window.File) continue
1684
+
1685
+ if (searchParams.has(name) && !name.includes('[]')) {
1686
+ searchParams.delete(name);
1687
+ searchParams.set(name, value);
1688
+ } else {
1689
+ searchParams.append(name, value);
1690
+ }
1691
+ }
1692
+ }
1693
+
1694
+ class FetchRequest {
1695
+ constructor (method, url, options = {}) {
1696
+ this.method = method;
1697
+ this.options = options;
1698
+ this.originalUrl = url.toString();
1699
+ }
1700
+
1701
+ async perform () {
1702
+ try {
1703
+ const requestInterceptor = RequestInterceptor.get();
1704
+ if (requestInterceptor) {
1705
+ await requestInterceptor(this);
1706
+ }
1707
+ } catch (error) {
1708
+ console.error(error);
1709
+ }
1710
+
1711
+ const fetch = (this.responseKind === 'turbo-stream' && window.Turbo)
1712
+ ? window.Turbo.fetch
1713
+ : window.fetch;
1714
+
1715
+ const response = new FetchResponse(await fetch(this.url, this.fetchOptions));
1716
+
1717
+ if (response.unauthenticated && response.authenticationURL) {
1718
+ return Promise.reject(window.location.href = response.authenticationURL)
1719
+ }
1720
+
1721
+ if (response.isScript) {
1722
+ await response.activeScript();
1723
+ }
1724
+
1725
+ const responseStatusIsTurboStreamable = response.ok || response.unprocessableEntity;
1726
+
1727
+ if (responseStatusIsTurboStreamable && response.isTurboStream) {
1728
+ await response.renderTurboStream();
1729
+ }
1730
+
1731
+ return response
1732
+ }
1733
+
1734
+ addHeader (key, value) {
1735
+ const headers = this.additionalHeaders;
1736
+ headers[key] = value;
1737
+ this.options.headers = headers;
1738
+ }
1739
+
1740
+ sameHostname () {
1741
+ if (!this.originalUrl.startsWith('http:')) {
1742
+ return true
1743
+ }
1744
+
1745
+ try {
1746
+ return new URL(this.originalUrl).hostname === window.location.hostname
1747
+ } catch (_) {
1748
+ return true
1749
+ }
1750
+ }
1751
+
1752
+ get fetchOptions () {
1753
+ return {
1754
+ method: this.method.toUpperCase(),
1755
+ headers: this.headers,
1756
+ body: this.formattedBody,
1757
+ signal: this.signal,
1758
+ credentials: this.credentials,
1759
+ redirect: this.redirect
1760
+ }
1761
+ }
1762
+
1763
+ get headers () {
1764
+ const baseHeaders = {
1765
+ 'X-Requested-With': 'XMLHttpRequest',
1766
+ 'Content-Type': this.contentType,
1767
+ Accept: this.accept
1768
+ };
1769
+
1770
+ if (this.sameHostname()) {
1771
+ baseHeaders['X-CSRF-Token'] = this.csrfToken;
1772
+ }
1773
+
1774
+ return compact(
1775
+ Object.assign(baseHeaders, this.additionalHeaders)
1776
+ )
1777
+ }
1778
+
1779
+ get csrfToken () {
1780
+ return getCookie(metaContent('csrf-param')) || metaContent('csrf-token')
1781
+ }
1782
+
1783
+ get contentType () {
1784
+ if (this.options.contentType) {
1785
+ return this.options.contentType
1786
+ } else if (this.body == null || this.body instanceof window.FormData) {
1787
+ return undefined
1788
+ } else if (this.body instanceof window.File) {
1789
+ return this.body.type
1790
+ }
1791
+
1792
+ return 'application/json'
1793
+ }
1794
+
1795
+ get accept () {
1796
+ switch (this.responseKind) {
1797
+ case 'html':
1798
+ return 'text/html, application/xhtml+xml'
1799
+ case 'turbo-stream':
1800
+ return 'text/vnd.turbo-stream.html, text/html, application/xhtml+xml'
1801
+ case 'json':
1802
+ return 'application/json, application/vnd.api+json'
1803
+ case 'script':
1804
+ return 'text/javascript, application/javascript'
1805
+ default:
1806
+ return '*/*'
1807
+ }
1808
+ }
1809
+
1810
+ get body () {
1811
+ return this.options.body
1812
+ }
1813
+
1814
+ get query () {
1815
+ const originalQuery = (this.originalUrl.split('?')[1] || '').split('#')[0];
1816
+ const params = new URLSearchParams(originalQuery);
1817
+
1818
+ let requestQuery = this.options.query;
1819
+ if (requestQuery instanceof window.FormData) {
1820
+ requestQuery = stringEntriesFromFormData(requestQuery);
1821
+ } else if (requestQuery instanceof window.URLSearchParams) {
1822
+ requestQuery = requestQuery.entries();
1823
+ } else {
1824
+ requestQuery = Object.entries(requestQuery || {});
1825
+ }
1826
+
1827
+ mergeEntries(params, requestQuery);
1828
+
1829
+ const query = params.toString();
1830
+ return (query.length > 0 ? `?${query}` : '')
1831
+ }
1832
+
1833
+ get url () {
1834
+ return (this.originalUrl.split('?')[0]).split('#')[0] + this.query
1835
+ }
1836
+
1837
+ get responseKind () {
1838
+ return this.options.responseKind || 'html'
1839
+ }
1840
+
1841
+ get signal () {
1842
+ return this.options.signal
1843
+ }
1844
+
1845
+ get redirect () {
1846
+ return this.options.redirect || 'follow'
1847
+ }
1848
+
1849
+ get credentials () {
1850
+ return this.options.credentials || 'same-origin'
1851
+ }
1852
+
1853
+ get additionalHeaders () {
1854
+ return this.options.headers || {}
1855
+ }
1856
+
1857
+ get formattedBody () {
1858
+ const bodyIsAString = Object.prototype.toString.call(this.body) === '[object String]';
1859
+ const contentTypeIsJson = this.headers['Content-Type'] === 'application/json';
1860
+
1861
+ if (contentTypeIsJson && !bodyIsAString) {
1862
+ return JSON.stringify(this.body)
1863
+ }
1864
+
1865
+ return this.body
1866
+ }
1867
+ }
1868
+
1869
+ async function post (url, options) {
1870
+ const request = new FetchRequest('post', url, options);
1871
+ return request.perform()
1872
+ }
1873
+
1874
+ function insertText(textarea, text) {
1875
+ var _a, _b, _c;
1876
+ const before = textarea.value.slice(0, (_a = textarea.selectionStart) !== null && _a !== undefined ? _a : undefined);
1877
+ const after = textarea.value.slice((_b = textarea.selectionEnd) !== null && _b !== undefined ? _b : undefined);
1878
+ let canInsertText = true;
1879
+ textarea.contentEditable = 'true';
1880
+ try {
1881
+ canInsertText = document.execCommand('insertText', false, text);
1882
+ }
1883
+ catch (error) {
1884
+ canInsertText = false;
1885
+ }
1886
+ textarea.contentEditable = 'false';
1887
+ if (canInsertText && !textarea.value.slice(0, (_c = textarea.selectionStart) !== null && _c !== undefined ? _c : undefined).endsWith(text)) {
1888
+ canInsertText = false;
1889
+ }
1890
+ if (!canInsertText) {
1891
+ try {
1892
+ document.execCommand('ms-beginUndoUnit');
1893
+ }
1894
+ catch (e) {
1895
+ }
1896
+ textarea.value = before + text + after;
1897
+ try {
1898
+ document.execCommand('ms-endUndoUnit');
1899
+ }
1900
+ catch (e) {
1901
+ }
1902
+ textarea.dispatchEvent(new CustomEvent('change', { bubbles: true, cancelable: true }));
1903
+ }
1904
+ }
1905
+
1906
+ const skipFormattingMap = new WeakMap();
1907
+ function setSkipFormattingFlag(event) {
1908
+ const { currentTarget: el } = event;
1909
+ const isSkipFormattingKeys = event.code === 'KeyV' && (event.ctrlKey || event.metaKey) && event.shiftKey;
1910
+ if (isSkipFormattingKeys || (isSkipFormattingKeys && event.altKey)) {
1911
+ skipFormattingMap.set(el, true);
1912
+ }
1913
+ }
1914
+ function unsetSkipFormattedFlag(event) {
1915
+ const { currentTarget: el } = event;
1916
+ skipFormattingMap.delete(el);
1917
+ }
1918
+ function shouldSkipFormatting(el) {
1919
+ var _a;
1920
+ const shouldSkipFormattingState = (_a = skipFormattingMap.get(el)) !== null && _a !== undefined ? _a : false;
1921
+ return shouldSkipFormattingState;
1922
+ }
1923
+ function installAround(el, installCallbacks, optionConfig) {
1924
+ el.addEventListener('keydown', setSkipFormattingFlag);
1925
+ for (const installCallback of installCallbacks) {
1926
+ installCallback(el, optionConfig);
1927
+ }
1928
+ el.addEventListener('paste', unsetSkipFormattedFlag);
1929
+ }
1930
+ function uninstall$5(el) {
1931
+ el.removeEventListener('keydown', setSkipFormattingFlag);
1932
+ el.removeEventListener('paste', unsetSkipFormattedFlag);
1933
+ }
1934
+
1935
+ function install$4(el) {
1936
+ el.addEventListener('paste', onPaste$4);
1937
+ }
1938
+ function uninstall$4(el) {
1939
+ el.removeEventListener('paste', onPaste$4);
1940
+ }
1941
+ function onPaste$4(event) {
1942
+ const transfer = event.clipboardData;
1943
+ const { currentTarget: el } = event;
1944
+ if (shouldSkipFormatting(el))
1945
+ return;
1946
+ if (!transfer || !hasHTML(transfer))
1947
+ return;
1948
+ const field = event.currentTarget;
1949
+ if (!(field instanceof HTMLTextAreaElement))
1950
+ return;
1951
+ if (isWithinUserMention(field)) {
1952
+ return;
1953
+ }
1954
+ let plaintext = transfer.getData('text/plain');
1955
+ const textHTML = transfer.getData('text/html');
1956
+ const textHTMLClean = textHTML.replace(/\u00A0/g, ' ').replace(/\uC2A0/g, ' ');
1957
+ if (!textHTML)
1958
+ return;
1959
+ plaintext = plaintext.trim();
1960
+ if (!plaintext)
1961
+ return;
1962
+ const parser = new DOMParser();
1963
+ const doc = parser.parseFromString(textHTMLClean, 'text/html');
1964
+ const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_ALL, node => node.parentNode && isLink(node.parentNode) ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT);
1965
+ const markdown = convertToMarkdown(plaintext, walker);
1966
+ if (markdown === plaintext)
1967
+ return;
1968
+ event.stopPropagation();
1969
+ event.preventDefault();
1970
+ insertText(field, markdown);
1971
+ }
1972
+ function convertToMarkdown(plaintext, walker) {
1973
+ let currentNode = walker.firstChild();
1974
+ let markdown = plaintext;
1975
+ let markdownIgnoreBeforeIndex = 0;
1976
+ let index = 0;
1977
+ const NODE_LIMIT = 10000;
1978
+ while (currentNode && index < NODE_LIMIT) {
1979
+ index++;
1980
+ const text = isLink(currentNode)
1981
+ ? (currentNode.textContent || '').replace(/[\t\n\r ]+/g, ' ')
1982
+ : (currentNode === null || currentNode === undefined ? undefined : currentNode.wholeText) || '';
1983
+ if (isEmptyString(text)) {
1984
+ currentNode = walker.nextNode();
1985
+ continue;
1986
+ }
1987
+ if (!isLink(currentNode)) {
1988
+ markdownIgnoreBeforeIndex += text.replace(/[\t\n\r ]+/g, ' ').trimStart().length;
1989
+ currentNode = walker.nextNode();
1990
+ continue;
1991
+ }
1992
+ const markdownFoundIndex = markdown.indexOf(text, markdownIgnoreBeforeIndex);
1993
+ if (markdownFoundIndex >= 0) {
1994
+ const markdownLink = linkify$2(currentNode, text);
1995
+ markdown = markdown.slice(0, markdownFoundIndex) + markdownLink + markdown.slice(markdownFoundIndex + text.length);
1996
+ markdownIgnoreBeforeIndex = markdownFoundIndex + markdownLink.length;
1997
+ }
1998
+ currentNode = walker.nextNode();
1999
+ }
2000
+ return index === NODE_LIMIT ? plaintext : markdown;
2001
+ }
2002
+ function isWithinUserMention(textarea) {
2003
+ const selectionStart = textarea.selectionStart || 0;
2004
+ if (selectionStart === 0) {
2005
+ return false;
2006
+ }
2007
+ const previousChar = textarea.value.substring(selectionStart - 1, selectionStart);
2008
+ return previousChar === '@';
2009
+ }
2010
+ function isEmptyString(text) {
2011
+ return !text || (text === null || text === undefined ? undefined : text.trim().length) === 0;
2012
+ }
2013
+ function isLink(node) {
2014
+ var _a;
2015
+ return ((_a = node.tagName) === null || _a === undefined ? undefined : _a.toLowerCase()) === 'a' && node.hasAttribute('href');
2016
+ }
2017
+ function hasHTML(transfer) {
2018
+ return transfer.types.includes('text/html');
2019
+ }
2020
+ function linkify$2(element, label) {
2021
+ const url = element.href || '';
2022
+ let markdown = '';
2023
+ if (isUserMention(element) || isTeamMention(element)) {
2024
+ markdown = label;
2025
+ }
2026
+ else if (isSpecialLink(element) || areEqualLinks(url, label)) {
2027
+ markdown = url;
2028
+ }
2029
+ else {
2030
+ markdown = `[${label}](${url})`;
2031
+ }
2032
+ return markdown;
2033
+ }
2034
+ function isSpecialLink(link) {
2035
+ return (link.className.indexOf('commit-link') >= 0 ||
2036
+ (!!link.getAttribute('data-hovercard-type') && link.getAttribute('data-hovercard-type') !== 'user'));
2037
+ }
2038
+ function areEqualLinks(link1, link2) {
2039
+ link1 = link1.slice(-1) === '/' ? link1.slice(0, -1) : link1;
2040
+ link2 = link2.slice(-1) === '/' ? link2.slice(0, -1) : link2;
2041
+ return link1.toLowerCase() === link2.toLowerCase();
2042
+ }
2043
+ function isUserMention(link) {
2044
+ var _a;
2045
+ return ((_a = link.textContent) === null || _a === undefined ? undefined : _a.slice(0, 1)) === '@' && link.getAttribute('data-hovercard-type') === 'user';
2046
+ }
2047
+ function isTeamMention(link) {
2048
+ var _a;
2049
+ return ((_a = link.textContent) === null || _a === undefined ? undefined : _a.slice(0, 1)) === '@' && link.getAttribute('data-hovercard-type') === 'team';
2050
+ }
2051
+
2052
+ function install$3(el) {
2053
+ el.addEventListener('dragover', onDragover$1);
2054
+ el.addEventListener('drop', onDrop$1);
2055
+ el.addEventListener('paste', onPaste$3);
2056
+ }
2057
+ function uninstall$3(el) {
2058
+ el.removeEventListener('dragover', onDragover$1);
2059
+ el.removeEventListener('drop', onDrop$1);
2060
+ el.removeEventListener('paste', onPaste$3);
2061
+ }
2062
+ function onDrop$1(event) {
2063
+ const transfer = event.dataTransfer;
2064
+ if (!transfer)
2065
+ return;
2066
+ if (hasFile$1(transfer))
2067
+ return;
2068
+ if (!hasLink(transfer))
2069
+ return;
2070
+ const links = extractLinks(transfer);
2071
+ if (!links.some(isImageLink))
2072
+ return;
2073
+ event.stopPropagation();
2074
+ event.preventDefault();
2075
+ const field = event.currentTarget;
2076
+ if (!(field instanceof HTMLTextAreaElement))
2077
+ return;
2078
+ insertText(field, links.map(linkify$1).join(''));
2079
+ }
2080
+ function onDragover$1(event) {
2081
+ const transfer = event.dataTransfer;
2082
+ if (transfer)
2083
+ transfer.dropEffect = 'link';
2084
+ }
2085
+ function onPaste$3(event) {
2086
+ const { currentTarget: el } = event;
2087
+ if (shouldSkipFormatting(el))
2088
+ return;
2089
+ const transfer = event.clipboardData;
2090
+ if (!transfer || !hasLink(transfer))
2091
+ return;
2092
+ const links = extractLinks(transfer);
2093
+ if (!links.some(isImageLink))
2094
+ return;
2095
+ event.stopPropagation();
2096
+ event.preventDefault();
2097
+ const field = event.currentTarget;
2098
+ if (!(field instanceof HTMLTextAreaElement))
2099
+ return;
2100
+ insertText(field, links.map(linkify$1).join(''));
2101
+ }
2102
+ function linkify$1(link) {
2103
+ return isImageLink(link) ? `\n![](${link})\n` : link;
2104
+ }
2105
+ function hasFile$1(transfer) {
2106
+ return Array.from(transfer.types).indexOf('Files') >= 0;
2107
+ }
2108
+ function hasLink(transfer) {
2109
+ return Array.from(transfer.types).indexOf('text/uri-list') >= 0;
2110
+ }
2111
+ function extractLinks(transfer) {
2112
+ return (transfer.getData('text/uri-list') || '').split('\r\n');
2113
+ }
2114
+ const IMAGE_RE = /\.(gif|png|jpe?g)$/i;
2115
+ function isImageLink(url) {
2116
+ return IMAGE_RE.test(url);
2117
+ }
2118
+
2119
+ const pasteLinkAsPlainTextOverSelectedTextMap = new WeakMap();
2120
+ function install$2(el, optionConfig) {
2121
+ var _a;
2122
+ pasteLinkAsPlainTextOverSelectedTextMap.set(el, ((_a = optionConfig === null || optionConfig === undefined ? undefined : optionConfig.defaultPlainTextPaste) === null || _a === undefined ? undefined : _a.urlLinks) === true);
2123
+ el.addEventListener('paste', onPaste$2);
2124
+ }
2125
+ function uninstall$2(el) {
2126
+ el.removeEventListener('paste', onPaste$2);
2127
+ }
2128
+ function onPaste$2(event) {
2129
+ var _a;
2130
+ const { currentTarget: el } = event;
2131
+ const element = el;
2132
+ const shouldPasteAsPlainText = (_a = pasteLinkAsPlainTextOverSelectedTextMap.get(element)) !== null && _a !== undefined ? _a : false;
2133
+ const shouldSkipDefaultBehavior = shouldSkipFormatting(element);
2134
+ if ((!shouldPasteAsPlainText && shouldSkipDefaultBehavior) ||
2135
+ (shouldPasteAsPlainText && !shouldSkipDefaultBehavior)) {
2136
+ return;
2137
+ }
2138
+ const transfer = event.clipboardData;
2139
+ if (!transfer || !hasPlainText(transfer))
2140
+ return;
2141
+ const field = event.currentTarget;
2142
+ if (!(field instanceof HTMLTextAreaElement))
2143
+ return;
2144
+ const text = transfer.getData('text/plain');
2145
+ if (!text)
2146
+ return;
2147
+ if (!isURL(text))
2148
+ return;
2149
+ if (isWithinLink(field))
2150
+ return;
2151
+ const selectedText = field.value.substring(field.selectionStart, field.selectionEnd);
2152
+ if (!selectedText.length)
2153
+ return;
2154
+ if (isURL(selectedText.trim()))
2155
+ return;
2156
+ event.stopPropagation();
2157
+ event.preventDefault();
2158
+ insertText(field, linkify(selectedText, text.trim()));
2159
+ }
2160
+ function hasPlainText(transfer) {
2161
+ return Array.from(transfer.types).includes('text/plain');
2162
+ }
2163
+ function isWithinLink(textarea) {
2164
+ const selectionStart = textarea.selectionStart || 0;
2165
+ if (selectionStart > 1) {
2166
+ const previousChars = textarea.value.substring(selectionStart - 2, selectionStart);
2167
+ return previousChars === '](';
2168
+ }
2169
+ else {
2170
+ return false;
2171
+ }
2172
+ }
2173
+ function linkify(selectedText, text) {
2174
+ return `[${selectedText}](${text})`;
2175
+ }
2176
+ function isURL(url) {
2177
+ try {
2178
+ const parsedURL = new URL(url);
2179
+ return removeTrailingSlash(parsedURL.href).trim() === removeTrailingSlash(url).trim();
2180
+ }
2181
+ catch (_a) {
2182
+ return false;
2183
+ }
2184
+ }
2185
+ function removeTrailingSlash(url) {
2186
+ return url.endsWith('/') ? url.slice(0, url.length - 1) : url;
2187
+ }
2188
+
2189
+ function install$1(el) {
2190
+ el.addEventListener('dragover', onDragover);
2191
+ el.addEventListener('drop', onDrop);
2192
+ el.addEventListener('paste', onPaste$1);
2193
+ }
2194
+ function uninstall$1(el) {
2195
+ el.removeEventListener('dragover', onDragover);
2196
+ el.removeEventListener('drop', onDrop);
2197
+ el.removeEventListener('paste', onPaste$1);
2198
+ }
2199
+ function onDrop(event) {
2200
+ const transfer = event.dataTransfer;
2201
+ if (!transfer)
2202
+ return;
2203
+ if (hasFile(transfer))
2204
+ return;
2205
+ const textToPaste = generateText(transfer);
2206
+ if (!textToPaste)
2207
+ return;
2208
+ event.stopPropagation();
2209
+ event.preventDefault();
2210
+ const field = event.currentTarget;
2211
+ if (field instanceof HTMLTextAreaElement) {
2212
+ insertText(field, textToPaste);
2213
+ }
2214
+ }
2215
+ function onDragover(event) {
2216
+ const transfer = event.dataTransfer;
2217
+ if (transfer)
2218
+ transfer.dropEffect = 'copy';
2219
+ }
2220
+ function onPaste$1(event) {
2221
+ const { currentTarget: el } = event;
2222
+ if (shouldSkipFormatting(el))
2223
+ return;
2224
+ if (!event.clipboardData)
2225
+ return;
2226
+ const textToPaste = generateText(event.clipboardData);
2227
+ if (!textToPaste)
2228
+ return;
2229
+ event.stopPropagation();
2230
+ event.preventDefault();
2231
+ const field = event.currentTarget;
2232
+ if (field instanceof HTMLTextAreaElement) {
2233
+ insertText(field, textToPaste);
2234
+ }
2235
+ }
2236
+ function hasFile(transfer) {
2237
+ return Array.from(transfer.types).indexOf('Files') >= 0;
2238
+ }
2239
+ function columnText(column) {
2240
+ const noBreakSpace = '\u00A0';
2241
+ const text = (column.textContent || '').trim().replace(/\|/g, '\\|').replace(/\n/g, ' ');
2242
+ return text || noBreakSpace;
2243
+ }
2244
+ function tableHeaders(row) {
2245
+ return Array.from(row.querySelectorAll('td, th')).map(columnText);
2246
+ }
2247
+ function tableMarkdown(node) {
2248
+ const rows = Array.from(node.querySelectorAll('tr'));
2249
+ const firstRow = rows.shift();
2250
+ if (!firstRow)
2251
+ return '';
2252
+ const headers = tableHeaders(firstRow);
2253
+ const spacers = headers.map(() => '--');
2254
+ const header = `${headers.join(' | ')}\n${spacers.join(' | ')}\n`;
2255
+ const body = rows
2256
+ .map(row => {
2257
+ return Array.from(row.querySelectorAll('td')).map(columnText).join(' | ');
2258
+ })
2259
+ .join('\n');
2260
+ return `\n${header}${body}\n\n`;
2261
+ }
2262
+ function generateText(transfer) {
2263
+ if (Array.from(transfer.types).indexOf('text/html') === -1)
2264
+ return;
2265
+ const html = transfer.getData('text/html');
2266
+ if (!/<table/i.test(html))
2267
+ return;
2268
+ const start = html.substring(0, html.indexOf('<table'));
2269
+ const tableCloseIndex = html.lastIndexOf('</table>');
2270
+ if (!start || !tableCloseIndex)
2271
+ return;
2272
+ const end = html.substring(tableCloseIndex + 8);
2273
+ const parser = new DOMParser();
2274
+ const parsedDocument = parser.parseFromString(html, 'text/html');
2275
+ let table = parsedDocument.querySelector('table');
2276
+ table = !table || table.closest('[data-paste-markdown-skip]') ? null : table;
2277
+ if (!table)
2278
+ return;
2279
+ const formattedTable = tableMarkdown(table);
2280
+ if (!formattedTable)
2281
+ return;
2282
+ return [start, formattedTable, end].join('').replace(/<meta.*?>/, '');
2283
+ }
2284
+
2285
+ function install(el) {
2286
+ el.addEventListener('paste', onPaste);
2287
+ }
2288
+ function uninstall(el) {
2289
+ el.removeEventListener('paste', onPaste);
2290
+ }
2291
+ function onPaste(event) {
2292
+ const { currentTarget: el } = event;
2293
+ if (shouldSkipFormatting(el))
2294
+ return;
2295
+ const transfer = event.clipboardData;
2296
+ if (!transfer || !hasMarkdown(transfer))
2297
+ return;
2298
+ const field = event.currentTarget;
2299
+ if (!(field instanceof HTMLTextAreaElement))
2300
+ return;
2301
+ const text = transfer.getData('text/x-gfm');
2302
+ if (!text)
2303
+ return;
2304
+ event.stopPropagation();
2305
+ event.preventDefault();
2306
+ insertText(field, text);
2307
+ }
2308
+ function hasMarkdown(transfer) {
2309
+ return Array.from(transfer.types).indexOf('text/x-gfm') >= 0;
2310
+ }
2311
+
2312
+ function subscribe(el, optionConfig) {
2313
+ installAround(el, [install$1, install$3, install$2, install, install$4], optionConfig);
2314
+ return {
2315
+ unsubscribe: () => {
2316
+ uninstall$5(el);
2317
+ uninstall$1(el);
2318
+ uninstall$4(el);
2319
+ uninstall$3(el);
2320
+ uninstall$2(el);
2321
+ uninstall(el);
2322
+ },
2323
+ };
2324
+ }
2325
+
2326
+ /* eslint-disable camelcase */
2327
+
2328
+ // upload code from Jeremy Smith's blog post
2329
+ // https://hybrd.co/posts/github-issue-style-file-uploader-using-stimulus-and-active-storage
2330
+
2331
+ // Connects to data-controller="marksmith"
2332
+ class marksmith_controller extends stimulus.Controller {
2333
+ static values = {
2334
+ attachUrl: String,
2335
+ previewUrl: String,
2336
+ extraPreviewParams: { type: Object, default: {} },
2337
+ fieldId: String,
2338
+ }
2339
+
2340
+ static targets = ['fieldContainer', 'fieldElement', 'previewElement', 'writeTabButton', 'previewTabButton', 'toolbar']
2341
+
2342
+ connect() {
2343
+ subscribe(this.fieldContainerTarget, { defaultPlainTextPaste: { urlLinks: true } });
2344
+ }
2345
+
2346
+ switchToWrite(event) {
2347
+ event.preventDefault();
2348
+
2349
+ // toggle buttons
2350
+ this.writeTabButtonTarget.classList.add('ms:hidden');
2351
+ this.previewTabButtonTarget.classList.remove('ms:hidden');
2352
+
2353
+ // toggle write/preview buttons
2354
+ this.fieldContainerTarget.classList.remove('ms:hidden');
2355
+ this.previewElementTarget.classList.add('ms:hidden');
2356
+
2357
+ // toggle the toolbar back
2358
+ this.toolbarTarget.classList.remove('ms:hidden');
2359
+ }
2360
+
2361
+ switchToPreview(event) {
2362
+ event.preventDefault();
2363
+
2364
+ post(this.previewUrlValue, {
2365
+ body: {
2366
+ body: this.fieldElementTarget.value,
2367
+ element_id: this.previewElementTarget.id,
2368
+ extra_params: this.extraPreviewParamsValue,
2369
+ },
2370
+ responseKind: 'turbo-stream',
2371
+ });
2372
+
2373
+ // set the min height to the field element height
2374
+ this.previewElementTarget.style.minHeight = `${this.fieldElementTarget.offsetHeight}px`;
2375
+
2376
+ // toggle buttons
2377
+ this.writeTabButtonTarget.classList.remove('ms:hidden');
2378
+ this.previewTabButtonTarget.classList.add('ms:hidden');
2379
+
2380
+ // toggle elements
2381
+ this.fieldContainerTarget.classList.add('ms:hidden');
2382
+ this.previewElementTarget.classList.remove('ms:hidden');
2383
+
2384
+ // toggle the toolbar
2385
+ this.toolbarTarget.classList.add('ms:hidden');
2386
+ }
2387
+
2388
+ dropUpload(event) {
2389
+ event.preventDefault();
2390
+ this.uploadFiles(event.dataTransfer.files);
2391
+ }
2392
+
2393
+ pasteUpload(event) {
2394
+ if (!event.clipboardData.files.length) return
2395
+
2396
+ event.preventDefault();
2397
+ this.uploadFiles(event.clipboardData.files);
2398
+ }
2399
+
2400
+ buttonUpload(event) {
2401
+ event.preventDefault();
2402
+ // Create a hidden file input and trigger it
2403
+ const fileInput = document.createElement('input');
2404
+ fileInput.type = 'file';
2405
+ fileInput.multiple = true;
2406
+ fileInput.accept = 'image/*,.pdf,.doc,.docx,.txt';
2407
+
2408
+ fileInput.addEventListener('change', (e) => {
2409
+ this.uploadFiles(e.target.files);
2410
+ });
2411
+
2412
+ fileInput.click();
2413
+ }
2414
+
2415
+ uploadFiles(files) {
2416
+ Array.from(files).forEach((file) => this.uploadFile(file));
2417
+ }
2418
+
2419
+ uploadFile(file) {
2420
+ const upload = new DirectUpload(file, this.attachUrlValue);
2421
+
2422
+ upload.create((error, blob) => {
2423
+ if (error) {
2424
+ console.log('Error', error);
2425
+ } else {
2426
+ const text = this.markdownLink(blob);
2427
+ const start = this.fieldElementTarget.selectionStart;
2428
+ const end = this.fieldElementTarget.selectionEnd;
2429
+ this.fieldElementTarget.setRangeText(text, start, end);
2430
+ }
2431
+ });
2432
+ }
2433
+
2434
+ markdownLink(blob) {
2435
+ const { filename } = blob;
2436
+ const url = `/rails/active_storage/blobs/${blob.signed_id}/${filename}`;
2437
+ const prefix = (this.isImage(blob.content_type) ? '!' : '');
2438
+
2439
+ return `${prefix}[${filename}](${url})\n`
2440
+ }
2441
+
2442
+ isImage(contentType) {
2443
+ return ['image/jpeg', 'image/gif', 'image/png'].includes(contentType)
2444
+ }
2445
+ }
2446
+
2447
+ return marksmith_controller;
2448
+
2449
+ })(FakeStimulus);