markdown-actions 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,8 +15,58 @@ var __spreadValues = (a, b) => {
15
15
  return a;
16
16
  };
17
17
 
18
- // src/core/style-args.js
19
- function getDefaultStyleArgs() {
18
+ // src/core/formats.js
19
+ var FORMATS = {
20
+ bold: {
21
+ prefix: "**",
22
+ suffix: "**",
23
+ trimFirst: true
24
+ },
25
+ italic: {
26
+ prefix: "_",
27
+ suffix: "_",
28
+ trimFirst: true
29
+ },
30
+ code: {
31
+ prefix: "`",
32
+ suffix: "`",
33
+ blockPrefix: "```",
34
+ blockSuffix: "```"
35
+ },
36
+ link: {
37
+ prefix: "[",
38
+ suffix: "](url)",
39
+ replaceNext: "url",
40
+ scanFor: "https?://"
41
+ },
42
+ bulletList: {
43
+ prefix: "- ",
44
+ multiline: true,
45
+ unorderedList: true
46
+ },
47
+ numberedList: {
48
+ prefix: "1. ",
49
+ multiline: true,
50
+ orderedList: true
51
+ },
52
+ quote: {
53
+ prefix: "> ",
54
+ multiline: true,
55
+ surroundWithNewlines: true
56
+ },
57
+ taskList: {
58
+ prefix: "- [ ] ",
59
+ multiline: true,
60
+ surroundWithNewlines: true
61
+ },
62
+ header1: { prefix: "# " },
63
+ header2: { prefix: "## " },
64
+ header3: { prefix: "### " },
65
+ header4: { prefix: "#### " },
66
+ header5: { prefix: "##### " },
67
+ header6: { prefix: "###### " }
68
+ };
69
+ function getDefaultStyle() {
20
70
  return {
21
71
  prefix: "",
22
72
  suffix: "",
@@ -32,17 +82,97 @@ function getDefaultStyleArgs() {
32
82
  trimFirst: false
33
83
  };
34
84
  }
35
- function mergeStyleWithDefaults(style) {
36
- return __spreadValues(__spreadValues({}, getDefaultStyleArgs()), style);
85
+ function mergeWithDefaults(format) {
86
+ return __spreadValues(__spreadValues({}, getDefaultStyle()), format);
87
+ }
88
+
89
+ // src/core/insertion.js
90
+ var canInsertText = null;
91
+ function insertText(textarea, { text, selectionStart, selectionEnd }) {
92
+ console.group("\u{1F527} insertText");
93
+ console.log("Current selection:", `${textarea.selectionStart}-${textarea.selectionEnd}`);
94
+ console.log("Text to insert:", JSON.stringify(text));
95
+ console.log("New selection to set:", selectionStart, "-", selectionEnd);
96
+ textarea.focus();
97
+ const originalSelectionStart = textarea.selectionStart;
98
+ const originalSelectionEnd = textarea.selectionEnd;
99
+ const before = textarea.value.slice(0, originalSelectionStart);
100
+ const after = textarea.value.slice(originalSelectionEnd);
101
+ console.log("Before text (last 20):", JSON.stringify(before.slice(-20)));
102
+ console.log("After text (first 20):", JSON.stringify(after.slice(0, 20)));
103
+ console.log("Selected text being replaced:", JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));
104
+ const originalValue = textarea.value;
105
+ const hasSelection = originalSelectionStart !== originalSelectionEnd;
106
+ if (!hasSelection && (canInsertText === null || canInsertText === true)) {
107
+ textarea.contentEditable = "true";
108
+ try {
109
+ canInsertText = document.execCommand("insertText", false, text);
110
+ } catch (error) {
111
+ canInsertText = false;
112
+ }
113
+ textarea.contentEditable = "false";
114
+ } else if (hasSelection) {
115
+ console.log("Has selection, skipping execCommand and using manual mode");
116
+ canInsertText = false;
117
+ }
118
+ console.log("canInsertText before:", canInsertText);
119
+ console.log("execCommand result:", canInsertText);
120
+ if (canInsertText) {
121
+ const expectedValue = before + text + after;
122
+ const actualValue = textarea.value;
123
+ console.log("Expected length:", expectedValue.length);
124
+ console.log("Actual length:", actualValue.length);
125
+ if (actualValue !== expectedValue) {
126
+ console.log("execCommand changed the value but not as expected");
127
+ console.log("Expected:", JSON.stringify(expectedValue.slice(0, 100)));
128
+ console.log("Actual:", JSON.stringify(actualValue.slice(0, 100)));
129
+ }
130
+ }
131
+ if (!canInsertText) {
132
+ console.log("Using manual insertion");
133
+ if (textarea.value === originalValue) {
134
+ console.log("Value unchanged, doing manual replacement");
135
+ try {
136
+ document.execCommand("ms-beginUndoUnit");
137
+ } catch (e) {
138
+ }
139
+ textarea.value = before + text + after;
140
+ try {
141
+ document.execCommand("ms-endUndoUnit");
142
+ } catch (e) {
143
+ }
144
+ textarea.dispatchEvent(new CustomEvent("input", { bubbles: true, cancelable: true }));
145
+ } else {
146
+ console.log("Value was changed by execCommand, skipping manual insertion");
147
+ }
148
+ }
149
+ console.log("Setting selection range:", selectionStart, selectionEnd);
150
+ if (selectionStart != null && selectionEnd != null) {
151
+ textarea.setSelectionRange(selectionStart, selectionEnd);
152
+ } else {
153
+ textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd);
154
+ }
155
+ console.log("Final value length:", textarea.value.length);
156
+ console.groupEnd();
157
+ }
158
+ function setUndoMethod(method) {
159
+ switch (method) {
160
+ case "native":
161
+ canInsertText = true;
162
+ break;
163
+ case "manual":
164
+ canInsertText = false;
165
+ break;
166
+ case "auto":
167
+ canInsertText = null;
168
+ break;
169
+ }
37
170
  }
38
171
 
39
- // src/core/selection-new.js
172
+ // src/core/selection.js
40
173
  function isMultipleLines(string) {
41
174
  return string.trim().split("\n").length > 1;
42
175
  }
43
- function repeat(string, n) {
44
- return Array(n + 1).join(string);
45
- }
46
176
  function wordSelectionStart(text, i) {
47
177
  let index = i;
48
178
  while (text[index] && text[index - 1] != null && !text[index - 1].match(/\s/)) {
@@ -67,7 +197,11 @@ function expandSelectionToLine(textarea) {
67
197
  textarea.selectionStart = counter;
68
198
  }
69
199
  if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {
70
- textarea.selectionEnd = counter + lineLength - 1;
200
+ if (index === lines.length - 1) {
201
+ textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length);
202
+ } else {
203
+ textarea.selectionEnd = counter + lineLength - 1;
204
+ }
71
205
  }
72
206
  counter += lineLength;
73
207
  }
@@ -95,19 +229,13 @@ function newlinesToSurroundSelectedText(textarea) {
95
229
  const breaksAfter = afterSelection.match(/^\n*/);
96
230
  const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0;
97
231
  const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0;
98
- let newlinesToAppend;
99
- let newlinesToPrepend;
232
+ let newlinesToAppend = "";
233
+ let newlinesToPrepend = "";
100
234
  if (beforeSelection.match(/\S/) && newlinesBeforeSelection < 2) {
101
- newlinesToAppend = repeat("\n", 2 - newlinesBeforeSelection);
235
+ newlinesToAppend = "\n".repeat(2 - newlinesBeforeSelection);
102
236
  }
103
237
  if (afterSelection.match(/\S/) && newlinesAfterSelection < 2) {
104
- newlinesToPrepend = repeat("\n", 2 - newlinesAfterSelection);
105
- }
106
- if (newlinesToAppend == null) {
107
- newlinesToAppend = "";
108
- }
109
- if (newlinesToPrepend == null) {
110
- newlinesToPrepend = "";
238
+ newlinesToPrepend = "\n".repeat(2 - newlinesAfterSelection);
111
239
  }
112
240
  return { newlinesToAppend, newlinesToPrepend };
113
241
  }
@@ -120,64 +248,52 @@ function preserveSelection(textarea, callback) {
120
248
  textarea.selectionEnd = end;
121
249
  textarea.scrollTop = scrollTop;
122
250
  }
123
-
124
- // src/core/insertion-new.js
125
- var canInsertText = null;
126
- function insertText(textarea, { text, selectionStart, selectionEnd }) {
127
- const originalSelectionStart = textarea.selectionStart;
128
- const before = textarea.value.slice(0, originalSelectionStart);
129
- const after = textarea.value.slice(textarea.selectionEnd);
130
- if (canInsertText === null || canInsertText === true) {
131
- textarea.contentEditable = "true";
132
- try {
133
- canInsertText = document.execCommand("insertText", false, text);
134
- } catch (error) {
135
- canInsertText = false;
136
- }
137
- textarea.contentEditable = "false";
138
- }
139
- if (canInsertText && !textarea.value.slice(0, textarea.selectionStart).endsWith(text)) {
140
- canInsertText = false;
141
- }
142
- if (!canInsertText) {
143
- try {
144
- document.execCommand("ms-beginUndoUnit");
145
- } catch (e) {
251
+ function applyLineOperation(textarea, operation, options = {}) {
252
+ const originalStart = textarea.selectionStart;
253
+ const originalEnd = textarea.selectionEnd;
254
+ const noInitialSelection = originalStart === originalEnd;
255
+ if (noInitialSelection) {
256
+ const value = textarea.value;
257
+ const start = originalStart;
258
+ let lineStart = start;
259
+ let lineEnd = start;
260
+ while (lineStart > 0 && value[lineStart - 1] !== "\n") {
261
+ lineStart--;
146
262
  }
147
- textarea.value = before + text + after;
148
- try {
149
- document.execCommand("ms-endUndoUnit");
150
- } catch (e) {
263
+ while (lineEnd < value.length && value[lineEnd] !== "\n") {
264
+ lineEnd++;
151
265
  }
152
- textarea.dispatchEvent(new CustomEvent("input", { bubbles: true, cancelable: true }));
153
- }
154
- if (selectionStart != null && selectionEnd != null) {
155
- textarea.setSelectionRange(selectionStart, selectionEnd);
266
+ textarea.selectionStart = lineStart;
267
+ textarea.selectionEnd = lineEnd;
156
268
  } else {
157
- textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd);
269
+ expandSelectionToLine(textarea);
158
270
  }
159
- }
160
- function setUndoMethod(method) {
161
- if (method === "native") {
162
- canInsertText = true;
163
- } else if (method === "manual") {
164
- canInsertText = false;
165
- } else {
166
- canInsertText = null;
271
+ const result = operation(textarea);
272
+ if (noInitialSelection && options.prefix) {
273
+ const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
274
+ const isRemoving = selectedText.startsWith(options.prefix);
275
+ if (isRemoving) {
276
+ result.selectionStart = Math.max(originalStart - options.prefix.length, textarea.selectionStart);
277
+ result.selectionEnd = result.selectionStart;
278
+ } else {
279
+ result.selectionStart = originalStart + options.prefix.length;
280
+ result.selectionEnd = result.selectionStart;
281
+ }
167
282
  }
283
+ return result;
168
284
  }
169
285
 
170
- // src/operations/block-new.js
171
- function blockStyle(textarea, arg) {
286
+ // src/operations/block.js
287
+ function blockStyle(textarea, style) {
172
288
  let newlinesToAppend;
173
289
  let newlinesToPrepend;
174
- const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines } = arg;
290
+ const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style;
175
291
  const originalSelectionStart = textarea.selectionStart;
176
292
  const originalSelectionEnd = textarea.selectionEnd;
177
293
  let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
178
- let prefixToUse = isMultipleLines(selectedText) && blockPrefix.length > 0 ? `${blockPrefix}
294
+ let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}
179
295
  ` : prefix;
180
- let suffixToUse = isMultipleLines(selectedText) && blockSuffix.length > 0 ? `
296
+ let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `
181
297
  ${blockSuffix}` : suffix;
182
298
  if (prefixSpace) {
183
299
  const beforeSelection = textarea.value[textarea.selectionStart - 1];
@@ -185,10 +301,10 @@ ${blockSuffix}` : suffix;
185
301
  prefixToUse = ` ${prefixToUse}`;
186
302
  }
187
303
  }
188
- selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, arg.multiline);
304
+ selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline);
189
305
  let selectionStart = textarea.selectionStart;
190
306
  let selectionEnd = textarea.selectionEnd;
191
- const hasReplaceNext = replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0;
307
+ const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0;
192
308
  if (surroundWithNewlines) {
193
309
  const ref = newlinesToSurroundSelectedText(textarea);
194
310
  newlinesToAppend = ref.newlinesToAppend;
@@ -212,7 +328,7 @@ ${blockSuffix}` : suffix;
212
328
  selectionStart = originalSelectionStart + prefixToUse.length;
213
329
  selectionEnd = originalSelectionEnd + prefixToUse.length;
214
330
  const whitespaceEdges = selectedText.match(/^\s*|\s*$/g);
215
- if (arg.trimFirst && whitespaceEdges) {
331
+ if (trimFirst && whitespaceEdges) {
216
332
  const leadingWhitespace = whitespaceEdges[0] || "";
217
333
  const trailingWhitespace = whitespaceEdges[1] || "";
218
334
  replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace;
@@ -220,9 +336,9 @@ ${blockSuffix}` : suffix;
220
336
  selectionEnd -= trailingWhitespace.length;
221
337
  }
222
338
  return { text: replacementText, selectionStart, selectionEnd };
223
- } else if (scanFor.length > 0 && selectedText.match(scanFor)) {
339
+ } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {
224
340
  suffixToUse = suffixToUse.replace(replaceNext, selectedText);
225
- const replacementText = prefixToUse + selectedText + suffixToUse;
341
+ const replacementText = prefixToUse + suffixToUse;
226
342
  selectionStart = selectionEnd = selectionStart + prefixToUse.length;
227
343
  return { text: replacementText, selectionStart, selectionEnd };
228
344
  } else {
@@ -232,18 +348,24 @@ ${blockSuffix}` : suffix;
232
348
  return { text: replacementText, selectionStart, selectionEnd };
233
349
  }
234
350
  }
235
- function multilineStyle(textarea, arg) {
236
- const { prefix, suffix, surroundWithNewlines } = arg;
351
+ function multilineStyle(textarea, style) {
352
+ const { prefix, suffix, surroundWithNewlines } = style;
237
353
  let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
238
354
  let selectionStart = textarea.selectionStart;
239
355
  let selectionEnd = textarea.selectionEnd;
240
356
  const lines = text.split("\n");
241
- const undoStyle = lines.every((line) => line.startsWith(prefix) && line.endsWith(suffix));
357
+ const undoStyle = lines.every((line) => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)));
242
358
  if (undoStyle) {
243
- text = lines.map((line) => line.slice(prefix.length, line.length - suffix.length)).join("\n");
359
+ text = lines.map((line) => {
360
+ let result = line.slice(prefix.length);
361
+ if (suffix) {
362
+ result = result.slice(0, result.length - suffix.length);
363
+ }
364
+ return result;
365
+ }).join("\n");
244
366
  selectionEnd = selectionStart + text.length;
245
367
  } else {
246
- text = lines.map((line) => prefix + line + suffix).join("\n");
368
+ text = lines.map((line) => prefix + line + (suffix || "")).join("\n");
247
369
  if (surroundWithNewlines) {
248
370
  const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea);
249
371
  selectionStart += newlinesToAppend.length;
@@ -254,7 +376,7 @@ function multilineStyle(textarea, arg) {
254
376
  return { text, selectionStart, selectionEnd };
255
377
  }
256
378
 
257
- // src/operations/list-new.js
379
+ // src/operations/list.js
258
380
  function undoOrderedListStyle(text) {
259
381
  const lines = text.split("\n");
260
382
  const orderedListRegex = /^\d+\.\s+/;
@@ -274,7 +396,7 @@ function undoUnorderedListStyle(text) {
274
396
  const shouldUndoUnorderedList = lines.every((line) => line.startsWith(unorderedListPrefix));
275
397
  let result = lines;
276
398
  if (shouldUndoUnorderedList) {
277
- result = lines.map((line) => line.slice(unorderedListPrefix.length, line.length));
399
+ result = lines.map((line) => line.slice(unorderedListPrefix.length));
278
400
  }
279
401
  return {
280
402
  text: result.join("\n"),
@@ -289,19 +411,19 @@ function makePrefix(index, unorderedList) {
289
411
  }
290
412
  }
291
413
  function clearExistingListStyle(style, selectedText) {
292
- let undoResultOpositeList;
293
414
  let undoResult;
415
+ let undoResultOppositeList;
294
416
  let pristineText;
295
417
  if (style.orderedList) {
296
418
  undoResult = undoOrderedListStyle(selectedText);
297
- undoResultOpositeList = undoUnorderedListStyle(undoResult.text);
298
- pristineText = undoResultOpositeList.text;
419
+ undoResultOppositeList = undoUnorderedListStyle(undoResult.text);
420
+ pristineText = undoResultOppositeList.text;
299
421
  } else {
300
422
  undoResult = undoUnorderedListStyle(selectedText);
301
- undoResultOpositeList = undoOrderedListStyle(undoResult.text);
302
- pristineText = undoResultOpositeList.text;
423
+ undoResultOppositeList = undoOrderedListStyle(undoResult.text);
424
+ pristineText = undoResultOppositeList.text;
303
425
  }
304
- return [undoResult, undoResultOpositeList, pristineText];
426
+ return [undoResult, undoResultOppositeList, pristineText];
305
427
  }
306
428
  function listStyle(textarea, style) {
307
429
  const noInitialSelection = textarea.selectionStart === textarea.selectionEnd;
@@ -309,14 +431,14 @@ function listStyle(textarea, style) {
309
431
  let selectionEnd = textarea.selectionEnd;
310
432
  expandSelectionToLine(textarea);
311
433
  const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
312
- const [undoResult, undoResultOpositeList, pristineText] = clearExistingListStyle(style, selectedText);
434
+ const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText);
313
435
  const prefixedLines = pristineText.split("\n").map((value, index) => {
314
436
  return `${makePrefix(index, style.unorderedList)}${value}`;
315
437
  });
316
438
  const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {
317
439
  return previousValue + makePrefix(currentIndex, style.unorderedList).length;
318
440
  }, 0);
319
- const totalPrefixLengthOpositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {
441
+ const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {
320
442
  return previousValue + makePrefix(currentIndex, !style.unorderedList).length;
321
443
  }, 0);
322
444
  if (undoResult.processed) {
@@ -335,9 +457,9 @@ function listStyle(textarea, style) {
335
457
  selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0);
336
458
  selectionEnd = selectionStart;
337
459
  } else {
338
- if (undoResultOpositeList.processed) {
460
+ if (undoResultOppositeList.processed) {
339
461
  selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0);
340
- selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOpositeList;
462
+ selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList;
341
463
  } else {
342
464
  selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0);
343
465
  selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength;
@@ -345,18 +467,10 @@ function listStyle(textarea, style) {
345
467
  }
346
468
  return { text, selectionStart, selectionEnd };
347
469
  }
348
-
349
- // src/core/style-text.js
350
- function styleSelectedText(textarea, styleArgs) {
351
- const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
352
- let result;
353
- if (styleArgs.orderedList || styleArgs.unorderedList) {
354
- result = listStyle(textarea, styleArgs);
355
- } else if (styleArgs.multiline && isMultipleLines(text)) {
356
- result = multilineStyle(textarea, styleArgs);
357
- } else {
358
- result = blockStyle(textarea, styleArgs);
359
- }
470
+ function applyListStyle(textarea, style) {
471
+ const originalStart = textarea.selectionStart;
472
+ const originalEnd = textarea.selectionEnd;
473
+ const result = listStyle(textarea, style);
360
474
  insertText(textarea, result);
361
475
  }
362
476
 
@@ -441,107 +555,173 @@ function hasFormat(textarea, format) {
441
555
  const activeFormats = getActiveFormats(textarea);
442
556
  return activeFormats.includes(format);
443
557
  }
558
+ function expandSelection(textarea, options = {}) {
559
+ if (!textarea)
560
+ return;
561
+ const { toWord, toLine, toFormat } = options;
562
+ const { selectionStart, selectionEnd, value } = textarea;
563
+ if (toLine) {
564
+ const lines = value.split("\n");
565
+ let lineStart = 0;
566
+ let lineEnd = 0;
567
+ let currentPos = 0;
568
+ for (const line of lines) {
569
+ if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {
570
+ lineStart = currentPos;
571
+ lineEnd = currentPos + line.length;
572
+ break;
573
+ }
574
+ currentPos += line.length + 1;
575
+ }
576
+ textarea.selectionStart = lineStart;
577
+ textarea.selectionEnd = lineEnd;
578
+ } else if (toWord && selectionStart === selectionEnd) {
579
+ let start = selectionStart;
580
+ let end = selectionEnd;
581
+ while (start > 0 && !/\s/.test(value[start - 1])) {
582
+ start--;
583
+ }
584
+ while (end < value.length && !/\s/.test(value[end])) {
585
+ end++;
586
+ }
587
+ textarea.selectionStart = start;
588
+ textarea.selectionEnd = end;
589
+ }
590
+ }
444
591
 
445
- // src/index-new.js
446
- var FORMATS2 = {
447
- bold: { prefix: "**", suffix: "**", trimFirst: true },
448
- italic: { prefix: "_", suffix: "_", trimFirst: true },
449
- code: {
450
- prefix: "`",
451
- suffix: "`",
452
- blockPrefix: "```",
453
- blockSuffix: "```"
454
- },
455
- link: {
456
- prefix: "[",
457
- suffix: "](url)",
458
- replaceNext: "url",
459
- scanFor: "https?://"
460
- },
461
- quote: {
462
- prefix: "> ",
463
- multiline: true,
464
- surroundWithNewlines: true
465
- },
466
- bulletList: {
467
- prefix: "- ",
468
- multiline: true,
469
- unorderedList: true
470
- },
471
- numberedList: {
472
- prefix: "1. ",
473
- multiline: true,
474
- orderedList: true
475
- },
476
- header1: { prefix: "# " },
477
- header2: { prefix: "## " },
478
- header3: { prefix: "### " },
479
- header4: { prefix: "#### " },
480
- header5: { prefix: "##### " },
481
- header6: { prefix: "###### " }
482
- };
483
- function applyStyle(textarea, format) {
484
- const style = mergeStyleWithDefaults(format);
485
- textarea.focus();
486
- styleSelectedText(textarea, style);
592
+ // src/debug.js
593
+ function debugLog(funcName, message, data) {
594
+ console.group(`\u{1F50D} ${funcName}`);
595
+ console.log(message);
596
+ if (data) {
597
+ console.log("Data:", data);
598
+ }
599
+ console.groupEnd();
600
+ }
601
+ function debugSelection(textarea, label) {
602
+ const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
603
+ console.group(`\u{1F4CD} Selection: ${label}`);
604
+ console.log("Position:", `${textarea.selectionStart}-${textarea.selectionEnd}`);
605
+ console.log("Selected text:", JSON.stringify(selected));
606
+ console.log("Length:", selected.length);
607
+ const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);
608
+ const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));
609
+ console.log("Context:", JSON.stringify(before) + "[SELECTION]" + JSON.stringify(after));
610
+ console.groupEnd();
611
+ }
612
+ function debugResult(result) {
613
+ console.group("\u{1F4DD} Result");
614
+ console.log("Text to insert:", JSON.stringify(result.text));
615
+ console.log("New selection:", `${result.selectionStart}-${result.selectionEnd}`);
616
+ console.groupEnd();
487
617
  }
618
+
619
+ // src/index.js
488
620
  function toggleBold(textarea) {
489
621
  if (!textarea || textarea.disabled || textarea.readOnly)
490
622
  return;
491
- applyStyle(textarea, FORMATS2.bold);
623
+ debugLog("toggleBold", "Starting");
624
+ debugSelection(textarea, "Before");
625
+ const style = mergeWithDefaults(FORMATS.bold);
626
+ const result = blockStyle(textarea, style);
627
+ debugResult(result);
628
+ insertText(textarea, result);
629
+ debugSelection(textarea, "After");
492
630
  }
493
631
  function toggleItalic(textarea) {
494
632
  if (!textarea || textarea.disabled || textarea.readOnly)
495
633
  return;
496
- applyStyle(textarea, FORMATS2.italic);
634
+ const style = mergeWithDefaults(FORMATS.italic);
635
+ const result = blockStyle(textarea, style);
636
+ insertText(textarea, result);
497
637
  }
498
638
  function toggleCode(textarea) {
499
639
  if (!textarea || textarea.disabled || textarea.readOnly)
500
640
  return;
501
- applyStyle(textarea, FORMATS2.code);
641
+ const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
642
+ const style = mergeWithDefaults(FORMATS.code);
643
+ let result;
644
+ if (isMultipleLines(selectedText)) {
645
+ const blockStyle2 = {
646
+ prefix: "```\n",
647
+ suffix: "\n```",
648
+ surroundWithNewlines: true
649
+ };
650
+ result = multilineStyle(textarea, mergeWithDefaults(blockStyle2));
651
+ } else {
652
+ result = blockStyle(textarea, style);
653
+ }
654
+ insertText(textarea, result);
502
655
  }
503
656
  function insertLink(textarea, options = {}) {
504
657
  if (!textarea || textarea.disabled || textarea.readOnly)
505
658
  return;
506
- let format = __spreadValues({}, FORMATS2.link);
659
+ const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
660
+ let style = mergeWithDefaults(FORMATS.link);
507
661
  if (options.url) {
508
- format.suffix = `](${options.url})`;
509
- format.replaceNext = "";
662
+ style.suffix = `](${options.url})`;
663
+ style.replaceNext = "";
510
664
  }
511
- if (options.text && !textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)) {
665
+ if (options.text && !selectedText) {
512
666
  const pos = textarea.selectionStart;
513
667
  textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos);
514
668
  textarea.selectionStart = pos;
515
669
  textarea.selectionEnd = pos + options.text.length;
516
670
  }
517
- applyStyle(textarea, format);
671
+ const result = blockStyle(textarea, style);
672
+ insertText(textarea, result);
518
673
  }
519
674
  function toggleBulletList(textarea) {
520
675
  if (!textarea || textarea.disabled || textarea.readOnly)
521
676
  return;
522
- applyStyle(textarea, FORMATS2.bulletList);
677
+ const style = mergeWithDefaults(FORMATS.bulletList);
678
+ applyListStyle(textarea, style);
523
679
  }
524
680
  function toggleNumberedList(textarea) {
525
681
  if (!textarea || textarea.disabled || textarea.readOnly)
526
682
  return;
527
- applyStyle(textarea, FORMATS2.numberedList);
683
+ const style = mergeWithDefaults(FORMATS.numberedList);
684
+ applyListStyle(textarea, style);
528
685
  }
529
686
  function toggleQuote(textarea) {
530
687
  if (!textarea || textarea.disabled || textarea.readOnly)
531
688
  return;
532
- applyStyle(textarea, FORMATS2.quote);
689
+ debugLog("toggleQuote", "Starting");
690
+ debugSelection(textarea, "Initial");
691
+ const style = mergeWithDefaults(FORMATS.quote);
692
+ const result = applyLineOperation(
693
+ textarea,
694
+ (ta) => multilineStyle(ta, style),
695
+ { prefix: style.prefix }
696
+ );
697
+ debugResult(result);
698
+ insertText(textarea, result);
699
+ debugSelection(textarea, "Final");
533
700
  }
534
- function insertHeader(textarea, level = 1) {
701
+ function toggleTaskList(textarea) {
702
+ if (!textarea || textarea.disabled || textarea.readOnly)
703
+ return;
704
+ const style = mergeWithDefaults(FORMATS.taskList);
705
+ const result = applyLineOperation(
706
+ textarea,
707
+ (ta) => multilineStyle(ta, style),
708
+ { prefix: style.prefix }
709
+ );
710
+ insertText(textarea, result);
711
+ }
712
+ function insertHeader(textarea, level = 1, toggle = false) {
535
713
  if (!textarea || textarea.disabled || textarea.readOnly)
536
714
  return;
537
715
  if (level < 1 || level > 6)
538
716
  level = 1;
539
- const headerKey = `header${level}`;
540
- const format = FORMATS2[headerKey] || FORMATS2.header1;
717
+ const originalStart = textarea.selectionStart;
718
+ const originalEnd = textarea.selectionEnd;
719
+ const noInitialSelection = originalStart === originalEnd;
720
+ const headerKey = `header${level === 1 ? "1" : level}`;
721
+ const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1);
541
722
  const value = textarea.value;
542
- const start = textarea.selectionStart;
543
- let lineStart = start;
544
- let lineEnd = start;
723
+ let lineStart = originalStart;
724
+ let lineEnd = originalStart;
545
725
  while (lineStart > 0 && value[lineStart - 1] !== "\n") {
546
726
  lineStart--;
547
727
  }
@@ -551,12 +731,63 @@ function insertHeader(textarea, level = 1) {
551
731
  textarea.selectionStart = lineStart;
552
732
  textarea.selectionEnd = lineEnd;
553
733
  const currentLine = value.slice(lineStart, lineEnd);
734
+ const existingHeaderMatch = currentLine.match(/^(#{1,6})\s*/);
735
+ const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0;
736
+ const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0;
554
737
  const cleanedLine = currentLine.replace(/^#{1,6}\s*/, "");
555
- const newLine = format.prefix + cleanedLine;
556
- const tempSelection = textarea.selectionStart;
557
- textarea.value = value.slice(0, lineStart) + newLine + value.slice(lineEnd);
558
- textarea.selectionStart = lineStart + format.prefix.length;
559
- textarea.selectionEnd = lineStart + newLine.length;
738
+ let newLine;
739
+ let isRemoving = false;
740
+ if (toggle && existingLevel === level) {
741
+ newLine = cleanedLine;
742
+ isRemoving = true;
743
+ } else {
744
+ newLine = style.prefix + cleanedLine;
745
+ }
746
+ let selectionStart, selectionEnd;
747
+ if (noInitialSelection) {
748
+ const cursorOffsetInLine = originalStart - lineStart;
749
+ if (isRemoving) {
750
+ if (cursorOffsetInLine < existingPrefixLength) {
751
+ selectionStart = lineStart;
752
+ } else {
753
+ selectionStart = originalStart - existingPrefixLength;
754
+ }
755
+ } else if (existingPrefixLength > 0) {
756
+ if (cursorOffsetInLine < existingPrefixLength) {
757
+ selectionStart = lineStart + Math.min(cursorOffsetInLine, style.prefix.length);
758
+ } else {
759
+ const prefixDiff = style.prefix.length - existingPrefixLength;
760
+ selectionStart = originalStart + prefixDiff;
761
+ }
762
+ } else {
763
+ selectionStart = originalStart + style.prefix.length;
764
+ }
765
+ selectionStart = Math.min(selectionStart, lineStart + newLine.length);
766
+ selectionEnd = selectionStart;
767
+ } else {
768
+ if (isRemoving) {
769
+ selectionStart = lineStart;
770
+ selectionEnd = lineStart + newLine.length;
771
+ } else {
772
+ selectionStart = lineStart + style.prefix.length;
773
+ selectionEnd = lineStart + newLine.length;
774
+ }
775
+ }
776
+ const result = {
777
+ text: newLine,
778
+ selectionStart,
779
+ selectionEnd
780
+ };
781
+ insertText(textarea, result);
782
+ }
783
+ function toggleH1(textarea) {
784
+ insertHeader(textarea, 1, true);
785
+ }
786
+ function toggleH2(textarea) {
787
+ insertHeader(textarea, 2, true);
788
+ }
789
+ function toggleH3(textarea) {
790
+ insertHeader(textarea, 3, true);
560
791
  }
561
792
  function getActiveFormats2(textarea) {
562
793
  return getActiveFormats(textarea);
@@ -564,32 +795,27 @@ function getActiveFormats2(textarea) {
564
795
  function hasFormat2(textarea, format) {
565
796
  return hasFormat(textarea, format);
566
797
  }
567
- function expandSelection(textarea, options = {}) {
568
- if (!textarea)
569
- return;
570
- const { toWord, toLine } = options;
571
- const { selectionStart, selectionEnd, value } = textarea;
572
- if (toLine) {
573
- expandSelectionToLine(textarea);
574
- } else if (toWord && selectionStart === selectionEnd) {
575
- let start = selectionStart;
576
- let end = selectionEnd;
577
- while (start > 0 && !/\s/.test(value[start - 1])) {
578
- start--;
579
- }
580
- while (end < value.length && !/\s/.test(value[end])) {
581
- end++;
582
- }
583
- textarea.selectionStart = start;
584
- textarea.selectionEnd = end;
585
- }
798
+ function expandSelection2(textarea, options = {}) {
799
+ expandSelection(textarea, options);
586
800
  }
587
801
  function applyCustomFormat(textarea, format) {
588
802
  if (!textarea || textarea.disabled || textarea.readOnly)
589
803
  return;
590
- applyStyle(textarea, format);
804
+ const style = mergeWithDefaults(format);
805
+ let result;
806
+ if (style.multiline) {
807
+ const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
808
+ if (isMultipleLines(selectedText)) {
809
+ result = multilineStyle(textarea, style);
810
+ } else {
811
+ result = blockStyle(textarea, style);
812
+ }
813
+ } else {
814
+ result = blockStyle(textarea, style);
815
+ }
816
+ insertText(textarea, result);
591
817
  }
592
- var index_new_default = {
818
+ var src_default = {
593
819
  toggleBold,
594
820
  toggleItalic,
595
821
  toggleCode,
@@ -597,18 +823,22 @@ var index_new_default = {
597
823
  toggleBulletList,
598
824
  toggleNumberedList,
599
825
  toggleQuote,
826
+ toggleTaskList,
600
827
  insertHeader,
828
+ toggleH1,
829
+ toggleH2,
830
+ toggleH3,
601
831
  getActiveFormats: getActiveFormats2,
602
832
  hasFormat: hasFormat2,
603
- expandSelection,
833
+ expandSelection: expandSelection2,
604
834
  applyCustomFormat,
605
835
  preserveSelection,
606
836
  setUndoMethod
607
837
  };
608
838
  export {
609
839
  applyCustomFormat,
610
- index_new_default as default,
611
- expandSelection,
840
+ src_default as default,
841
+ expandSelection2 as expandSelection,
612
842
  getActiveFormats2 as getActiveFormats,
613
843
  hasFormat2 as hasFormat,
614
844
  insertHeader,
@@ -618,8 +848,12 @@ export {
618
848
  toggleBold,
619
849
  toggleBulletList,
620
850
  toggleCode,
851
+ toggleH1,
852
+ toggleH2,
853
+ toggleH3,
621
854
  toggleItalic,
622
855
  toggleNumberedList,
623
- toggleQuote
856
+ toggleQuote,
857
+ toggleTaskList
624
858
  };
625
859
  //# sourceMappingURL=markdown-actions.esm.js.map