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