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,2939 @@
1
+ /*!
2
+ Marksmith 0.0.15
3
+ */
4
+ var MarksmithController = (function () {
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
+ /*
690
+ Stimulus 3.2.1
691
+ Copyright © 2023 Basecamp, LLC
692
+ */
693
+
694
+ function camelize(value) {
695
+ return value.replace(/(?:[_-])([a-z0-9])/g, (_, char) => char.toUpperCase());
696
+ }
697
+ function namespaceCamelize(value) {
698
+ return camelize(value.replace(/--/g, "-").replace(/__/g, "_"));
699
+ }
700
+ function capitalize(value) {
701
+ return value.charAt(0).toUpperCase() + value.slice(1);
702
+ }
703
+ function dasherize(value) {
704
+ return value.replace(/([A-Z])/g, (_, char) => `-${char.toLowerCase()}`);
705
+ }
706
+
707
+ function isSomething(object) {
708
+ return object !== null && object !== undefined;
709
+ }
710
+ function hasProperty(object, property) {
711
+ return Object.prototype.hasOwnProperty.call(object, property);
712
+ }
713
+
714
+ function readInheritableStaticArrayValues(constructor, propertyName) {
715
+ const ancestors = getAncestorsForConstructor(constructor);
716
+ return Array.from(ancestors.reduce((values, constructor) => {
717
+ getOwnStaticArrayValues(constructor, propertyName).forEach((name) => values.add(name));
718
+ return values;
719
+ }, new Set()));
720
+ }
721
+ function readInheritableStaticObjectPairs(constructor, propertyName) {
722
+ const ancestors = getAncestorsForConstructor(constructor);
723
+ return ancestors.reduce((pairs, constructor) => {
724
+ pairs.push(...getOwnStaticObjectPairs(constructor, propertyName));
725
+ return pairs;
726
+ }, []);
727
+ }
728
+ function getAncestorsForConstructor(constructor) {
729
+ const ancestors = [];
730
+ while (constructor) {
731
+ ancestors.push(constructor);
732
+ constructor = Object.getPrototypeOf(constructor);
733
+ }
734
+ return ancestors.reverse();
735
+ }
736
+ function getOwnStaticArrayValues(constructor, propertyName) {
737
+ const definition = constructor[propertyName];
738
+ return Array.isArray(definition) ? definition : [];
739
+ }
740
+ function getOwnStaticObjectPairs(constructor, propertyName) {
741
+ const definition = constructor[propertyName];
742
+ return definition ? Object.keys(definition).map((key) => [key, definition[key]]) : [];
743
+ }
744
+ (() => {
745
+ function extendWithReflect(constructor) {
746
+ function extended() {
747
+ return Reflect.construct(constructor, arguments, new.target);
748
+ }
749
+ extended.prototype = Object.create(constructor.prototype, {
750
+ constructor: { value: extended },
751
+ });
752
+ Reflect.setPrototypeOf(extended, constructor);
753
+ return extended;
754
+ }
755
+ function testReflectExtension() {
756
+ const a = function () {
757
+ this.a.call(this);
758
+ };
759
+ const b = extendWithReflect(a);
760
+ b.prototype.a = function () { };
761
+ return new b();
762
+ }
763
+ try {
764
+ testReflectExtension();
765
+ return extendWithReflect;
766
+ }
767
+ catch (error) {
768
+ return (constructor) => class extended extends constructor {
769
+ };
770
+ }
771
+ })();
772
+
773
+ ({
774
+ controllerAttribute: "data-controller",
775
+ actionAttribute: "data-action",
776
+ targetAttribute: "data-target",
777
+ targetAttributeForScope: (identifier) => `data-${identifier}-target`,
778
+ outletAttributeForScope: (identifier, outlet) => `data-${identifier}-${outlet}-outlet`,
779
+ keyMappings: Object.assign(Object.assign({ enter: "Enter", tab: "Tab", esc: "Escape", space: " ", up: "ArrowUp", down: "ArrowDown", left: "ArrowLeft", right: "ArrowRight", home: "Home", end: "End", page_up: "PageUp", page_down: "PageDown" }, objectFromEntries("abcdefghijklmnopqrstuvwxyz".split("").map((c) => [c, c]))), objectFromEntries("0123456789".split("").map((n) => [n, n]))),
780
+ });
781
+ function objectFromEntries(array) {
782
+ return array.reduce((memo, [k, v]) => (Object.assign(Object.assign({}, memo), { [k]: v })), {});
783
+ }
784
+
785
+ function ClassPropertiesBlessing(constructor) {
786
+ const classes = readInheritableStaticArrayValues(constructor, "classes");
787
+ return classes.reduce((properties, classDefinition) => {
788
+ return Object.assign(properties, propertiesForClassDefinition(classDefinition));
789
+ }, {});
790
+ }
791
+ function propertiesForClassDefinition(key) {
792
+ return {
793
+ [`${key}Class`]: {
794
+ get() {
795
+ const { classes } = this;
796
+ if (classes.has(key)) {
797
+ return classes.get(key);
798
+ }
799
+ else {
800
+ const attribute = classes.getAttributeName(key);
801
+ throw new Error(`Missing attribute "${attribute}"`);
802
+ }
803
+ },
804
+ },
805
+ [`${key}Classes`]: {
806
+ get() {
807
+ return this.classes.getAll(key);
808
+ },
809
+ },
810
+ [`has${capitalize(key)}Class`]: {
811
+ get() {
812
+ return this.classes.has(key);
813
+ },
814
+ },
815
+ };
816
+ }
817
+
818
+ function OutletPropertiesBlessing(constructor) {
819
+ const outlets = readInheritableStaticArrayValues(constructor, "outlets");
820
+ return outlets.reduce((properties, outletDefinition) => {
821
+ return Object.assign(properties, propertiesForOutletDefinition(outletDefinition));
822
+ }, {});
823
+ }
824
+ function getOutletController(controller, element, identifier) {
825
+ return controller.application.getControllerForElementAndIdentifier(element, identifier);
826
+ }
827
+ function getControllerAndEnsureConnectedScope(controller, element, outletName) {
828
+ let outletController = getOutletController(controller, element, outletName);
829
+ if (outletController)
830
+ return outletController;
831
+ controller.application.router.proposeToConnectScopeForElementAndIdentifier(element, outletName);
832
+ outletController = getOutletController(controller, element, outletName);
833
+ if (outletController)
834
+ return outletController;
835
+ }
836
+ function propertiesForOutletDefinition(name) {
837
+ const camelizedName = namespaceCamelize(name);
838
+ return {
839
+ [`${camelizedName}Outlet`]: {
840
+ get() {
841
+ const outletElement = this.outlets.find(name);
842
+ const selector = this.outlets.getSelectorForOutletName(name);
843
+ if (outletElement) {
844
+ const outletController = getControllerAndEnsureConnectedScope(this, outletElement, name);
845
+ if (outletController)
846
+ return outletController;
847
+ throw new Error(`The provided outlet element is missing an outlet controller "${name}" instance for host controller "${this.identifier}"`);
848
+ }
849
+ throw new Error(`Missing outlet element "${name}" for host controller "${this.identifier}". Stimulus couldn't find a matching outlet element using selector "${selector}".`);
850
+ },
851
+ },
852
+ [`${camelizedName}Outlets`]: {
853
+ get() {
854
+ const outlets = this.outlets.findAll(name);
855
+ if (outlets.length > 0) {
856
+ return outlets
857
+ .map((outletElement) => {
858
+ const outletController = getControllerAndEnsureConnectedScope(this, outletElement, name);
859
+ if (outletController)
860
+ return outletController;
861
+ console.warn(`The provided outlet element is missing an outlet controller "${name}" instance for host controller "${this.identifier}"`, outletElement);
862
+ })
863
+ .filter((controller) => controller);
864
+ }
865
+ return [];
866
+ },
867
+ },
868
+ [`${camelizedName}OutletElement`]: {
869
+ get() {
870
+ const outletElement = this.outlets.find(name);
871
+ const selector = this.outlets.getSelectorForOutletName(name);
872
+ if (outletElement) {
873
+ return outletElement;
874
+ }
875
+ else {
876
+ throw new Error(`Missing outlet element "${name}" for host controller "${this.identifier}". Stimulus couldn't find a matching outlet element using selector "${selector}".`);
877
+ }
878
+ },
879
+ },
880
+ [`${camelizedName}OutletElements`]: {
881
+ get() {
882
+ return this.outlets.findAll(name);
883
+ },
884
+ },
885
+ [`has${capitalize(camelizedName)}Outlet`]: {
886
+ get() {
887
+ return this.outlets.has(name);
888
+ },
889
+ },
890
+ };
891
+ }
892
+
893
+ function TargetPropertiesBlessing(constructor) {
894
+ const targets = readInheritableStaticArrayValues(constructor, "targets");
895
+ return targets.reduce((properties, targetDefinition) => {
896
+ return Object.assign(properties, propertiesForTargetDefinition(targetDefinition));
897
+ }, {});
898
+ }
899
+ function propertiesForTargetDefinition(name) {
900
+ return {
901
+ [`${name}Target`]: {
902
+ get() {
903
+ const target = this.targets.find(name);
904
+ if (target) {
905
+ return target;
906
+ }
907
+ else {
908
+ throw new Error(`Missing target element "${name}" for "${this.identifier}" controller`);
909
+ }
910
+ },
911
+ },
912
+ [`${name}Targets`]: {
913
+ get() {
914
+ return this.targets.findAll(name);
915
+ },
916
+ },
917
+ [`has${capitalize(name)}Target`]: {
918
+ get() {
919
+ return this.targets.has(name);
920
+ },
921
+ },
922
+ };
923
+ }
924
+
925
+ function ValuePropertiesBlessing(constructor) {
926
+ const valueDefinitionPairs = readInheritableStaticObjectPairs(constructor, "values");
927
+ const propertyDescriptorMap = {
928
+ valueDescriptorMap: {
929
+ get() {
930
+ return valueDefinitionPairs.reduce((result, valueDefinitionPair) => {
931
+ const valueDescriptor = parseValueDefinitionPair(valueDefinitionPair, this.identifier);
932
+ const attributeName = this.data.getAttributeNameForKey(valueDescriptor.key);
933
+ return Object.assign(result, { [attributeName]: valueDescriptor });
934
+ }, {});
935
+ },
936
+ },
937
+ };
938
+ return valueDefinitionPairs.reduce((properties, valueDefinitionPair) => {
939
+ return Object.assign(properties, propertiesForValueDefinitionPair(valueDefinitionPair));
940
+ }, propertyDescriptorMap);
941
+ }
942
+ function propertiesForValueDefinitionPair(valueDefinitionPair, controller) {
943
+ const definition = parseValueDefinitionPair(valueDefinitionPair, controller);
944
+ const { key, name, reader: read, writer: write } = definition;
945
+ return {
946
+ [name]: {
947
+ get() {
948
+ const value = this.data.get(key);
949
+ if (value !== null) {
950
+ return read(value);
951
+ }
952
+ else {
953
+ return definition.defaultValue;
954
+ }
955
+ },
956
+ set(value) {
957
+ if (value === undefined) {
958
+ this.data.delete(key);
959
+ }
960
+ else {
961
+ this.data.set(key, write(value));
962
+ }
963
+ },
964
+ },
965
+ [`has${capitalize(name)}`]: {
966
+ get() {
967
+ return this.data.has(key) || definition.hasCustomDefaultValue;
968
+ },
969
+ },
970
+ };
971
+ }
972
+ function parseValueDefinitionPair([token, typeDefinition], controller) {
973
+ return valueDescriptorForTokenAndTypeDefinition({
974
+ controller,
975
+ token,
976
+ typeDefinition,
977
+ });
978
+ }
979
+ function parseValueTypeConstant(constant) {
980
+ switch (constant) {
981
+ case Array:
982
+ return "array";
983
+ case Boolean:
984
+ return "boolean";
985
+ case Number:
986
+ return "number";
987
+ case Object:
988
+ return "object";
989
+ case String:
990
+ return "string";
991
+ }
992
+ }
993
+ function parseValueTypeDefault(defaultValue) {
994
+ switch (typeof defaultValue) {
995
+ case "boolean":
996
+ return "boolean";
997
+ case "number":
998
+ return "number";
999
+ case "string":
1000
+ return "string";
1001
+ }
1002
+ if (Array.isArray(defaultValue))
1003
+ return "array";
1004
+ if (Object.prototype.toString.call(defaultValue) === "[object Object]")
1005
+ return "object";
1006
+ }
1007
+ function parseValueTypeObject(payload) {
1008
+ const { controller, token, typeObject } = payload;
1009
+ const hasType = isSomething(typeObject.type);
1010
+ const hasDefault = isSomething(typeObject.default);
1011
+ const fullObject = hasType && hasDefault;
1012
+ const onlyType = hasType && !hasDefault;
1013
+ const onlyDefault = !hasType && hasDefault;
1014
+ const typeFromObject = parseValueTypeConstant(typeObject.type);
1015
+ const typeFromDefaultValue = parseValueTypeDefault(payload.typeObject.default);
1016
+ if (onlyType)
1017
+ return typeFromObject;
1018
+ if (onlyDefault)
1019
+ return typeFromDefaultValue;
1020
+ if (typeFromObject !== typeFromDefaultValue) {
1021
+ const propertyPath = controller ? `${controller}.${token}` : token;
1022
+ throw new Error(`The specified default value for the Stimulus Value "${propertyPath}" must match the defined type "${typeFromObject}". The provided default value of "${typeObject.default}" is of type "${typeFromDefaultValue}".`);
1023
+ }
1024
+ if (fullObject)
1025
+ return typeFromObject;
1026
+ }
1027
+ function parseValueTypeDefinition(payload) {
1028
+ const { controller, token, typeDefinition } = payload;
1029
+ const typeObject = { controller, token, typeObject: typeDefinition };
1030
+ const typeFromObject = parseValueTypeObject(typeObject);
1031
+ const typeFromDefaultValue = parseValueTypeDefault(typeDefinition);
1032
+ const typeFromConstant = parseValueTypeConstant(typeDefinition);
1033
+ const type = typeFromObject || typeFromDefaultValue || typeFromConstant;
1034
+ if (type)
1035
+ return type;
1036
+ const propertyPath = controller ? `${controller}.${typeDefinition}` : token;
1037
+ throw new Error(`Unknown value type "${propertyPath}" for "${token}" value`);
1038
+ }
1039
+ function defaultValueForDefinition(typeDefinition) {
1040
+ const constant = parseValueTypeConstant(typeDefinition);
1041
+ if (constant)
1042
+ return defaultValuesByType[constant];
1043
+ const hasDefault = hasProperty(typeDefinition, "default");
1044
+ const hasType = hasProperty(typeDefinition, "type");
1045
+ const typeObject = typeDefinition;
1046
+ if (hasDefault)
1047
+ return typeObject.default;
1048
+ if (hasType) {
1049
+ const { type } = typeObject;
1050
+ const constantFromType = parseValueTypeConstant(type);
1051
+ if (constantFromType)
1052
+ return defaultValuesByType[constantFromType];
1053
+ }
1054
+ return typeDefinition;
1055
+ }
1056
+ function valueDescriptorForTokenAndTypeDefinition(payload) {
1057
+ const { token, typeDefinition } = payload;
1058
+ const key = `${dasherize(token)}-value`;
1059
+ const type = parseValueTypeDefinition(payload);
1060
+ return {
1061
+ type,
1062
+ key,
1063
+ name: camelize(key),
1064
+ get defaultValue() {
1065
+ return defaultValueForDefinition(typeDefinition);
1066
+ },
1067
+ get hasCustomDefaultValue() {
1068
+ return parseValueTypeDefault(typeDefinition) !== undefined;
1069
+ },
1070
+ reader: readers[type],
1071
+ writer: writers[type] || writers.default,
1072
+ };
1073
+ }
1074
+ const defaultValuesByType = {
1075
+ get array() {
1076
+ return [];
1077
+ },
1078
+ boolean: false,
1079
+ number: 0,
1080
+ get object() {
1081
+ return {};
1082
+ },
1083
+ string: "",
1084
+ };
1085
+ const readers = {
1086
+ array(value) {
1087
+ const array = JSON.parse(value);
1088
+ if (!Array.isArray(array)) {
1089
+ throw new TypeError(`expected value of type "array" but instead got value "${value}" of type "${parseValueTypeDefault(array)}"`);
1090
+ }
1091
+ return array;
1092
+ },
1093
+ boolean(value) {
1094
+ return !(value == "0" || String(value).toLowerCase() == "false");
1095
+ },
1096
+ number(value) {
1097
+ return Number(value.replace(/_/g, ""));
1098
+ },
1099
+ object(value) {
1100
+ const object = JSON.parse(value);
1101
+ if (object === null || typeof object != "object" || Array.isArray(object)) {
1102
+ throw new TypeError(`expected value of type "object" but instead got value "${value}" of type "${parseValueTypeDefault(object)}"`);
1103
+ }
1104
+ return object;
1105
+ },
1106
+ string(value) {
1107
+ return value;
1108
+ },
1109
+ };
1110
+ const writers = {
1111
+ default: writeString,
1112
+ array: writeJSON,
1113
+ object: writeJSON,
1114
+ };
1115
+ function writeJSON(value) {
1116
+ return JSON.stringify(value);
1117
+ }
1118
+ function writeString(value) {
1119
+ return `${value}`;
1120
+ }
1121
+
1122
+ class Controller {
1123
+ constructor(context) {
1124
+ this.context = context;
1125
+ }
1126
+ static get shouldLoad() {
1127
+ return true;
1128
+ }
1129
+ static afterLoad(_identifier, _application) {
1130
+ return;
1131
+ }
1132
+ get application() {
1133
+ return this.context.application;
1134
+ }
1135
+ get scope() {
1136
+ return this.context.scope;
1137
+ }
1138
+ get element() {
1139
+ return this.scope.element;
1140
+ }
1141
+ get identifier() {
1142
+ return this.scope.identifier;
1143
+ }
1144
+ get targets() {
1145
+ return this.scope.targets;
1146
+ }
1147
+ get outlets() {
1148
+ return this.scope.outlets;
1149
+ }
1150
+ get classes() {
1151
+ return this.scope.classes;
1152
+ }
1153
+ get data() {
1154
+ return this.scope.data;
1155
+ }
1156
+ initialize() {
1157
+ }
1158
+ connect() {
1159
+ }
1160
+ disconnect() {
1161
+ }
1162
+ dispatch(eventName, { target = this.element, detail = {}, prefix = this.identifier, bubbles = true, cancelable = true, } = {}) {
1163
+ const type = prefix ? `${prefix}:${eventName}` : eventName;
1164
+ const event = new CustomEvent(type, { detail, bubbles, cancelable });
1165
+ target.dispatchEvent(event);
1166
+ return event;
1167
+ }
1168
+ }
1169
+ Controller.blessings = [
1170
+ ClassPropertiesBlessing,
1171
+ TargetPropertiesBlessing,
1172
+ ValuePropertiesBlessing,
1173
+ OutletPropertiesBlessing,
1174
+ ];
1175
+ Controller.targets = [];
1176
+ Controller.outlets = [];
1177
+ Controller.values = {};
1178
+
1179
+ var sparkMd5 = {
1180
+ exports: {}
1181
+ };
1182
+
1183
+ (function(module, exports) {
1184
+ (function(factory) {
1185
+ {
1186
+ module.exports = factory();
1187
+ }
1188
+ })((function(undefined$1) {
1189
+ var hex_chr = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" ];
1190
+ function md5cycle(x, k) {
1191
+ var a = x[0], b = x[1], c = x[2], d = x[3];
1192
+ a += (b & c | ~b & d) + k[0] - 680876936 | 0;
1193
+ a = (a << 7 | a >>> 25) + b | 0;
1194
+ d += (a & b | ~a & c) + k[1] - 389564586 | 0;
1195
+ d = (d << 12 | d >>> 20) + a | 0;
1196
+ c += (d & a | ~d & b) + k[2] + 606105819 | 0;
1197
+ c = (c << 17 | c >>> 15) + d | 0;
1198
+ b += (c & d | ~c & a) + k[3] - 1044525330 | 0;
1199
+ b = (b << 22 | b >>> 10) + c | 0;
1200
+ a += (b & c | ~b & d) + k[4] - 176418897 | 0;
1201
+ a = (a << 7 | a >>> 25) + b | 0;
1202
+ d += (a & b | ~a & c) + k[5] + 1200080426 | 0;
1203
+ d = (d << 12 | d >>> 20) + a | 0;
1204
+ c += (d & a | ~d & b) + k[6] - 1473231341 | 0;
1205
+ c = (c << 17 | c >>> 15) + d | 0;
1206
+ b += (c & d | ~c & a) + k[7] - 45705983 | 0;
1207
+ b = (b << 22 | b >>> 10) + c | 0;
1208
+ a += (b & c | ~b & d) + k[8] + 1770035416 | 0;
1209
+ a = (a << 7 | a >>> 25) + b | 0;
1210
+ d += (a & b | ~a & c) + k[9] - 1958414417 | 0;
1211
+ d = (d << 12 | d >>> 20) + a | 0;
1212
+ c += (d & a | ~d & b) + k[10] - 42063 | 0;
1213
+ c = (c << 17 | c >>> 15) + d | 0;
1214
+ b += (c & d | ~c & a) + k[11] - 1990404162 | 0;
1215
+ b = (b << 22 | b >>> 10) + c | 0;
1216
+ a += (b & c | ~b & d) + k[12] + 1804603682 | 0;
1217
+ a = (a << 7 | a >>> 25) + b | 0;
1218
+ d += (a & b | ~a & c) + k[13] - 40341101 | 0;
1219
+ d = (d << 12 | d >>> 20) + a | 0;
1220
+ c += (d & a | ~d & b) + k[14] - 1502002290 | 0;
1221
+ c = (c << 17 | c >>> 15) + d | 0;
1222
+ b += (c & d | ~c & a) + k[15] + 1236535329 | 0;
1223
+ b = (b << 22 | b >>> 10) + c | 0;
1224
+ a += (b & d | c & ~d) + k[1] - 165796510 | 0;
1225
+ a = (a << 5 | a >>> 27) + b | 0;
1226
+ d += (a & c | b & ~c) + k[6] - 1069501632 | 0;
1227
+ d = (d << 9 | d >>> 23) + a | 0;
1228
+ c += (d & b | a & ~b) + k[11] + 643717713 | 0;
1229
+ c = (c << 14 | c >>> 18) + d | 0;
1230
+ b += (c & a | d & ~a) + k[0] - 373897302 | 0;
1231
+ b = (b << 20 | b >>> 12) + c | 0;
1232
+ a += (b & d | c & ~d) + k[5] - 701558691 | 0;
1233
+ a = (a << 5 | a >>> 27) + b | 0;
1234
+ d += (a & c | b & ~c) + k[10] + 38016083 | 0;
1235
+ d = (d << 9 | d >>> 23) + a | 0;
1236
+ c += (d & b | a & ~b) + k[15] - 660478335 | 0;
1237
+ c = (c << 14 | c >>> 18) + d | 0;
1238
+ b += (c & a | d & ~a) + k[4] - 405537848 | 0;
1239
+ b = (b << 20 | b >>> 12) + c | 0;
1240
+ a += (b & d | c & ~d) + k[9] + 568446438 | 0;
1241
+ a = (a << 5 | a >>> 27) + b | 0;
1242
+ d += (a & c | b & ~c) + k[14] - 1019803690 | 0;
1243
+ d = (d << 9 | d >>> 23) + a | 0;
1244
+ c += (d & b | a & ~b) + k[3] - 187363961 | 0;
1245
+ c = (c << 14 | c >>> 18) + d | 0;
1246
+ b += (c & a | d & ~a) + k[8] + 1163531501 | 0;
1247
+ b = (b << 20 | b >>> 12) + c | 0;
1248
+ a += (b & d | c & ~d) + k[13] - 1444681467 | 0;
1249
+ a = (a << 5 | a >>> 27) + b | 0;
1250
+ d += (a & c | b & ~c) + k[2] - 51403784 | 0;
1251
+ d = (d << 9 | d >>> 23) + a | 0;
1252
+ c += (d & b | a & ~b) + k[7] + 1735328473 | 0;
1253
+ c = (c << 14 | c >>> 18) + d | 0;
1254
+ b += (c & a | d & ~a) + k[12] - 1926607734 | 0;
1255
+ b = (b << 20 | b >>> 12) + c | 0;
1256
+ a += (b ^ c ^ d) + k[5] - 378558 | 0;
1257
+ a = (a << 4 | a >>> 28) + b | 0;
1258
+ d += (a ^ b ^ c) + k[8] - 2022574463 | 0;
1259
+ d = (d << 11 | d >>> 21) + a | 0;
1260
+ c += (d ^ a ^ b) + k[11] + 1839030562 | 0;
1261
+ c = (c << 16 | c >>> 16) + d | 0;
1262
+ b += (c ^ d ^ a) + k[14] - 35309556 | 0;
1263
+ b = (b << 23 | b >>> 9) + c | 0;
1264
+ a += (b ^ c ^ d) + k[1] - 1530992060 | 0;
1265
+ a = (a << 4 | a >>> 28) + b | 0;
1266
+ d += (a ^ b ^ c) + k[4] + 1272893353 | 0;
1267
+ d = (d << 11 | d >>> 21) + a | 0;
1268
+ c += (d ^ a ^ b) + k[7] - 155497632 | 0;
1269
+ c = (c << 16 | c >>> 16) + d | 0;
1270
+ b += (c ^ d ^ a) + k[10] - 1094730640 | 0;
1271
+ b = (b << 23 | b >>> 9) + c | 0;
1272
+ a += (b ^ c ^ d) + k[13] + 681279174 | 0;
1273
+ a = (a << 4 | a >>> 28) + b | 0;
1274
+ d += (a ^ b ^ c) + k[0] - 358537222 | 0;
1275
+ d = (d << 11 | d >>> 21) + a | 0;
1276
+ c += (d ^ a ^ b) + k[3] - 722521979 | 0;
1277
+ c = (c << 16 | c >>> 16) + d | 0;
1278
+ b += (c ^ d ^ a) + k[6] + 76029189 | 0;
1279
+ b = (b << 23 | b >>> 9) + c | 0;
1280
+ a += (b ^ c ^ d) + k[9] - 640364487 | 0;
1281
+ a = (a << 4 | a >>> 28) + b | 0;
1282
+ d += (a ^ b ^ c) + k[12] - 421815835 | 0;
1283
+ d = (d << 11 | d >>> 21) + a | 0;
1284
+ c += (d ^ a ^ b) + k[15] + 530742520 | 0;
1285
+ c = (c << 16 | c >>> 16) + d | 0;
1286
+ b += (c ^ d ^ a) + k[2] - 995338651 | 0;
1287
+ b = (b << 23 | b >>> 9) + c | 0;
1288
+ a += (c ^ (b | ~d)) + k[0] - 198630844 | 0;
1289
+ a = (a << 6 | a >>> 26) + b | 0;
1290
+ d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0;
1291
+ d = (d << 10 | d >>> 22) + a | 0;
1292
+ c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0;
1293
+ c = (c << 15 | c >>> 17) + d | 0;
1294
+ b += (d ^ (c | ~a)) + k[5] - 57434055 | 0;
1295
+ b = (b << 21 | b >>> 11) + c | 0;
1296
+ a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0;
1297
+ a = (a << 6 | a >>> 26) + b | 0;
1298
+ d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0;
1299
+ d = (d << 10 | d >>> 22) + a | 0;
1300
+ c += (a ^ (d | ~b)) + k[10] - 1051523 | 0;
1301
+ c = (c << 15 | c >>> 17) + d | 0;
1302
+ b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0;
1303
+ b = (b << 21 | b >>> 11) + c | 0;
1304
+ a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0;
1305
+ a = (a << 6 | a >>> 26) + b | 0;
1306
+ d += (b ^ (a | ~c)) + k[15] - 30611744 | 0;
1307
+ d = (d << 10 | d >>> 22) + a | 0;
1308
+ c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0;
1309
+ c = (c << 15 | c >>> 17) + d | 0;
1310
+ b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0;
1311
+ b = (b << 21 | b >>> 11) + c | 0;
1312
+ a += (c ^ (b | ~d)) + k[4] - 145523070 | 0;
1313
+ a = (a << 6 | a >>> 26) + b | 0;
1314
+ d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0;
1315
+ d = (d << 10 | d >>> 22) + a | 0;
1316
+ c += (a ^ (d | ~b)) + k[2] + 718787259 | 0;
1317
+ c = (c << 15 | c >>> 17) + d | 0;
1318
+ b += (d ^ (c | ~a)) + k[9] - 343485551 | 0;
1319
+ b = (b << 21 | b >>> 11) + c | 0;
1320
+ x[0] = a + x[0] | 0;
1321
+ x[1] = b + x[1] | 0;
1322
+ x[2] = c + x[2] | 0;
1323
+ x[3] = d + x[3] | 0;
1324
+ }
1325
+ function md5blk(s) {
1326
+ var md5blks = [], i;
1327
+ for (i = 0; i < 64; i += 4) {
1328
+ md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
1329
+ }
1330
+ return md5blks;
1331
+ }
1332
+ function md5blk_array(a) {
1333
+ var md5blks = [], i;
1334
+ for (i = 0; i < 64; i += 4) {
1335
+ md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);
1336
+ }
1337
+ return md5blks;
1338
+ }
1339
+ function md51(s) {
1340
+ var n = s.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;
1341
+ for (i = 64; i <= n; i += 64) {
1342
+ md5cycle(state, md5blk(s.substring(i - 64, i)));
1343
+ }
1344
+ s = s.substring(i - 64);
1345
+ length = s.length;
1346
+ tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
1347
+ for (i = 0; i < length; i += 1) {
1348
+ tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3);
1349
+ }
1350
+ tail[i >> 2] |= 128 << (i % 4 << 3);
1351
+ if (i > 55) {
1352
+ md5cycle(state, tail);
1353
+ for (i = 0; i < 16; i += 1) {
1354
+ tail[i] = 0;
1355
+ }
1356
+ }
1357
+ tmp = n * 8;
1358
+ tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
1359
+ lo = parseInt(tmp[2], 16);
1360
+ hi = parseInt(tmp[1], 16) || 0;
1361
+ tail[14] = lo;
1362
+ tail[15] = hi;
1363
+ md5cycle(state, tail);
1364
+ return state;
1365
+ }
1366
+ function md51_array(a) {
1367
+ var n = a.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;
1368
+ for (i = 64; i <= n; i += 64) {
1369
+ md5cycle(state, md5blk_array(a.subarray(i - 64, i)));
1370
+ }
1371
+ a = i - 64 < n ? a.subarray(i - 64) : new Uint8Array(0);
1372
+ length = a.length;
1373
+ tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
1374
+ for (i = 0; i < length; i += 1) {
1375
+ tail[i >> 2] |= a[i] << (i % 4 << 3);
1376
+ }
1377
+ tail[i >> 2] |= 128 << (i % 4 << 3);
1378
+ if (i > 55) {
1379
+ md5cycle(state, tail);
1380
+ for (i = 0; i < 16; i += 1) {
1381
+ tail[i] = 0;
1382
+ }
1383
+ }
1384
+ tmp = n * 8;
1385
+ tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
1386
+ lo = parseInt(tmp[2], 16);
1387
+ hi = parseInt(tmp[1], 16) || 0;
1388
+ tail[14] = lo;
1389
+ tail[15] = hi;
1390
+ md5cycle(state, tail);
1391
+ return state;
1392
+ }
1393
+ function rhex(n) {
1394
+ var s = "", j;
1395
+ for (j = 0; j < 4; j += 1) {
1396
+ s += hex_chr[n >> j * 8 + 4 & 15] + hex_chr[n >> j * 8 & 15];
1397
+ }
1398
+ return s;
1399
+ }
1400
+ function hex(x) {
1401
+ var i;
1402
+ for (i = 0; i < x.length; i += 1) {
1403
+ x[i] = rhex(x[i]);
1404
+ }
1405
+ return x.join("");
1406
+ }
1407
+ if (hex(md51("hello")) !== "5d41402abc4b2a76b9719d911017c592") ;
1408
+ if (typeof ArrayBuffer !== "undefined" && !ArrayBuffer.prototype.slice) {
1409
+ (function() {
1410
+ function clamp(val, length) {
1411
+ val = val | 0 || 0;
1412
+ if (val < 0) {
1413
+ return Math.max(val + length, 0);
1414
+ }
1415
+ return Math.min(val, length);
1416
+ }
1417
+ ArrayBuffer.prototype.slice = function(from, to) {
1418
+ var length = this.byteLength, begin = clamp(from, length), end = length, num, target, targetArray, sourceArray;
1419
+ if (to !== undefined$1) {
1420
+ end = clamp(to, length);
1421
+ }
1422
+ if (begin > end) {
1423
+ return new ArrayBuffer(0);
1424
+ }
1425
+ num = end - begin;
1426
+ target = new ArrayBuffer(num);
1427
+ targetArray = new Uint8Array(target);
1428
+ sourceArray = new Uint8Array(this, begin, num);
1429
+ targetArray.set(sourceArray);
1430
+ return target;
1431
+ };
1432
+ })();
1433
+ }
1434
+ function toUtf8(str) {
1435
+ if (/[\u0080-\uFFFF]/.test(str)) {
1436
+ str = unescape(encodeURIComponent(str));
1437
+ }
1438
+ return str;
1439
+ }
1440
+ function utf8Str2ArrayBuffer(str, returnUInt8Array) {
1441
+ var length = str.length, buff = new ArrayBuffer(length), arr = new Uint8Array(buff), i;
1442
+ for (i = 0; i < length; i += 1) {
1443
+ arr[i] = str.charCodeAt(i);
1444
+ }
1445
+ return returnUInt8Array ? arr : buff;
1446
+ }
1447
+ function arrayBuffer2Utf8Str(buff) {
1448
+ return String.fromCharCode.apply(null, new Uint8Array(buff));
1449
+ }
1450
+ function concatenateArrayBuffers(first, second, returnUInt8Array) {
1451
+ var result = new Uint8Array(first.byteLength + second.byteLength);
1452
+ result.set(new Uint8Array(first));
1453
+ result.set(new Uint8Array(second), first.byteLength);
1454
+ return result ;
1455
+ }
1456
+ function hexToBinaryString(hex) {
1457
+ var bytes = [], length = hex.length, x;
1458
+ for (x = 0; x < length - 1; x += 2) {
1459
+ bytes.push(parseInt(hex.substr(x, 2), 16));
1460
+ }
1461
+ return String.fromCharCode.apply(String, bytes);
1462
+ }
1463
+ function SparkMD5() {
1464
+ this.reset();
1465
+ }
1466
+ SparkMD5.prototype.append = function(str) {
1467
+ this.appendBinary(toUtf8(str));
1468
+ return this;
1469
+ };
1470
+ SparkMD5.prototype.appendBinary = function(contents) {
1471
+ this._buff += contents;
1472
+ this._length += contents.length;
1473
+ var length = this._buff.length, i;
1474
+ for (i = 64; i <= length; i += 64) {
1475
+ md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i)));
1476
+ }
1477
+ this._buff = this._buff.substring(i - 64);
1478
+ return this;
1479
+ };
1480
+ SparkMD5.prototype.end = function(raw) {
1481
+ 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;
1482
+ for (i = 0; i < length; i += 1) {
1483
+ tail[i >> 2] |= buff.charCodeAt(i) << (i % 4 << 3);
1484
+ }
1485
+ this._finish(tail, length);
1486
+ ret = hex(this._hash);
1487
+ if (raw) {
1488
+ ret = hexToBinaryString(ret);
1489
+ }
1490
+ this.reset();
1491
+ return ret;
1492
+ };
1493
+ SparkMD5.prototype.reset = function() {
1494
+ this._buff = "";
1495
+ this._length = 0;
1496
+ this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];
1497
+ return this;
1498
+ };
1499
+ SparkMD5.prototype.getState = function() {
1500
+ return {
1501
+ buff: this._buff,
1502
+ length: this._length,
1503
+ hash: this._hash.slice()
1504
+ };
1505
+ };
1506
+ SparkMD5.prototype.setState = function(state) {
1507
+ this._buff = state.buff;
1508
+ this._length = state.length;
1509
+ this._hash = state.hash;
1510
+ return this;
1511
+ };
1512
+ SparkMD5.prototype.destroy = function() {
1513
+ delete this._hash;
1514
+ delete this._buff;
1515
+ delete this._length;
1516
+ };
1517
+ SparkMD5.prototype._finish = function(tail, length) {
1518
+ var i = length, tmp, lo, hi;
1519
+ tail[i >> 2] |= 128 << (i % 4 << 3);
1520
+ if (i > 55) {
1521
+ md5cycle(this._hash, tail);
1522
+ for (i = 0; i < 16; i += 1) {
1523
+ tail[i] = 0;
1524
+ }
1525
+ }
1526
+ tmp = this._length * 8;
1527
+ tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
1528
+ lo = parseInt(tmp[2], 16);
1529
+ hi = parseInt(tmp[1], 16) || 0;
1530
+ tail[14] = lo;
1531
+ tail[15] = hi;
1532
+ md5cycle(this._hash, tail);
1533
+ };
1534
+ SparkMD5.hash = function(str, raw) {
1535
+ return SparkMD5.hashBinary(toUtf8(str), raw);
1536
+ };
1537
+ SparkMD5.hashBinary = function(content, raw) {
1538
+ var hash = md51(content), ret = hex(hash);
1539
+ return raw ? hexToBinaryString(ret) : ret;
1540
+ };
1541
+ SparkMD5.ArrayBuffer = function() {
1542
+ this.reset();
1543
+ };
1544
+ SparkMD5.ArrayBuffer.prototype.append = function(arr) {
1545
+ var buff = concatenateArrayBuffers(this._buff.buffer, arr), length = buff.length, i;
1546
+ this._length += arr.byteLength;
1547
+ for (i = 64; i <= length; i += 64) {
1548
+ md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i)));
1549
+ }
1550
+ this._buff = i - 64 < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0);
1551
+ return this;
1552
+ };
1553
+ SparkMD5.ArrayBuffer.prototype.end = function(raw) {
1554
+ 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;
1555
+ for (i = 0; i < length; i += 1) {
1556
+ tail[i >> 2] |= buff[i] << (i % 4 << 3);
1557
+ }
1558
+ this._finish(tail, length);
1559
+ ret = hex(this._hash);
1560
+ if (raw) {
1561
+ ret = hexToBinaryString(ret);
1562
+ }
1563
+ this.reset();
1564
+ return ret;
1565
+ };
1566
+ SparkMD5.ArrayBuffer.prototype.reset = function() {
1567
+ this._buff = new Uint8Array(0);
1568
+ this._length = 0;
1569
+ this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];
1570
+ return this;
1571
+ };
1572
+ SparkMD5.ArrayBuffer.prototype.getState = function() {
1573
+ var state = SparkMD5.prototype.getState.call(this);
1574
+ state.buff = arrayBuffer2Utf8Str(state.buff);
1575
+ return state;
1576
+ };
1577
+ SparkMD5.ArrayBuffer.prototype.setState = function(state) {
1578
+ state.buff = utf8Str2ArrayBuffer(state.buff, true);
1579
+ return SparkMD5.prototype.setState.call(this, state);
1580
+ };
1581
+ SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;
1582
+ SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;
1583
+ SparkMD5.ArrayBuffer.hash = function(arr, raw) {
1584
+ var hash = md51_array(new Uint8Array(arr)), ret = hex(hash);
1585
+ return raw ? hexToBinaryString(ret) : ret;
1586
+ };
1587
+ return SparkMD5;
1588
+ }));
1589
+ })(sparkMd5);
1590
+
1591
+ var SparkMD5 = sparkMd5.exports;
1592
+
1593
+ const fileSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
1594
+
1595
+ class FileChecksum {
1596
+ static create(file, callback) {
1597
+ const instance = new FileChecksum(file);
1598
+ instance.create(callback);
1599
+ }
1600
+ constructor(file) {
1601
+ this.file = file;
1602
+ this.chunkSize = 2097152;
1603
+ this.chunkCount = Math.ceil(this.file.size / this.chunkSize);
1604
+ this.chunkIndex = 0;
1605
+ }
1606
+ create(callback) {
1607
+ this.callback = callback;
1608
+ this.md5Buffer = new SparkMD5.ArrayBuffer;
1609
+ this.fileReader = new FileReader;
1610
+ this.fileReader.addEventListener("load", (event => this.fileReaderDidLoad(event)));
1611
+ this.fileReader.addEventListener("error", (event => this.fileReaderDidError(event)));
1612
+ this.readNextChunk();
1613
+ }
1614
+ fileReaderDidLoad(event) {
1615
+ this.md5Buffer.append(event.target.result);
1616
+ if (!this.readNextChunk()) {
1617
+ const binaryDigest = this.md5Buffer.end(true);
1618
+ const base64digest = btoa(binaryDigest);
1619
+ this.callback(null, base64digest);
1620
+ }
1621
+ }
1622
+ fileReaderDidError(event) {
1623
+ this.callback(`Error reading ${this.file.name}`);
1624
+ }
1625
+ readNextChunk() {
1626
+ if (this.chunkIndex < this.chunkCount || this.chunkIndex == 0 && this.chunkCount == 0) {
1627
+ const start = this.chunkIndex * this.chunkSize;
1628
+ const end = Math.min(start + this.chunkSize, this.file.size);
1629
+ const bytes = fileSlice.call(this.file, start, end);
1630
+ this.fileReader.readAsArrayBuffer(bytes);
1631
+ this.chunkIndex++;
1632
+ return true;
1633
+ } else {
1634
+ return false;
1635
+ }
1636
+ }
1637
+ }
1638
+
1639
+ function getMetaValue(name) {
1640
+ const element = findElement(document.head, `meta[name="${name}"]`);
1641
+ if (element) {
1642
+ return element.getAttribute("content");
1643
+ }
1644
+ }
1645
+
1646
+ function findElements(root, selector) {
1647
+ if (typeof root == "string") {
1648
+ selector = root;
1649
+ root = document;
1650
+ }
1651
+ const elements = root.querySelectorAll(selector);
1652
+ return toArray(elements);
1653
+ }
1654
+
1655
+ function findElement(root, selector) {
1656
+ if (typeof root == "string") {
1657
+ selector = root;
1658
+ root = document;
1659
+ }
1660
+ return root.querySelector(selector);
1661
+ }
1662
+
1663
+ function dispatchEvent(element, type, eventInit = {}) {
1664
+ const {disabled: disabled} = element;
1665
+ const {bubbles: bubbles, cancelable: cancelable, detail: detail} = eventInit;
1666
+ const event = document.createEvent("Event");
1667
+ event.initEvent(type, bubbles || true, cancelable || true);
1668
+ event.detail = detail || {};
1669
+ try {
1670
+ element.disabled = false;
1671
+ element.dispatchEvent(event);
1672
+ } finally {
1673
+ element.disabled = disabled;
1674
+ }
1675
+ return event;
1676
+ }
1677
+
1678
+ function toArray(value) {
1679
+ if (Array.isArray(value)) {
1680
+ return value;
1681
+ } else if (Array.from) {
1682
+ return Array.from(value);
1683
+ } else {
1684
+ return [].slice.call(value);
1685
+ }
1686
+ }
1687
+
1688
+ class BlobRecord {
1689
+ constructor(file, checksum, url, customHeaders = {}) {
1690
+ this.file = file;
1691
+ this.attributes = {
1692
+ filename: file.name,
1693
+ content_type: file.type || "application/octet-stream",
1694
+ byte_size: file.size,
1695
+ checksum: checksum
1696
+ };
1697
+ this.xhr = new XMLHttpRequest;
1698
+ this.xhr.open("POST", url, true);
1699
+ this.xhr.responseType = "json";
1700
+ this.xhr.setRequestHeader("Content-Type", "application/json");
1701
+ this.xhr.setRequestHeader("Accept", "application/json");
1702
+ this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
1703
+ Object.keys(customHeaders).forEach((headerKey => {
1704
+ this.xhr.setRequestHeader(headerKey, customHeaders[headerKey]);
1705
+ }));
1706
+ const csrfToken = getMetaValue("csrf-token");
1707
+ if (csrfToken != undefined) {
1708
+ this.xhr.setRequestHeader("X-CSRF-Token", csrfToken);
1709
+ }
1710
+ this.xhr.addEventListener("load", (event => this.requestDidLoad(event)));
1711
+ this.xhr.addEventListener("error", (event => this.requestDidError(event)));
1712
+ }
1713
+ get status() {
1714
+ return this.xhr.status;
1715
+ }
1716
+ get response() {
1717
+ const {responseType: responseType, response: response} = this.xhr;
1718
+ if (responseType == "json") {
1719
+ return response;
1720
+ } else {
1721
+ return JSON.parse(response);
1722
+ }
1723
+ }
1724
+ create(callback) {
1725
+ this.callback = callback;
1726
+ this.xhr.send(JSON.stringify({
1727
+ blob: this.attributes
1728
+ }));
1729
+ }
1730
+ requestDidLoad(event) {
1731
+ if (this.status >= 200 && this.status < 300) {
1732
+ const {response: response} = this;
1733
+ const {direct_upload: direct_upload} = response;
1734
+ delete response.direct_upload;
1735
+ this.attributes = response;
1736
+ this.directUploadData = direct_upload;
1737
+ this.callback(null, this.toJSON());
1738
+ } else {
1739
+ this.requestDidError(event);
1740
+ }
1741
+ }
1742
+ requestDidError(event) {
1743
+ this.callback(`Error creating Blob for "${this.file.name}". Status: ${this.status}`);
1744
+ }
1745
+ toJSON() {
1746
+ const result = {};
1747
+ for (const key in this.attributes) {
1748
+ result[key] = this.attributes[key];
1749
+ }
1750
+ return result;
1751
+ }
1752
+ }
1753
+
1754
+ class BlobUpload {
1755
+ constructor(blob) {
1756
+ this.blob = blob;
1757
+ this.file = blob.file;
1758
+ const {url: url, headers: headers} = blob.directUploadData;
1759
+ this.xhr = new XMLHttpRequest;
1760
+ this.xhr.open("PUT", url, true);
1761
+ this.xhr.responseType = "text";
1762
+ for (const key in headers) {
1763
+ this.xhr.setRequestHeader(key, headers[key]);
1764
+ }
1765
+ this.xhr.addEventListener("load", (event => this.requestDidLoad(event)));
1766
+ this.xhr.addEventListener("error", (event => this.requestDidError(event)));
1767
+ }
1768
+ create(callback) {
1769
+ this.callback = callback;
1770
+ this.xhr.send(this.file.slice());
1771
+ }
1772
+ requestDidLoad(event) {
1773
+ const {status: status, response: response} = this.xhr;
1774
+ if (status >= 200 && status < 300) {
1775
+ this.callback(null, response);
1776
+ } else {
1777
+ this.requestDidError(event);
1778
+ }
1779
+ }
1780
+ requestDidError(event) {
1781
+ this.callback(`Error storing "${this.file.name}". Status: ${this.xhr.status}`);
1782
+ }
1783
+ }
1784
+
1785
+ let id = 0;
1786
+
1787
+ class DirectUpload {
1788
+ constructor(file, url, delegate, customHeaders = {}) {
1789
+ this.id = ++id;
1790
+ this.file = file;
1791
+ this.url = url;
1792
+ this.delegate = delegate;
1793
+ this.customHeaders = customHeaders;
1794
+ }
1795
+ create(callback) {
1796
+ FileChecksum.create(this.file, ((error, checksum) => {
1797
+ if (error) {
1798
+ callback(error);
1799
+ return;
1800
+ }
1801
+ const blob = new BlobRecord(this.file, checksum, this.url, this.customHeaders);
1802
+ notify(this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr);
1803
+ blob.create((error => {
1804
+ if (error) {
1805
+ callback(error);
1806
+ } else {
1807
+ const upload = new BlobUpload(blob);
1808
+ notify(this.delegate, "directUploadWillStoreFileWithXHR", upload.xhr);
1809
+ upload.create((error => {
1810
+ if (error) {
1811
+ callback(error);
1812
+ } else {
1813
+ callback(null, blob.toJSON());
1814
+ }
1815
+ }));
1816
+ }
1817
+ }));
1818
+ }));
1819
+ }
1820
+ }
1821
+
1822
+ function notify(object, methodName, ...messages) {
1823
+ if (object && typeof object[methodName] == "function") {
1824
+ return object[methodName](...messages);
1825
+ }
1826
+ }
1827
+
1828
+ class DirectUploadController {
1829
+ constructor(input, file) {
1830
+ this.input = input;
1831
+ this.file = file;
1832
+ this.directUpload = new DirectUpload(this.file, this.url, this);
1833
+ this.dispatch("initialize");
1834
+ }
1835
+ start(callback) {
1836
+ const hiddenInput = document.createElement("input");
1837
+ hiddenInput.type = "hidden";
1838
+ hiddenInput.name = this.input.name;
1839
+ this.input.insertAdjacentElement("beforebegin", hiddenInput);
1840
+ this.dispatch("start");
1841
+ this.directUpload.create(((error, attributes) => {
1842
+ if (error) {
1843
+ hiddenInput.parentNode.removeChild(hiddenInput);
1844
+ this.dispatchError(error);
1845
+ } else {
1846
+ hiddenInput.value = attributes.signed_id;
1847
+ }
1848
+ this.dispatch("end");
1849
+ callback(error);
1850
+ }));
1851
+ }
1852
+ uploadRequestDidProgress(event) {
1853
+ const progress = event.loaded / event.total * 100;
1854
+ if (progress) {
1855
+ this.dispatch("progress", {
1856
+ progress: progress
1857
+ });
1858
+ }
1859
+ }
1860
+ get url() {
1861
+ return this.input.getAttribute("data-direct-upload-url");
1862
+ }
1863
+ dispatch(name, detail = {}) {
1864
+ detail.file = this.file;
1865
+ detail.id = this.directUpload.id;
1866
+ return dispatchEvent(this.input, `direct-upload:${name}`, {
1867
+ detail: detail
1868
+ });
1869
+ }
1870
+ dispatchError(error) {
1871
+ const event = this.dispatch("error", {
1872
+ error: error
1873
+ });
1874
+ if (!event.defaultPrevented) {
1875
+ alert(error);
1876
+ }
1877
+ }
1878
+ directUploadWillCreateBlobWithXHR(xhr) {
1879
+ this.dispatch("before-blob-request", {
1880
+ xhr: xhr
1881
+ });
1882
+ }
1883
+ directUploadWillStoreFileWithXHR(xhr) {
1884
+ this.dispatch("before-storage-request", {
1885
+ xhr: xhr
1886
+ });
1887
+ xhr.upload.addEventListener("progress", (event => this.uploadRequestDidProgress(event)));
1888
+ }
1889
+ }
1890
+
1891
+ const inputSelector = "input[type=file][data-direct-upload-url]:not([disabled])";
1892
+
1893
+ class DirectUploadsController {
1894
+ constructor(form) {
1895
+ this.form = form;
1896
+ this.inputs = findElements(form, inputSelector).filter((input => input.files.length));
1897
+ }
1898
+ start(callback) {
1899
+ const controllers = this.createDirectUploadControllers();
1900
+ const startNextController = () => {
1901
+ const controller = controllers.shift();
1902
+ if (controller) {
1903
+ controller.start((error => {
1904
+ if (error) {
1905
+ callback(error);
1906
+ this.dispatch("end");
1907
+ } else {
1908
+ startNextController();
1909
+ }
1910
+ }));
1911
+ } else {
1912
+ callback();
1913
+ this.dispatch("end");
1914
+ }
1915
+ };
1916
+ this.dispatch("start");
1917
+ startNextController();
1918
+ }
1919
+ createDirectUploadControllers() {
1920
+ const controllers = [];
1921
+ this.inputs.forEach((input => {
1922
+ toArray(input.files).forEach((file => {
1923
+ const controller = new DirectUploadController(input, file);
1924
+ controllers.push(controller);
1925
+ }));
1926
+ }));
1927
+ return controllers;
1928
+ }
1929
+ dispatch(name, detail = {}) {
1930
+ return dispatchEvent(this.form, `direct-uploads:${name}`, {
1931
+ detail: detail
1932
+ });
1933
+ }
1934
+ }
1935
+
1936
+ const processingAttribute = "data-direct-uploads-processing";
1937
+
1938
+ const submitButtonsByForm = new WeakMap;
1939
+
1940
+ let started = false;
1941
+
1942
+ function start() {
1943
+ if (!started) {
1944
+ started = true;
1945
+ document.addEventListener("click", didClick, true);
1946
+ document.addEventListener("submit", didSubmitForm, true);
1947
+ document.addEventListener("ajax:before", didSubmitRemoteElement);
1948
+ }
1949
+ }
1950
+
1951
+ function didClick(event) {
1952
+ const button = event.target.closest("button, input");
1953
+ if (button && button.type === "submit" && button.form) {
1954
+ submitButtonsByForm.set(button.form, button);
1955
+ }
1956
+ }
1957
+
1958
+ function didSubmitForm(event) {
1959
+ handleFormSubmissionEvent(event);
1960
+ }
1961
+
1962
+ function didSubmitRemoteElement(event) {
1963
+ if (event.target.tagName == "FORM") {
1964
+ handleFormSubmissionEvent(event);
1965
+ }
1966
+ }
1967
+
1968
+ function handleFormSubmissionEvent(event) {
1969
+ const form = event.target;
1970
+ if (form.hasAttribute(processingAttribute)) {
1971
+ event.preventDefault();
1972
+ return;
1973
+ }
1974
+ const controller = new DirectUploadsController(form);
1975
+ const {inputs: inputs} = controller;
1976
+ if (inputs.length) {
1977
+ event.preventDefault();
1978
+ form.setAttribute(processingAttribute, "");
1979
+ inputs.forEach(disable);
1980
+ controller.start((error => {
1981
+ form.removeAttribute(processingAttribute);
1982
+ if (error) {
1983
+ inputs.forEach(enable);
1984
+ } else {
1985
+ submitForm(form);
1986
+ }
1987
+ }));
1988
+ }
1989
+ }
1990
+
1991
+ function submitForm(form) {
1992
+ let button = submitButtonsByForm.get(form) || findElement(form, "input[type=submit], button[type=submit]");
1993
+ if (button) {
1994
+ const {disabled: disabled} = button;
1995
+ button.disabled = false;
1996
+ button.focus();
1997
+ button.click();
1998
+ button.disabled = disabled;
1999
+ } else {
2000
+ button = document.createElement("input");
2001
+ button.type = "submit";
2002
+ button.style.display = "none";
2003
+ form.appendChild(button);
2004
+ button.click();
2005
+ form.removeChild(button);
2006
+ }
2007
+ submitButtonsByForm.delete(form);
2008
+ }
2009
+
2010
+ function disable(input) {
2011
+ input.disabled = true;
2012
+ }
2013
+
2014
+ function enable(input) {
2015
+ input.disabled = false;
2016
+ }
2017
+
2018
+ function autostart() {
2019
+ if (window.ActiveStorage) {
2020
+ start();
2021
+ }
2022
+ }
2023
+
2024
+ setTimeout(autostart, 1);
2025
+
2026
+ class FetchResponse {
2027
+ constructor (response) {
2028
+ this.response = response;
2029
+ }
2030
+
2031
+ get statusCode () {
2032
+ return this.response.status
2033
+ }
2034
+
2035
+ get redirected () {
2036
+ return this.response.redirected
2037
+ }
2038
+
2039
+ get ok () {
2040
+ return this.response.ok
2041
+ }
2042
+
2043
+ get unauthenticated () {
2044
+ return this.statusCode === 401
2045
+ }
2046
+
2047
+ get unprocessableEntity () {
2048
+ return this.statusCode === 422
2049
+ }
2050
+
2051
+ get authenticationURL () {
2052
+ return this.response.headers.get('WWW-Authenticate')
2053
+ }
2054
+
2055
+ get contentType () {
2056
+ const contentType = this.response.headers.get('Content-Type') || '';
2057
+
2058
+ return contentType.replace(/;.*$/, '')
2059
+ }
2060
+
2061
+ get headers () {
2062
+ return this.response.headers
2063
+ }
2064
+
2065
+ get html () {
2066
+ if (this.contentType.match(/^(application|text)\/(html|xhtml\+xml)$/)) {
2067
+ return this.text
2068
+ }
2069
+
2070
+ return Promise.reject(new Error(`Expected an HTML response but got "${this.contentType}" instead`))
2071
+ }
2072
+
2073
+ get json () {
2074
+ if (this.contentType.match(/^application\/.*json$/)) {
2075
+ return this.responseJson || (this.responseJson = this.response.json())
2076
+ }
2077
+
2078
+ return Promise.reject(new Error(`Expected a JSON response but got "${this.contentType}" instead`))
2079
+ }
2080
+
2081
+ get text () {
2082
+ return this.responseText || (this.responseText = this.response.text())
2083
+ }
2084
+
2085
+ get isTurboStream () {
2086
+ return this.contentType.match(/^text\/vnd\.turbo-stream\.html/)
2087
+ }
2088
+
2089
+ get isScript () {
2090
+ return this.contentType.match(/\b(?:java|ecma)script\b/)
2091
+ }
2092
+
2093
+ async renderTurboStream () {
2094
+ if (this.isTurboStream) {
2095
+ if (window.Turbo) {
2096
+ await window.Turbo.renderStreamMessage(await this.text);
2097
+ } else {
2098
+ console.warn('You must set `window.Turbo = Turbo` to automatically process Turbo Stream events with request.js');
2099
+ }
2100
+ } else {
2101
+ return Promise.reject(new Error(`Expected a Turbo Stream response but got "${this.contentType}" instead`))
2102
+ }
2103
+ }
2104
+
2105
+ async activeScript () {
2106
+ if (this.isScript) {
2107
+ const script = document.createElement('script');
2108
+ const metaTag = document.querySelector('meta[name=csp-nonce]');
2109
+ const nonce = metaTag && metaTag.content;
2110
+ if (nonce) { script.setAttribute('nonce', nonce); }
2111
+ script.innerHTML = await this.text;
2112
+ document.body.appendChild(script);
2113
+ } else {
2114
+ return Promise.reject(new Error(`Expected a Script response but got "${this.contentType}" instead`))
2115
+ }
2116
+ }
2117
+ }
2118
+
2119
+ class RequestInterceptor {
2120
+ static register (interceptor) {
2121
+ this.interceptor = interceptor;
2122
+ }
2123
+
2124
+ static get () {
2125
+ return this.interceptor
2126
+ }
2127
+
2128
+ static reset () {
2129
+ this.interceptor = undefined;
2130
+ }
2131
+ }
2132
+
2133
+ function getCookie (name) {
2134
+ const cookies = document.cookie ? document.cookie.split('; ') : [];
2135
+ const prefix = `${encodeURIComponent(name)}=`;
2136
+ const cookie = cookies.find(cookie => cookie.startsWith(prefix));
2137
+
2138
+ if (cookie) {
2139
+ const value = cookie.split('=').slice(1).join('=');
2140
+
2141
+ if (value) {
2142
+ return decodeURIComponent(value)
2143
+ }
2144
+ }
2145
+ }
2146
+
2147
+ function compact (object) {
2148
+ const result = {};
2149
+
2150
+ for (const key in object) {
2151
+ const value = object[key];
2152
+ if (value !== undefined) {
2153
+ result[key] = value;
2154
+ }
2155
+ }
2156
+
2157
+ return result
2158
+ }
2159
+
2160
+ function metaContent (name) {
2161
+ const element = document.head.querySelector(`meta[name="${name}"]`);
2162
+ return element && element.content
2163
+ }
2164
+
2165
+ function stringEntriesFromFormData (formData) {
2166
+ return [...formData].reduce((entries, [name, value]) => {
2167
+ return entries.concat(typeof value === 'string' ? [[name, value]] : [])
2168
+ }, [])
2169
+ }
2170
+
2171
+ function mergeEntries (searchParams, entries) {
2172
+ for (const [name, value] of entries) {
2173
+ if (value instanceof window.File) continue
2174
+
2175
+ if (searchParams.has(name) && !name.includes('[]')) {
2176
+ searchParams.delete(name);
2177
+ searchParams.set(name, value);
2178
+ } else {
2179
+ searchParams.append(name, value);
2180
+ }
2181
+ }
2182
+ }
2183
+
2184
+ class FetchRequest {
2185
+ constructor (method, url, options = {}) {
2186
+ this.method = method;
2187
+ this.options = options;
2188
+ this.originalUrl = url.toString();
2189
+ }
2190
+
2191
+ async perform () {
2192
+ try {
2193
+ const requestInterceptor = RequestInterceptor.get();
2194
+ if (requestInterceptor) {
2195
+ await requestInterceptor(this);
2196
+ }
2197
+ } catch (error) {
2198
+ console.error(error);
2199
+ }
2200
+
2201
+ const fetch = (this.responseKind === 'turbo-stream' && window.Turbo)
2202
+ ? window.Turbo.fetch
2203
+ : window.fetch;
2204
+
2205
+ const response = new FetchResponse(await fetch(this.url, this.fetchOptions));
2206
+
2207
+ if (response.unauthenticated && response.authenticationURL) {
2208
+ return Promise.reject(window.location.href = response.authenticationURL)
2209
+ }
2210
+
2211
+ if (response.isScript) {
2212
+ await response.activeScript();
2213
+ }
2214
+
2215
+ const responseStatusIsTurboStreamable = response.ok || response.unprocessableEntity;
2216
+
2217
+ if (responseStatusIsTurboStreamable && response.isTurboStream) {
2218
+ await response.renderTurboStream();
2219
+ }
2220
+
2221
+ return response
2222
+ }
2223
+
2224
+ addHeader (key, value) {
2225
+ const headers = this.additionalHeaders;
2226
+ headers[key] = value;
2227
+ this.options.headers = headers;
2228
+ }
2229
+
2230
+ sameHostname () {
2231
+ if (!this.originalUrl.startsWith('http:')) {
2232
+ return true
2233
+ }
2234
+
2235
+ try {
2236
+ return new URL(this.originalUrl).hostname === window.location.hostname
2237
+ } catch (_) {
2238
+ return true
2239
+ }
2240
+ }
2241
+
2242
+ get fetchOptions () {
2243
+ return {
2244
+ method: this.method.toUpperCase(),
2245
+ headers: this.headers,
2246
+ body: this.formattedBody,
2247
+ signal: this.signal,
2248
+ credentials: this.credentials,
2249
+ redirect: this.redirect
2250
+ }
2251
+ }
2252
+
2253
+ get headers () {
2254
+ const baseHeaders = {
2255
+ 'X-Requested-With': 'XMLHttpRequest',
2256
+ 'Content-Type': this.contentType,
2257
+ Accept: this.accept
2258
+ };
2259
+
2260
+ if (this.sameHostname()) {
2261
+ baseHeaders['X-CSRF-Token'] = this.csrfToken;
2262
+ }
2263
+
2264
+ return compact(
2265
+ Object.assign(baseHeaders, this.additionalHeaders)
2266
+ )
2267
+ }
2268
+
2269
+ get csrfToken () {
2270
+ return getCookie(metaContent('csrf-param')) || metaContent('csrf-token')
2271
+ }
2272
+
2273
+ get contentType () {
2274
+ if (this.options.contentType) {
2275
+ return this.options.contentType
2276
+ } else if (this.body == null || this.body instanceof window.FormData) {
2277
+ return undefined
2278
+ } else if (this.body instanceof window.File) {
2279
+ return this.body.type
2280
+ }
2281
+
2282
+ return 'application/json'
2283
+ }
2284
+
2285
+ get accept () {
2286
+ switch (this.responseKind) {
2287
+ case 'html':
2288
+ return 'text/html, application/xhtml+xml'
2289
+ case 'turbo-stream':
2290
+ return 'text/vnd.turbo-stream.html, text/html, application/xhtml+xml'
2291
+ case 'json':
2292
+ return 'application/json, application/vnd.api+json'
2293
+ case 'script':
2294
+ return 'text/javascript, application/javascript'
2295
+ default:
2296
+ return '*/*'
2297
+ }
2298
+ }
2299
+
2300
+ get body () {
2301
+ return this.options.body
2302
+ }
2303
+
2304
+ get query () {
2305
+ const originalQuery = (this.originalUrl.split('?')[1] || '').split('#')[0];
2306
+ const params = new URLSearchParams(originalQuery);
2307
+
2308
+ let requestQuery = this.options.query;
2309
+ if (requestQuery instanceof window.FormData) {
2310
+ requestQuery = stringEntriesFromFormData(requestQuery);
2311
+ } else if (requestQuery instanceof window.URLSearchParams) {
2312
+ requestQuery = requestQuery.entries();
2313
+ } else {
2314
+ requestQuery = Object.entries(requestQuery || {});
2315
+ }
2316
+
2317
+ mergeEntries(params, requestQuery);
2318
+
2319
+ const query = params.toString();
2320
+ return (query.length > 0 ? `?${query}` : '')
2321
+ }
2322
+
2323
+ get url () {
2324
+ return (this.originalUrl.split('?')[0]).split('#')[0] + this.query
2325
+ }
2326
+
2327
+ get responseKind () {
2328
+ return this.options.responseKind || 'html'
2329
+ }
2330
+
2331
+ get signal () {
2332
+ return this.options.signal
2333
+ }
2334
+
2335
+ get redirect () {
2336
+ return this.options.redirect || 'follow'
2337
+ }
2338
+
2339
+ get credentials () {
2340
+ return this.options.credentials || 'same-origin'
2341
+ }
2342
+
2343
+ get additionalHeaders () {
2344
+ return this.options.headers || {}
2345
+ }
2346
+
2347
+ get formattedBody () {
2348
+ const bodyIsAString = Object.prototype.toString.call(this.body) === '[object String]';
2349
+ const contentTypeIsJson = this.headers['Content-Type'] === 'application/json';
2350
+
2351
+ if (contentTypeIsJson && !bodyIsAString) {
2352
+ return JSON.stringify(this.body)
2353
+ }
2354
+
2355
+ return this.body
2356
+ }
2357
+ }
2358
+
2359
+ async function post (url, options) {
2360
+ const request = new FetchRequest('post', url, options);
2361
+ return request.perform()
2362
+ }
2363
+
2364
+ function insertText(textarea, text) {
2365
+ var _a, _b, _c;
2366
+ const before = textarea.value.slice(0, (_a = textarea.selectionStart) !== null && _a !== undefined ? _a : undefined);
2367
+ const after = textarea.value.slice((_b = textarea.selectionEnd) !== null && _b !== undefined ? _b : undefined);
2368
+ let canInsertText = true;
2369
+ textarea.contentEditable = 'true';
2370
+ try {
2371
+ canInsertText = document.execCommand('insertText', false, text);
2372
+ }
2373
+ catch (error) {
2374
+ canInsertText = false;
2375
+ }
2376
+ textarea.contentEditable = 'false';
2377
+ if (canInsertText && !textarea.value.slice(0, (_c = textarea.selectionStart) !== null && _c !== undefined ? _c : undefined).endsWith(text)) {
2378
+ canInsertText = false;
2379
+ }
2380
+ if (!canInsertText) {
2381
+ try {
2382
+ document.execCommand('ms-beginUndoUnit');
2383
+ }
2384
+ catch (e) {
2385
+ }
2386
+ textarea.value = before + text + after;
2387
+ try {
2388
+ document.execCommand('ms-endUndoUnit');
2389
+ }
2390
+ catch (e) {
2391
+ }
2392
+ textarea.dispatchEvent(new CustomEvent('change', { bubbles: true, cancelable: true }));
2393
+ }
2394
+ }
2395
+
2396
+ const skipFormattingMap = new WeakMap();
2397
+ function setSkipFormattingFlag(event) {
2398
+ const { currentTarget: el } = event;
2399
+ const isSkipFormattingKeys = event.code === 'KeyV' && (event.ctrlKey || event.metaKey) && event.shiftKey;
2400
+ if (isSkipFormattingKeys || (isSkipFormattingKeys && event.altKey)) {
2401
+ skipFormattingMap.set(el, true);
2402
+ }
2403
+ }
2404
+ function unsetSkipFormattedFlag(event) {
2405
+ const { currentTarget: el } = event;
2406
+ skipFormattingMap.delete(el);
2407
+ }
2408
+ function shouldSkipFormatting(el) {
2409
+ var _a;
2410
+ const shouldSkipFormattingState = (_a = skipFormattingMap.get(el)) !== null && _a !== undefined ? _a : false;
2411
+ return shouldSkipFormattingState;
2412
+ }
2413
+ function installAround(el, installCallbacks, optionConfig) {
2414
+ el.addEventListener('keydown', setSkipFormattingFlag);
2415
+ for (const installCallback of installCallbacks) {
2416
+ installCallback(el, optionConfig);
2417
+ }
2418
+ el.addEventListener('paste', unsetSkipFormattedFlag);
2419
+ }
2420
+ function uninstall$5(el) {
2421
+ el.removeEventListener('keydown', setSkipFormattingFlag);
2422
+ el.removeEventListener('paste', unsetSkipFormattedFlag);
2423
+ }
2424
+
2425
+ function install$4(el) {
2426
+ el.addEventListener('paste', onPaste$4);
2427
+ }
2428
+ function uninstall$4(el) {
2429
+ el.removeEventListener('paste', onPaste$4);
2430
+ }
2431
+ function onPaste$4(event) {
2432
+ const transfer = event.clipboardData;
2433
+ const { currentTarget: el } = event;
2434
+ if (shouldSkipFormatting(el))
2435
+ return;
2436
+ if (!transfer || !hasHTML(transfer))
2437
+ return;
2438
+ const field = event.currentTarget;
2439
+ if (!(field instanceof HTMLTextAreaElement))
2440
+ return;
2441
+ if (isWithinUserMention(field)) {
2442
+ return;
2443
+ }
2444
+ let plaintext = transfer.getData('text/plain');
2445
+ const textHTML = transfer.getData('text/html');
2446
+ const textHTMLClean = textHTML.replace(/\u00A0/g, ' ').replace(/\uC2A0/g, ' ');
2447
+ if (!textHTML)
2448
+ return;
2449
+ plaintext = plaintext.trim();
2450
+ if (!plaintext)
2451
+ return;
2452
+ const parser = new DOMParser();
2453
+ const doc = parser.parseFromString(textHTMLClean, 'text/html');
2454
+ const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_ALL, node => node.parentNode && isLink(node.parentNode) ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT);
2455
+ const markdown = convertToMarkdown(plaintext, walker);
2456
+ if (markdown === plaintext)
2457
+ return;
2458
+ event.stopPropagation();
2459
+ event.preventDefault();
2460
+ insertText(field, markdown);
2461
+ }
2462
+ function convertToMarkdown(plaintext, walker) {
2463
+ let currentNode = walker.firstChild();
2464
+ let markdown = plaintext;
2465
+ let markdownIgnoreBeforeIndex = 0;
2466
+ let index = 0;
2467
+ const NODE_LIMIT = 10000;
2468
+ while (currentNode && index < NODE_LIMIT) {
2469
+ index++;
2470
+ const text = isLink(currentNode)
2471
+ ? (currentNode.textContent || '').replace(/[\t\n\r ]+/g, ' ')
2472
+ : (currentNode === null || currentNode === undefined ? undefined : currentNode.wholeText) || '';
2473
+ if (isEmptyString(text)) {
2474
+ currentNode = walker.nextNode();
2475
+ continue;
2476
+ }
2477
+ if (!isLink(currentNode)) {
2478
+ markdownIgnoreBeforeIndex += text.replace(/[\t\n\r ]+/g, ' ').trimStart().length;
2479
+ currentNode = walker.nextNode();
2480
+ continue;
2481
+ }
2482
+ const markdownFoundIndex = markdown.indexOf(text, markdownIgnoreBeforeIndex);
2483
+ if (markdownFoundIndex >= 0) {
2484
+ const markdownLink = linkify$2(currentNode, text);
2485
+ markdown = markdown.slice(0, markdownFoundIndex) + markdownLink + markdown.slice(markdownFoundIndex + text.length);
2486
+ markdownIgnoreBeforeIndex = markdownFoundIndex + markdownLink.length;
2487
+ }
2488
+ currentNode = walker.nextNode();
2489
+ }
2490
+ return index === NODE_LIMIT ? plaintext : markdown;
2491
+ }
2492
+ function isWithinUserMention(textarea) {
2493
+ const selectionStart = textarea.selectionStart || 0;
2494
+ if (selectionStart === 0) {
2495
+ return false;
2496
+ }
2497
+ const previousChar = textarea.value.substring(selectionStart - 1, selectionStart);
2498
+ return previousChar === '@';
2499
+ }
2500
+ function isEmptyString(text) {
2501
+ return !text || (text === null || text === undefined ? undefined : text.trim().length) === 0;
2502
+ }
2503
+ function isLink(node) {
2504
+ var _a;
2505
+ return ((_a = node.tagName) === null || _a === undefined ? undefined : _a.toLowerCase()) === 'a' && node.hasAttribute('href');
2506
+ }
2507
+ function hasHTML(transfer) {
2508
+ return transfer.types.includes('text/html');
2509
+ }
2510
+ function linkify$2(element, label) {
2511
+ const url = element.href || '';
2512
+ let markdown = '';
2513
+ if (isUserMention(element) || isTeamMention(element)) {
2514
+ markdown = label;
2515
+ }
2516
+ else if (isSpecialLink(element) || areEqualLinks(url, label)) {
2517
+ markdown = url;
2518
+ }
2519
+ else {
2520
+ markdown = `[${label}](${url})`;
2521
+ }
2522
+ return markdown;
2523
+ }
2524
+ function isSpecialLink(link) {
2525
+ return (link.className.indexOf('commit-link') >= 0 ||
2526
+ (!!link.getAttribute('data-hovercard-type') && link.getAttribute('data-hovercard-type') !== 'user'));
2527
+ }
2528
+ function areEqualLinks(link1, link2) {
2529
+ link1 = link1.slice(-1) === '/' ? link1.slice(0, -1) : link1;
2530
+ link2 = link2.slice(-1) === '/' ? link2.slice(0, -1) : link2;
2531
+ return link1.toLowerCase() === link2.toLowerCase();
2532
+ }
2533
+ function isUserMention(link) {
2534
+ var _a;
2535
+ return ((_a = link.textContent) === null || _a === undefined ? undefined : _a.slice(0, 1)) === '@' && link.getAttribute('data-hovercard-type') === 'user';
2536
+ }
2537
+ function isTeamMention(link) {
2538
+ var _a;
2539
+ return ((_a = link.textContent) === null || _a === undefined ? undefined : _a.slice(0, 1)) === '@' && link.getAttribute('data-hovercard-type') === 'team';
2540
+ }
2541
+
2542
+ function install$3(el) {
2543
+ el.addEventListener('dragover', onDragover$1);
2544
+ el.addEventListener('drop', onDrop$1);
2545
+ el.addEventListener('paste', onPaste$3);
2546
+ }
2547
+ function uninstall$3(el) {
2548
+ el.removeEventListener('dragover', onDragover$1);
2549
+ el.removeEventListener('drop', onDrop$1);
2550
+ el.removeEventListener('paste', onPaste$3);
2551
+ }
2552
+ function onDrop$1(event) {
2553
+ const transfer = event.dataTransfer;
2554
+ if (!transfer)
2555
+ return;
2556
+ if (hasFile$1(transfer))
2557
+ return;
2558
+ if (!hasLink(transfer))
2559
+ return;
2560
+ const links = extractLinks(transfer);
2561
+ if (!links.some(isImageLink))
2562
+ return;
2563
+ event.stopPropagation();
2564
+ event.preventDefault();
2565
+ const field = event.currentTarget;
2566
+ if (!(field instanceof HTMLTextAreaElement))
2567
+ return;
2568
+ insertText(field, links.map(linkify$1).join(''));
2569
+ }
2570
+ function onDragover$1(event) {
2571
+ const transfer = event.dataTransfer;
2572
+ if (transfer)
2573
+ transfer.dropEffect = 'link';
2574
+ }
2575
+ function onPaste$3(event) {
2576
+ const { currentTarget: el } = event;
2577
+ if (shouldSkipFormatting(el))
2578
+ return;
2579
+ const transfer = event.clipboardData;
2580
+ if (!transfer || !hasLink(transfer))
2581
+ return;
2582
+ const links = extractLinks(transfer);
2583
+ if (!links.some(isImageLink))
2584
+ return;
2585
+ event.stopPropagation();
2586
+ event.preventDefault();
2587
+ const field = event.currentTarget;
2588
+ if (!(field instanceof HTMLTextAreaElement))
2589
+ return;
2590
+ insertText(field, links.map(linkify$1).join(''));
2591
+ }
2592
+ function linkify$1(link) {
2593
+ return isImageLink(link) ? `\n![](${link})\n` : link;
2594
+ }
2595
+ function hasFile$1(transfer) {
2596
+ return Array.from(transfer.types).indexOf('Files') >= 0;
2597
+ }
2598
+ function hasLink(transfer) {
2599
+ return Array.from(transfer.types).indexOf('text/uri-list') >= 0;
2600
+ }
2601
+ function extractLinks(transfer) {
2602
+ return (transfer.getData('text/uri-list') || '').split('\r\n');
2603
+ }
2604
+ const IMAGE_RE = /\.(gif|png|jpe?g)$/i;
2605
+ function isImageLink(url) {
2606
+ return IMAGE_RE.test(url);
2607
+ }
2608
+
2609
+ const pasteLinkAsPlainTextOverSelectedTextMap = new WeakMap();
2610
+ function install$2(el, optionConfig) {
2611
+ var _a;
2612
+ pasteLinkAsPlainTextOverSelectedTextMap.set(el, ((_a = optionConfig === null || optionConfig === undefined ? undefined : optionConfig.defaultPlainTextPaste) === null || _a === undefined ? undefined : _a.urlLinks) === true);
2613
+ el.addEventListener('paste', onPaste$2);
2614
+ }
2615
+ function uninstall$2(el) {
2616
+ el.removeEventListener('paste', onPaste$2);
2617
+ }
2618
+ function onPaste$2(event) {
2619
+ var _a;
2620
+ const { currentTarget: el } = event;
2621
+ const element = el;
2622
+ const shouldPasteAsPlainText = (_a = pasteLinkAsPlainTextOverSelectedTextMap.get(element)) !== null && _a !== undefined ? _a : false;
2623
+ const shouldSkipDefaultBehavior = shouldSkipFormatting(element);
2624
+ if ((!shouldPasteAsPlainText && shouldSkipDefaultBehavior) ||
2625
+ (shouldPasteAsPlainText && !shouldSkipDefaultBehavior)) {
2626
+ return;
2627
+ }
2628
+ const transfer = event.clipboardData;
2629
+ if (!transfer || !hasPlainText(transfer))
2630
+ return;
2631
+ const field = event.currentTarget;
2632
+ if (!(field instanceof HTMLTextAreaElement))
2633
+ return;
2634
+ const text = transfer.getData('text/plain');
2635
+ if (!text)
2636
+ return;
2637
+ if (!isURL(text))
2638
+ return;
2639
+ if (isWithinLink(field))
2640
+ return;
2641
+ const selectedText = field.value.substring(field.selectionStart, field.selectionEnd);
2642
+ if (!selectedText.length)
2643
+ return;
2644
+ if (isURL(selectedText.trim()))
2645
+ return;
2646
+ event.stopPropagation();
2647
+ event.preventDefault();
2648
+ insertText(field, linkify(selectedText, text.trim()));
2649
+ }
2650
+ function hasPlainText(transfer) {
2651
+ return Array.from(transfer.types).includes('text/plain');
2652
+ }
2653
+ function isWithinLink(textarea) {
2654
+ const selectionStart = textarea.selectionStart || 0;
2655
+ if (selectionStart > 1) {
2656
+ const previousChars = textarea.value.substring(selectionStart - 2, selectionStart);
2657
+ return previousChars === '](';
2658
+ }
2659
+ else {
2660
+ return false;
2661
+ }
2662
+ }
2663
+ function linkify(selectedText, text) {
2664
+ return `[${selectedText}](${text})`;
2665
+ }
2666
+ function isURL(url) {
2667
+ try {
2668
+ const parsedURL = new URL(url);
2669
+ return removeTrailingSlash(parsedURL.href).trim() === removeTrailingSlash(url).trim();
2670
+ }
2671
+ catch (_a) {
2672
+ return false;
2673
+ }
2674
+ }
2675
+ function removeTrailingSlash(url) {
2676
+ return url.endsWith('/') ? url.slice(0, url.length - 1) : url;
2677
+ }
2678
+
2679
+ function install$1(el) {
2680
+ el.addEventListener('dragover', onDragover);
2681
+ el.addEventListener('drop', onDrop);
2682
+ el.addEventListener('paste', onPaste$1);
2683
+ }
2684
+ function uninstall$1(el) {
2685
+ el.removeEventListener('dragover', onDragover);
2686
+ el.removeEventListener('drop', onDrop);
2687
+ el.removeEventListener('paste', onPaste$1);
2688
+ }
2689
+ function onDrop(event) {
2690
+ const transfer = event.dataTransfer;
2691
+ if (!transfer)
2692
+ return;
2693
+ if (hasFile(transfer))
2694
+ return;
2695
+ const textToPaste = generateText(transfer);
2696
+ if (!textToPaste)
2697
+ return;
2698
+ event.stopPropagation();
2699
+ event.preventDefault();
2700
+ const field = event.currentTarget;
2701
+ if (field instanceof HTMLTextAreaElement) {
2702
+ insertText(field, textToPaste);
2703
+ }
2704
+ }
2705
+ function onDragover(event) {
2706
+ const transfer = event.dataTransfer;
2707
+ if (transfer)
2708
+ transfer.dropEffect = 'copy';
2709
+ }
2710
+ function onPaste$1(event) {
2711
+ const { currentTarget: el } = event;
2712
+ if (shouldSkipFormatting(el))
2713
+ return;
2714
+ if (!event.clipboardData)
2715
+ return;
2716
+ const textToPaste = generateText(event.clipboardData);
2717
+ if (!textToPaste)
2718
+ return;
2719
+ event.stopPropagation();
2720
+ event.preventDefault();
2721
+ const field = event.currentTarget;
2722
+ if (field instanceof HTMLTextAreaElement) {
2723
+ insertText(field, textToPaste);
2724
+ }
2725
+ }
2726
+ function hasFile(transfer) {
2727
+ return Array.from(transfer.types).indexOf('Files') >= 0;
2728
+ }
2729
+ function columnText(column) {
2730
+ const noBreakSpace = '\u00A0';
2731
+ const text = (column.textContent || '').trim().replace(/\|/g, '\\|').replace(/\n/g, ' ');
2732
+ return text || noBreakSpace;
2733
+ }
2734
+ function tableHeaders(row) {
2735
+ return Array.from(row.querySelectorAll('td, th')).map(columnText);
2736
+ }
2737
+ function tableMarkdown(node) {
2738
+ const rows = Array.from(node.querySelectorAll('tr'));
2739
+ const firstRow = rows.shift();
2740
+ if (!firstRow)
2741
+ return '';
2742
+ const headers = tableHeaders(firstRow);
2743
+ const spacers = headers.map(() => '--');
2744
+ const header = `${headers.join(' | ')}\n${spacers.join(' | ')}\n`;
2745
+ const body = rows
2746
+ .map(row => {
2747
+ return Array.from(row.querySelectorAll('td')).map(columnText).join(' | ');
2748
+ })
2749
+ .join('\n');
2750
+ return `\n${header}${body}\n\n`;
2751
+ }
2752
+ function generateText(transfer) {
2753
+ if (Array.from(transfer.types).indexOf('text/html') === -1)
2754
+ return;
2755
+ const html = transfer.getData('text/html');
2756
+ if (!/<table/i.test(html))
2757
+ return;
2758
+ const start = html.substring(0, html.indexOf('<table'));
2759
+ const tableCloseIndex = html.lastIndexOf('</table>');
2760
+ if (!start || !tableCloseIndex)
2761
+ return;
2762
+ const end = html.substring(tableCloseIndex + 8);
2763
+ const parser = new DOMParser();
2764
+ const parsedDocument = parser.parseFromString(html, 'text/html');
2765
+ let table = parsedDocument.querySelector('table');
2766
+ table = !table || table.closest('[data-paste-markdown-skip]') ? null : table;
2767
+ if (!table)
2768
+ return;
2769
+ const formattedTable = tableMarkdown(table);
2770
+ if (!formattedTable)
2771
+ return;
2772
+ return [start, formattedTable, end].join('').replace(/<meta.*?>/, '');
2773
+ }
2774
+
2775
+ function install(el) {
2776
+ el.addEventListener('paste', onPaste);
2777
+ }
2778
+ function uninstall(el) {
2779
+ el.removeEventListener('paste', onPaste);
2780
+ }
2781
+ function onPaste(event) {
2782
+ const { currentTarget: el } = event;
2783
+ if (shouldSkipFormatting(el))
2784
+ return;
2785
+ const transfer = event.clipboardData;
2786
+ if (!transfer || !hasMarkdown(transfer))
2787
+ return;
2788
+ const field = event.currentTarget;
2789
+ if (!(field instanceof HTMLTextAreaElement))
2790
+ return;
2791
+ const text = transfer.getData('text/x-gfm');
2792
+ if (!text)
2793
+ return;
2794
+ event.stopPropagation();
2795
+ event.preventDefault();
2796
+ insertText(field, text);
2797
+ }
2798
+ function hasMarkdown(transfer) {
2799
+ return Array.from(transfer.types).indexOf('text/x-gfm') >= 0;
2800
+ }
2801
+
2802
+ function subscribe(el, optionConfig) {
2803
+ installAround(el, [install$1, install$3, install$2, install, install$4], optionConfig);
2804
+ return {
2805
+ unsubscribe: () => {
2806
+ uninstall$5(el);
2807
+ uninstall$1(el);
2808
+ uninstall$4(el);
2809
+ uninstall$3(el);
2810
+ uninstall$2(el);
2811
+ uninstall(el);
2812
+ },
2813
+ };
2814
+ }
2815
+
2816
+ /* eslint-disable camelcase */
2817
+
2818
+ // upload code from Jeremy Smith's blog post
2819
+ // https://hybrd.co/posts/github-issue-style-file-uploader-using-stimulus-and-active-storage
2820
+
2821
+ // Connects to data-controller="marksmith"
2822
+ class marksmith_controller extends Controller {
2823
+ static values = {
2824
+ attachUrl: String,
2825
+ previewUrl: String,
2826
+ extraPreviewParams: { type: Object, default: {} },
2827
+ fieldId: String,
2828
+ }
2829
+
2830
+ static targets = ['fieldContainer', 'fieldElement', 'previewElement', 'writeTabButton', 'previewTabButton', 'toolbar']
2831
+
2832
+ connect() {
2833
+ subscribe(this.fieldContainerTarget, { defaultPlainTextPaste: { urlLinks: true } });
2834
+ }
2835
+
2836
+ switchToWrite(event) {
2837
+ event.preventDefault();
2838
+
2839
+ // toggle buttons
2840
+ this.writeTabButtonTarget.classList.add('ms:hidden');
2841
+ this.previewTabButtonTarget.classList.remove('ms:hidden');
2842
+
2843
+ // toggle write/preview buttons
2844
+ this.fieldContainerTarget.classList.remove('ms:hidden');
2845
+ this.previewElementTarget.classList.add('ms:hidden');
2846
+
2847
+ // toggle the toolbar back
2848
+ this.toolbarTarget.classList.remove('ms:hidden');
2849
+ }
2850
+
2851
+ switchToPreview(event) {
2852
+ event.preventDefault();
2853
+
2854
+ post(this.previewUrlValue, {
2855
+ body: {
2856
+ body: this.fieldElementTarget.value,
2857
+ element_id: this.previewElementTarget.id,
2858
+ extra_params: this.extraPreviewParamsValue,
2859
+ },
2860
+ responseKind: 'turbo-stream',
2861
+ });
2862
+
2863
+ // set the min height to the field element height
2864
+ this.previewElementTarget.style.minHeight = `${this.fieldElementTarget.offsetHeight}px`;
2865
+
2866
+ // toggle buttons
2867
+ this.writeTabButtonTarget.classList.remove('ms:hidden');
2868
+ this.previewTabButtonTarget.classList.add('ms:hidden');
2869
+
2870
+ // toggle elements
2871
+ this.fieldContainerTarget.classList.add('ms:hidden');
2872
+ this.previewElementTarget.classList.remove('ms:hidden');
2873
+
2874
+ // toggle the toolbar
2875
+ this.toolbarTarget.classList.add('ms:hidden');
2876
+ }
2877
+
2878
+ dropUpload(event) {
2879
+ event.preventDefault();
2880
+ this.uploadFiles(event.dataTransfer.files);
2881
+ }
2882
+
2883
+ pasteUpload(event) {
2884
+ if (!event.clipboardData.files.length) return
2885
+
2886
+ event.preventDefault();
2887
+ this.uploadFiles(event.clipboardData.files);
2888
+ }
2889
+
2890
+ buttonUpload(event) {
2891
+ event.preventDefault();
2892
+ // Create a hidden file input and trigger it
2893
+ const fileInput = document.createElement('input');
2894
+ fileInput.type = 'file';
2895
+ fileInput.multiple = true;
2896
+ fileInput.accept = 'image/*,.pdf,.doc,.docx,.txt';
2897
+
2898
+ fileInput.addEventListener('change', (e) => {
2899
+ this.uploadFiles(e.target.files);
2900
+ });
2901
+
2902
+ fileInput.click();
2903
+ }
2904
+
2905
+ uploadFiles(files) {
2906
+ Array.from(files).forEach((file) => this.uploadFile(file));
2907
+ }
2908
+
2909
+ uploadFile(file) {
2910
+ const upload = new DirectUpload(file, this.attachUrlValue);
2911
+
2912
+ upload.create((error, blob) => {
2913
+ if (error) {
2914
+ console.log('Error', error);
2915
+ } else {
2916
+ const text = this.markdownLink(blob);
2917
+ const start = this.fieldElementTarget.selectionStart;
2918
+ const end = this.fieldElementTarget.selectionEnd;
2919
+ this.fieldElementTarget.setRangeText(text, start, end);
2920
+ }
2921
+ });
2922
+ }
2923
+
2924
+ markdownLink(blob) {
2925
+ const { filename } = blob;
2926
+ const url = `/rails/active_storage/blobs/${blob.signed_id}/${filename}`;
2927
+ const prefix = (this.isImage(blob.content_type) ? '!' : '');
2928
+
2929
+ return `${prefix}[${filename}](${url})\n`
2930
+ }
2931
+
2932
+ isImage(contentType) {
2933
+ return ['image/jpeg', 'image/gif', 'image/png'].includes(contentType)
2934
+ }
2935
+ }
2936
+
2937
+ return marksmith_controller;
2938
+
2939
+ })();