overtype 1.2.0 → 1.2.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.
package/dist/overtype.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * OverType v1.2.0
2
+ * OverType v1.2.1
3
3
  * A lightweight markdown editor library with perfect WYSIWYG alignment
4
4
  * @license MIT
5
5
  * @author Demo User
@@ -387,997 +387,848 @@ var MarkdownParser = class {
387
387
  // Track link index for anchor naming
388
388
  __publicField(MarkdownParser, "linkIndex", 0);
389
389
 
390
- // node_modules/markdown-actions/dist/markdown-actions.js
391
- var markdownActions = (() => {
392
- var __defProp2 = Object.defineProperty;
393
- var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
394
- var __getOwnPropNames2 = Object.getOwnPropertyNames;
395
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
396
- var __hasOwnProp2 = Object.prototype.hasOwnProperty;
397
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
398
- var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
399
- var __spreadValues = (a, b) => {
400
- for (var prop in b || (b = {}))
401
- if (__hasOwnProp2.call(b, prop))
390
+ // node_modules/markdown-actions/dist/markdown-actions.esm.js
391
+ var __defProp2 = Object.defineProperty;
392
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
393
+ var __hasOwnProp2 = Object.prototype.hasOwnProperty;
394
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
395
+ var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
396
+ var __spreadValues = (a, b) => {
397
+ for (var prop in b || (b = {}))
398
+ if (__hasOwnProp2.call(b, prop))
399
+ __defNormalProp2(a, prop, b[prop]);
400
+ if (__getOwnPropSymbols)
401
+ for (var prop of __getOwnPropSymbols(b)) {
402
+ if (__propIsEnum.call(b, prop))
402
403
  __defNormalProp2(a, prop, b[prop]);
403
- if (__getOwnPropSymbols)
404
- for (var prop of __getOwnPropSymbols(b)) {
405
- if (__propIsEnum.call(b, prop))
406
- __defNormalProp2(a, prop, b[prop]);
407
- }
408
- return a;
409
- };
410
- var __export2 = (target, all) => {
411
- for (var name in all)
412
- __defProp2(target, name, { get: all[name], enumerable: true });
413
- };
414
- var __copyProps2 = (to, from, except, desc) => {
415
- if (from && typeof from === "object" || typeof from === "function") {
416
- for (let key of __getOwnPropNames2(from))
417
- if (!__hasOwnProp2.call(to, key) && key !== except)
418
- __defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
419
404
  }
420
- return to;
421
- };
422
- var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
423
- var src_exports = {};
424
- __export2(src_exports, {
425
- applyCustomFormat: () => applyCustomFormat,
426
- default: () => src_default,
427
- expandSelection: () => expandSelection2,
428
- getActiveFormats: () => getActiveFormats22,
429
- getDebugMode: () => getDebugMode,
430
- hasFormat: () => hasFormat2,
431
- insertHeader: () => insertHeader,
432
- insertLink: () => insertLink3,
433
- preserveSelection: () => preserveSelection,
434
- setDebugMode: () => setDebugMode,
435
- setUndoMethod: () => setUndoMethod,
436
- toggleBold: () => toggleBold3,
437
- toggleBulletList: () => toggleBulletList3,
438
- toggleCode: () => toggleCode2,
439
- toggleH1: () => toggleH12,
440
- toggleH2: () => toggleH22,
441
- toggleH3: () => toggleH32,
442
- toggleItalic: () => toggleItalic3,
443
- toggleNumberedList: () => toggleNumberedList3,
444
- toggleQuote: () => toggleQuote2,
445
- toggleTaskList: () => toggleTaskList2
446
- });
447
- var FORMATS = {
448
- bold: {
449
- prefix: "**",
450
- suffix: "**",
451
- trimFirst: true
452
- },
453
- italic: {
454
- prefix: "_",
455
- suffix: "_",
456
- trimFirst: true
457
- },
458
- code: {
459
- prefix: "`",
460
- suffix: "`",
461
- blockPrefix: "```",
462
- blockSuffix: "```"
463
- },
464
- link: {
465
- prefix: "[",
466
- suffix: "](url)",
467
- replaceNext: "url",
468
- scanFor: "https?://"
469
- },
470
- bulletList: {
471
- prefix: "- ",
472
- multiline: true,
473
- unorderedList: true
474
- },
475
- numberedList: {
476
- prefix: "1. ",
477
- multiline: true,
478
- orderedList: true
479
- },
480
- quote: {
481
- prefix: "> ",
482
- multiline: true,
483
- surroundWithNewlines: true
484
- },
485
- taskList: {
486
- prefix: "- [ ] ",
487
- multiline: true,
488
- surroundWithNewlines: true
489
- },
490
- header1: { prefix: "# " },
491
- header2: { prefix: "## " },
492
- header3: { prefix: "### " },
493
- header4: { prefix: "#### " },
494
- header5: { prefix: "##### " },
495
- header6: { prefix: "###### " }
405
+ return a;
406
+ };
407
+ var FORMATS = {
408
+ bold: {
409
+ prefix: "**",
410
+ suffix: "**",
411
+ trimFirst: true
412
+ },
413
+ italic: {
414
+ prefix: "_",
415
+ suffix: "_",
416
+ trimFirst: true
417
+ },
418
+ code: {
419
+ prefix: "`",
420
+ suffix: "`",
421
+ blockPrefix: "```",
422
+ blockSuffix: "```"
423
+ },
424
+ link: {
425
+ prefix: "[",
426
+ suffix: "](url)",
427
+ replaceNext: "url",
428
+ scanFor: "https?://"
429
+ },
430
+ bulletList: {
431
+ prefix: "- ",
432
+ multiline: true,
433
+ unorderedList: true
434
+ },
435
+ numberedList: {
436
+ prefix: "1. ",
437
+ multiline: true,
438
+ orderedList: true
439
+ },
440
+ quote: {
441
+ prefix: "> ",
442
+ multiline: true,
443
+ surroundWithNewlines: true
444
+ },
445
+ taskList: {
446
+ prefix: "- [ ] ",
447
+ multiline: true,
448
+ surroundWithNewlines: true
449
+ },
450
+ header1: { prefix: "# " },
451
+ header2: { prefix: "## " },
452
+ header3: { prefix: "### " },
453
+ header4: { prefix: "#### " },
454
+ header5: { prefix: "##### " },
455
+ header6: { prefix: "###### " }
456
+ };
457
+ function getDefaultStyle() {
458
+ return {
459
+ prefix: "",
460
+ suffix: "",
461
+ blockPrefix: "",
462
+ blockSuffix: "",
463
+ multiline: false,
464
+ replaceNext: "",
465
+ prefixSpace: false,
466
+ scanFor: "",
467
+ surroundWithNewlines: false,
468
+ orderedList: false,
469
+ unorderedList: false,
470
+ trimFirst: false
496
471
  };
497
- function getDefaultStyle() {
498
- return {
499
- prefix: "",
500
- suffix: "",
501
- blockPrefix: "",
502
- blockSuffix: "",
503
- multiline: false,
504
- replaceNext: "",
505
- prefixSpace: false,
506
- scanFor: "",
507
- surroundWithNewlines: false,
508
- orderedList: false,
509
- unorderedList: false,
510
- trimFirst: false
511
- };
512
- }
513
- function mergeWithDefaults(format) {
514
- return __spreadValues(__spreadValues({}, getDefaultStyle()), format);
515
- }
516
- var debugMode = false;
517
- function setDebugMode(enabled) {
518
- debugMode = enabled;
519
- }
520
- function getDebugMode() {
521
- return debugMode;
522
- }
523
- function debugLog(funcName, message, data) {
524
- if (!debugMode)
525
- return;
526
- console.group(`\u{1F50D} ${funcName}`);
527
- console.log(message);
528
- if (data) {
529
- console.log("Data:", data);
472
+ }
473
+ function mergeWithDefaults(format) {
474
+ return __spreadValues(__spreadValues({}, getDefaultStyle()), format);
475
+ }
476
+ var debugMode = false;
477
+ function getDebugMode() {
478
+ return debugMode;
479
+ }
480
+ function debugLog(funcName, message, data) {
481
+ if (!debugMode)
482
+ return;
483
+ console.group(`\u{1F50D} ${funcName}`);
484
+ console.log(message);
485
+ if (data) {
486
+ console.log("Data:", data);
487
+ }
488
+ console.groupEnd();
489
+ }
490
+ function debugSelection(textarea, label) {
491
+ if (!debugMode)
492
+ return;
493
+ const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
494
+ console.group(`\u{1F4CD} Selection: ${label}`);
495
+ console.log("Position:", `${textarea.selectionStart}-${textarea.selectionEnd}`);
496
+ console.log("Selected text:", JSON.stringify(selected));
497
+ console.log("Length:", selected.length);
498
+ const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);
499
+ const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));
500
+ console.log("Context:", JSON.stringify(before) + "[SELECTION]" + JSON.stringify(after));
501
+ console.groupEnd();
502
+ }
503
+ function debugResult(result) {
504
+ if (!debugMode)
505
+ return;
506
+ console.group("\u{1F4DD} Result");
507
+ console.log("Text to insert:", JSON.stringify(result.text));
508
+ console.log("New selection:", `${result.selectionStart}-${result.selectionEnd}`);
509
+ console.groupEnd();
510
+ }
511
+ var canInsertText = null;
512
+ function insertText(textarea, { text, selectionStart, selectionEnd }) {
513
+ const debugMode2 = getDebugMode();
514
+ if (debugMode2) {
515
+ console.group("\u{1F527} insertText");
516
+ console.log("Current selection:", `${textarea.selectionStart}-${textarea.selectionEnd}`);
517
+ console.log("Text to insert:", JSON.stringify(text));
518
+ console.log("New selection to set:", selectionStart, "-", selectionEnd);
519
+ }
520
+ textarea.focus();
521
+ const originalSelectionStart = textarea.selectionStart;
522
+ const originalSelectionEnd = textarea.selectionEnd;
523
+ const before = textarea.value.slice(0, originalSelectionStart);
524
+ const after = textarea.value.slice(originalSelectionEnd);
525
+ if (debugMode2) {
526
+ console.log("Before text (last 20):", JSON.stringify(before.slice(-20)));
527
+ console.log("After text (first 20):", JSON.stringify(after.slice(0, 20)));
528
+ console.log("Selected text being replaced:", JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));
529
+ }
530
+ const originalValue = textarea.value;
531
+ const hasSelection = originalSelectionStart !== originalSelectionEnd;
532
+ if (canInsertText === null || canInsertText === true) {
533
+ textarea.contentEditable = "true";
534
+ try {
535
+ canInsertText = document.execCommand("insertText", false, text);
536
+ if (debugMode2)
537
+ console.log("execCommand returned:", canInsertText, "for text with", text.split("\n").length, "lines");
538
+ } catch (error) {
539
+ canInsertText = false;
540
+ if (debugMode2)
541
+ console.log("execCommand threw error:", error);
530
542
  }
531
- console.groupEnd();
532
- }
533
- function debugSelection(textarea, label) {
534
- if (!debugMode)
535
- return;
536
- const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
537
- console.group(`\u{1F4CD} Selection: ${label}`);
538
- console.log("Position:", `${textarea.selectionStart}-${textarea.selectionEnd}`);
539
- console.log("Selected text:", JSON.stringify(selected));
540
- console.log("Length:", selected.length);
541
- const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);
542
- const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));
543
- console.log("Context:", JSON.stringify(before) + "[SELECTION]" + JSON.stringify(after));
544
- console.groupEnd();
543
+ textarea.contentEditable = "false";
545
544
  }
546
- function debugResult(result) {
547
- if (!debugMode)
548
- return;
549
- console.group("\u{1F4DD} Result");
550
- console.log("Text to insert:", JSON.stringify(result.text));
551
- console.log("New selection:", `${result.selectionStart}-${result.selectionEnd}`);
552
- console.groupEnd();
545
+ if (debugMode2) {
546
+ console.log("canInsertText before:", canInsertText);
547
+ console.log("execCommand result:", canInsertText);
553
548
  }
554
- var canInsertText = null;
555
- function insertText(textarea, { text, selectionStart, selectionEnd }) {
556
- const debugMode2 = getDebugMode();
549
+ if (canInsertText) {
550
+ const expectedValue = before + text + after;
551
+ const actualValue = textarea.value;
557
552
  if (debugMode2) {
558
- console.group("\u{1F527} insertText");
559
- console.log("Current selection:", `${textarea.selectionStart}-${textarea.selectionEnd}`);
560
- console.log("Text to insert:", JSON.stringify(text));
561
- console.log("New selection to set:", selectionStart, "-", selectionEnd);
553
+ console.log("Expected length:", expectedValue.length);
554
+ console.log("Actual length:", actualValue.length);
562
555
  }
563
- textarea.focus();
564
- const originalSelectionStart = textarea.selectionStart;
565
- const originalSelectionEnd = textarea.selectionEnd;
566
- const before = textarea.value.slice(0, originalSelectionStart);
567
- const after = textarea.value.slice(originalSelectionEnd);
568
- if (debugMode2) {
569
- console.log("Before text (last 20):", JSON.stringify(before.slice(-20)));
570
- console.log("After text (first 20):", JSON.stringify(after.slice(0, 20)));
571
- console.log("Selected text being replaced:", JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));
572
- }
573
- const originalValue = textarea.value;
574
- const hasSelection = originalSelectionStart !== originalSelectionEnd;
575
- if (canInsertText === null || canInsertText === true) {
576
- textarea.contentEditable = "true";
577
- try {
578
- canInsertText = document.execCommand("insertText", false, text);
579
- if (debugMode2)
580
- console.log("execCommand returned:", canInsertText, "for text with", text.split("\n").length, "lines");
581
- } catch (error) {
582
- canInsertText = false;
583
- if (debugMode2)
584
- console.log("execCommand threw error:", error);
585
- }
586
- textarea.contentEditable = "false";
587
- }
588
- if (debugMode2) {
589
- console.log("canInsertText before:", canInsertText);
590
- console.log("execCommand result:", canInsertText);
591
- }
592
- if (canInsertText) {
593
- const expectedValue = before + text + after;
594
- const actualValue = textarea.value;
556
+ if (actualValue !== expectedValue) {
595
557
  if (debugMode2) {
596
- console.log("Expected length:", expectedValue.length);
597
- console.log("Actual length:", actualValue.length);
598
- }
599
- if (actualValue !== expectedValue) {
600
- if (debugMode2) {
601
- console.log("execCommand changed the value but not as expected");
602
- console.log("Expected:", JSON.stringify(expectedValue.slice(0, 100)));
603
- console.log("Actual:", JSON.stringify(actualValue.slice(0, 100)));
604
- }
558
+ console.log("execCommand changed the value but not as expected");
559
+ console.log("Expected:", JSON.stringify(expectedValue.slice(0, 100)));
560
+ console.log("Actual:", JSON.stringify(actualValue.slice(0, 100)));
605
561
  }
606
562
  }
607
- if (!canInsertText) {
563
+ }
564
+ if (!canInsertText) {
565
+ if (debugMode2)
566
+ console.log("Using manual insertion");
567
+ if (textarea.value === originalValue) {
608
568
  if (debugMode2)
609
- console.log("Using manual insertion");
610
- if (textarea.value === originalValue) {
611
- if (debugMode2)
612
- console.log("Value unchanged, doing manual replacement");
613
- try {
614
- document.execCommand("ms-beginUndoUnit");
615
- } catch (e) {
616
- }
617
- textarea.value = before + text + after;
618
- try {
619
- document.execCommand("ms-endUndoUnit");
620
- } catch (e) {
621
- }
622
- textarea.dispatchEvent(new CustomEvent("input", { bubbles: true, cancelable: true }));
623
- } else {
624
- if (debugMode2)
625
- console.log("Value was changed by execCommand, skipping manual insertion");
569
+ console.log("Value unchanged, doing manual replacement");
570
+ try {
571
+ document.execCommand("ms-beginUndoUnit");
572
+ } catch (e) {
626
573
  }
627
- }
628
- if (debugMode2)
629
- console.log("Setting selection range:", selectionStart, selectionEnd);
630
- if (selectionStart != null && selectionEnd != null) {
631
- textarea.setSelectionRange(selectionStart, selectionEnd);
574
+ textarea.value = before + text + after;
575
+ try {
576
+ document.execCommand("ms-endUndoUnit");
577
+ } catch (e) {
578
+ }
579
+ textarea.dispatchEvent(new CustomEvent("input", { bubbles: true, cancelable: true }));
632
580
  } else {
633
- textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd);
634
- }
635
- if (debugMode2) {
636
- console.log("Final value length:", textarea.value.length);
637
- console.groupEnd();
638
- }
639
- }
640
- function setUndoMethod(method) {
641
- switch (method) {
642
- case "native":
643
- canInsertText = true;
644
- break;
645
- case "manual":
646
- canInsertText = false;
647
- break;
648
- case "auto":
649
- canInsertText = null;
650
- break;
581
+ if (debugMode2)
582
+ console.log("Value was changed by execCommand, skipping manual insertion");
651
583
  }
652
584
  }
653
- function isMultipleLines(string) {
654
- return string.trim().split("\n").length > 1;
585
+ if (debugMode2)
586
+ console.log("Setting selection range:", selectionStart, selectionEnd);
587
+ if (selectionStart != null && selectionEnd != null) {
588
+ textarea.setSelectionRange(selectionStart, selectionEnd);
589
+ } else {
590
+ textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd);
655
591
  }
656
- function wordSelectionStart(text, i) {
657
- let index = i;
658
- while (text[index] && text[index - 1] != null && !text[index - 1].match(/\s/)) {
659
- index--;
660
- }
661
- return index;
592
+ if (debugMode2) {
593
+ console.log("Final value length:", textarea.value.length);
594
+ console.groupEnd();
662
595
  }
663
- function wordSelectionEnd(text, i, multiline) {
664
- let index = i;
665
- const breakpoint = multiline ? /\n/ : /\s/;
666
- while (text[index] && !text[index].match(breakpoint)) {
667
- index++;
668
- }
669
- return index;
596
+ }
597
+ function isMultipleLines(string) {
598
+ return string.trim().split("\n").length > 1;
599
+ }
600
+ function wordSelectionStart(text, i) {
601
+ let index = i;
602
+ while (text[index] && text[index - 1] != null && !text[index - 1].match(/\s/)) {
603
+ index--;
670
604
  }
671
- function expandSelectionToLine(textarea) {
672
- const lines = textarea.value.split("\n");
673
- let counter = 0;
674
- for (let index = 0; index < lines.length; index++) {
675
- const lineLength = lines[index].length + 1;
676
- if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {
677
- textarea.selectionStart = counter;
678
- }
679
- if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {
680
- if (index === lines.length - 1) {
681
- textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length);
682
- } else {
683
- textarea.selectionEnd = counter + lineLength - 1;
684
- }
685
- }
686
- counter += lineLength;
687
- }
605
+ return index;
606
+ }
607
+ function wordSelectionEnd(text, i, multiline) {
608
+ let index = i;
609
+ const breakpoint = multiline ? /\n/ : /\s/;
610
+ while (text[index] && !text[index].match(breakpoint)) {
611
+ index++;
688
612
  }
689
- function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {
690
- if (textarea.selectionStart === textarea.selectionEnd) {
691
- textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart);
692
- textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline);
693
- } else {
694
- const expandedSelectionStart = textarea.selectionStart - prefixToUse.length;
695
- const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length;
696
- const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse;
697
- const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse;
698
- if (beginsWithPrefix && endsWithSuffix) {
699
- textarea.selectionStart = expandedSelectionStart;
700
- textarea.selectionEnd = expandedSelectionEnd;
613
+ return index;
614
+ }
615
+ function expandSelectionToLine(textarea) {
616
+ const lines = textarea.value.split("\n");
617
+ let counter = 0;
618
+ for (let index = 0; index < lines.length; index++) {
619
+ const lineLength = lines[index].length + 1;
620
+ if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {
621
+ textarea.selectionStart = counter;
622
+ }
623
+ if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {
624
+ if (index === lines.length - 1) {
625
+ textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length);
626
+ } else {
627
+ textarea.selectionEnd = counter + lineLength - 1;
701
628
  }
702
629
  }
703
- return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
630
+ counter += lineLength;
704
631
  }
705
- function newlinesToSurroundSelectedText(textarea) {
706
- const beforeSelection = textarea.value.slice(0, textarea.selectionStart);
707
- const afterSelection = textarea.value.slice(textarea.selectionEnd);
708
- const breaksBefore = beforeSelection.match(/\n*$/);
709
- const breaksAfter = afterSelection.match(/^\n*/);
710
- const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0;
711
- const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0;
712
- let newlinesToAppend = "";
713
- let newlinesToPrepend = "";
714
- if (beforeSelection.match(/\S/) && newlinesBeforeSelection < 2) {
715
- newlinesToAppend = "\n".repeat(2 - newlinesBeforeSelection);
716
- }
717
- if (afterSelection.match(/\S/) && newlinesAfterSelection < 2) {
718
- newlinesToPrepend = "\n".repeat(2 - newlinesAfterSelection);
632
+ }
633
+ function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {
634
+ if (textarea.selectionStart === textarea.selectionEnd) {
635
+ textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart);
636
+ textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline);
637
+ } else {
638
+ const expandedSelectionStart = textarea.selectionStart - prefixToUse.length;
639
+ const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length;
640
+ const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse;
641
+ const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse;
642
+ if (beginsWithPrefix && endsWithSuffix) {
643
+ textarea.selectionStart = expandedSelectionStart;
644
+ textarea.selectionEnd = expandedSelectionEnd;
645
+ }
646
+ }
647
+ return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
648
+ }
649
+ function newlinesToSurroundSelectedText(textarea) {
650
+ const beforeSelection = textarea.value.slice(0, textarea.selectionStart);
651
+ const afterSelection = textarea.value.slice(textarea.selectionEnd);
652
+ const breaksBefore = beforeSelection.match(/\n*$/);
653
+ const breaksAfter = afterSelection.match(/^\n*/);
654
+ const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0;
655
+ const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0;
656
+ let newlinesToAppend = "";
657
+ let newlinesToPrepend = "";
658
+ if (beforeSelection.match(/\S/) && newlinesBeforeSelection < 2) {
659
+ newlinesToAppend = "\n".repeat(2 - newlinesBeforeSelection);
660
+ }
661
+ if (afterSelection.match(/\S/) && newlinesAfterSelection < 2) {
662
+ newlinesToPrepend = "\n".repeat(2 - newlinesAfterSelection);
663
+ }
664
+ return { newlinesToAppend, newlinesToPrepend };
665
+ }
666
+ function applyLineOperation(textarea, operation, options = {}) {
667
+ const originalStart = textarea.selectionStart;
668
+ const originalEnd = textarea.selectionEnd;
669
+ const noInitialSelection = originalStart === originalEnd;
670
+ const value = textarea.value;
671
+ let lineStart = originalStart;
672
+ while (lineStart > 0 && value[lineStart - 1] !== "\n") {
673
+ lineStart--;
674
+ }
675
+ if (noInitialSelection) {
676
+ let lineEnd = originalStart;
677
+ while (lineEnd < value.length && value[lineEnd] !== "\n") {
678
+ lineEnd++;
719
679
  }
720
- return { newlinesToAppend, newlinesToPrepend };
721
- }
722
- function preserveSelection(textarea, callback) {
723
- const start = textarea.selectionStart;
724
- const end = textarea.selectionEnd;
725
- const scrollTop = textarea.scrollTop;
726
- callback();
727
- textarea.selectionStart = start;
728
- textarea.selectionEnd = end;
729
- textarea.scrollTop = scrollTop;
680
+ textarea.selectionStart = lineStart;
681
+ textarea.selectionEnd = lineEnd;
682
+ } else {
683
+ expandSelectionToLine(textarea);
730
684
  }
731
- function applyLineOperation(textarea, operation, options = {}) {
732
- const originalStart = textarea.selectionStart;
733
- const originalEnd = textarea.selectionEnd;
734
- const noInitialSelection = originalStart === originalEnd;
735
- const value = textarea.value;
736
- let lineStart = originalStart;
737
- while (lineStart > 0 && value[lineStart - 1] !== "\n") {
738
- lineStart--;
739
- }
685
+ const result = operation(textarea);
686
+ if (options.adjustSelection) {
687
+ const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
688
+ const isRemoving = selectedText.startsWith(options.prefix);
689
+ const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart);
690
+ result.selectionStart = adjusted.start;
691
+ result.selectionEnd = adjusted.end;
692
+ } else if (options.prefix) {
693
+ const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
694
+ const isRemoving = selectedText.startsWith(options.prefix);
740
695
  if (noInitialSelection) {
741
- let lineEnd = originalStart;
742
- while (lineEnd < value.length && value[lineEnd] !== "\n") {
743
- lineEnd++;
696
+ if (isRemoving) {
697
+ result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart);
698
+ result.selectionEnd = result.selectionStart;
699
+ } else {
700
+ result.selectionStart = originalStart + options.prefix.length;
701
+ result.selectionEnd = result.selectionStart;
744
702
  }
745
- textarea.selectionStart = lineStart;
746
- textarea.selectionEnd = lineEnd;
747
703
  } else {
748
- expandSelectionToLine(textarea);
749
- }
750
- const result = operation(textarea);
751
- if (options.adjustSelection) {
752
- const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
753
- const isRemoving = selectedText.startsWith(options.prefix);
754
- const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart);
755
- result.selectionStart = adjusted.start;
756
- result.selectionEnd = adjusted.end;
757
- } else if (options.prefix) {
758
- const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
759
- const isRemoving = selectedText.startsWith(options.prefix);
760
- if (noInitialSelection) {
761
- if (isRemoving) {
762
- result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart);
763
- result.selectionEnd = result.selectionStart;
764
- } else {
765
- result.selectionStart = originalStart + options.prefix.length;
766
- result.selectionEnd = result.selectionStart;
767
- }
704
+ if (isRemoving) {
705
+ result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart);
706
+ result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart);
768
707
  } else {
769
- if (isRemoving) {
770
- result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart);
771
- result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart);
772
- } else {
773
- result.selectionStart = originalStart + options.prefix.length;
774
- result.selectionEnd = originalEnd + options.prefix.length;
775
- }
708
+ result.selectionStart = originalStart + options.prefix.length;
709
+ result.selectionEnd = originalEnd + options.prefix.length;
776
710
  }
777
711
  }
778
- return result;
779
712
  }
780
- function blockStyle(textarea, style) {
781
- let newlinesToAppend;
782
- let newlinesToPrepend;
783
- const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style;
784
- const originalSelectionStart = textarea.selectionStart;
785
- const originalSelectionEnd = textarea.selectionEnd;
786
- let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
787
- let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}
713
+ return result;
714
+ }
715
+ function blockStyle(textarea, style) {
716
+ let newlinesToAppend;
717
+ let newlinesToPrepend;
718
+ const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style;
719
+ const originalSelectionStart = textarea.selectionStart;
720
+ const originalSelectionEnd = textarea.selectionEnd;
721
+ let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
722
+ let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}
788
723
  ` : prefix;
789
- let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `
724
+ let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `
790
725
  ${blockSuffix}` : suffix;
791
- if (prefixSpace) {
792
- const beforeSelection = textarea.value[textarea.selectionStart - 1];
793
- if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\s/)) {
794
- prefixToUse = ` ${prefixToUse}`;
795
- }
796
- }
797
- selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline);
798
- let selectionStart = textarea.selectionStart;
799
- let selectionEnd = textarea.selectionEnd;
800
- const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0;
801
- if (surroundWithNewlines) {
802
- const ref = newlinesToSurroundSelectedText(textarea);
803
- newlinesToAppend = ref.newlinesToAppend;
804
- newlinesToPrepend = ref.newlinesToPrepend;
805
- prefixToUse = newlinesToAppend + prefix;
806
- suffixToUse += newlinesToPrepend;
807
- }
808
- if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {
809
- const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length);
810
- if (originalSelectionStart === originalSelectionEnd) {
811
- let position = originalSelectionStart - prefixToUse.length;
812
- position = Math.max(position, selectionStart);
813
- position = Math.min(position, selectionStart + replacementText.length);
814
- selectionStart = selectionEnd = position;
815
- } else {
816
- selectionEnd = selectionStart + replacementText.length;
817
- }
818
- return { text: replacementText, selectionStart, selectionEnd };
819
- } else if (!hasReplaceNext) {
820
- let replacementText = prefixToUse + selectedText + suffixToUse;
821
- selectionStart = originalSelectionStart + prefixToUse.length;
822
- selectionEnd = originalSelectionEnd + prefixToUse.length;
823
- const whitespaceEdges = selectedText.match(/^\s*|\s*$/g);
824
- if (trimFirst && whitespaceEdges) {
825
- const leadingWhitespace = whitespaceEdges[0] || "";
826
- const trailingWhitespace = whitespaceEdges[1] || "";
827
- replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace;
828
- selectionStart += leadingWhitespace.length;
829
- selectionEnd -= trailingWhitespace.length;
830
- }
831
- return { text: replacementText, selectionStart, selectionEnd };
832
- } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {
833
- suffixToUse = suffixToUse.replace(replaceNext, selectedText);
834
- const replacementText = prefixToUse + suffixToUse;
835
- selectionStart = selectionEnd = selectionStart + prefixToUse.length;
836
- return { text: replacementText, selectionStart, selectionEnd };
726
+ if (prefixSpace) {
727
+ const beforeSelection = textarea.value[textarea.selectionStart - 1];
728
+ if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\s/)) {
729
+ prefixToUse = ` ${prefixToUse}`;
730
+ }
731
+ }
732
+ selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline);
733
+ let selectionStart = textarea.selectionStart;
734
+ let selectionEnd = textarea.selectionEnd;
735
+ const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0;
736
+ if (surroundWithNewlines) {
737
+ const ref = newlinesToSurroundSelectedText(textarea);
738
+ newlinesToAppend = ref.newlinesToAppend;
739
+ newlinesToPrepend = ref.newlinesToPrepend;
740
+ prefixToUse = newlinesToAppend + prefix;
741
+ suffixToUse += newlinesToPrepend;
742
+ }
743
+ if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {
744
+ const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length);
745
+ if (originalSelectionStart === originalSelectionEnd) {
746
+ let position = originalSelectionStart - prefixToUse.length;
747
+ position = Math.max(position, selectionStart);
748
+ position = Math.min(position, selectionStart + replacementText.length);
749
+ selectionStart = selectionEnd = position;
837
750
  } else {
838
- const replacementText = prefixToUse + selectedText + suffixToUse;
839
- selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext);
840
- selectionEnd = selectionStart + replaceNext.length;
841
- return { text: replacementText, selectionStart, selectionEnd };
842
- }
751
+ selectionEnd = selectionStart + replacementText.length;
752
+ }
753
+ return { text: replacementText, selectionStart, selectionEnd };
754
+ } else if (!hasReplaceNext) {
755
+ let replacementText = prefixToUse + selectedText + suffixToUse;
756
+ selectionStart = originalSelectionStart + prefixToUse.length;
757
+ selectionEnd = originalSelectionEnd + prefixToUse.length;
758
+ const whitespaceEdges = selectedText.match(/^\s*|\s*$/g);
759
+ if (trimFirst && whitespaceEdges) {
760
+ const leadingWhitespace = whitespaceEdges[0] || "";
761
+ const trailingWhitespace = whitespaceEdges[1] || "";
762
+ replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace;
763
+ selectionStart += leadingWhitespace.length;
764
+ selectionEnd -= trailingWhitespace.length;
765
+ }
766
+ return { text: replacementText, selectionStart, selectionEnd };
767
+ } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {
768
+ suffixToUse = suffixToUse.replace(replaceNext, selectedText);
769
+ const replacementText = prefixToUse + suffixToUse;
770
+ selectionStart = selectionEnd = selectionStart + prefixToUse.length;
771
+ return { text: replacementText, selectionStart, selectionEnd };
772
+ } else {
773
+ const replacementText = prefixToUse + selectedText + suffixToUse;
774
+ selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext);
775
+ selectionEnd = selectionStart + replaceNext.length;
776
+ return { text: replacementText, selectionStart, selectionEnd };
843
777
  }
844
- function multilineStyle(textarea, style) {
845
- const { prefix, suffix, surroundWithNewlines } = style;
846
- let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
847
- let selectionStart = textarea.selectionStart;
848
- let selectionEnd = textarea.selectionEnd;
849
- const lines = text.split("\n");
850
- const undoStyle = lines.every((line) => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)));
851
- if (undoStyle) {
852
- text = lines.map((line) => {
853
- let result = line.slice(prefix.length);
854
- if (suffix) {
855
- result = result.slice(0, result.length - suffix.length);
856
- }
857
- return result;
858
- }).join("\n");
778
+ }
779
+ function multilineStyle(textarea, style) {
780
+ const { prefix, suffix, surroundWithNewlines } = style;
781
+ let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
782
+ let selectionStart = textarea.selectionStart;
783
+ let selectionEnd = textarea.selectionEnd;
784
+ const lines = text.split("\n");
785
+ const undoStyle = lines.every((line) => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)));
786
+ if (undoStyle) {
787
+ text = lines.map((line) => {
788
+ let result = line.slice(prefix.length);
789
+ if (suffix) {
790
+ result = result.slice(0, result.length - suffix.length);
791
+ }
792
+ return result;
793
+ }).join("\n");
794
+ selectionEnd = selectionStart + text.length;
795
+ } else {
796
+ text = lines.map((line) => prefix + line + (suffix || "")).join("\n");
797
+ if (surroundWithNewlines) {
798
+ const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea);
799
+ selectionStart += newlinesToAppend.length;
859
800
  selectionEnd = selectionStart + text.length;
860
- } else {
861
- text = lines.map((line) => prefix + line + (suffix || "")).join("\n");
862
- if (surroundWithNewlines) {
863
- const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea);
864
- selectionStart += newlinesToAppend.length;
865
- selectionEnd = selectionStart + text.length;
866
- text = newlinesToAppend + text + newlinesToPrepend;
867
- }
801
+ text = newlinesToAppend + text + newlinesToPrepend;
868
802
  }
869
- return { text, selectionStart, selectionEnd };
870
803
  }
871
- function undoOrderedListStyle(text) {
872
- const lines = text.split("\n");
873
- const orderedListRegex = /^\d+\.\s+/;
874
- const shouldUndoOrderedList = lines.every((line) => orderedListRegex.test(line));
875
- let result = lines;
876
- if (shouldUndoOrderedList) {
877
- result = lines.map((line) => line.replace(orderedListRegex, ""));
878
- }
879
- return {
880
- text: result.join("\n"),
881
- processed: shouldUndoOrderedList
882
- };
883
- }
884
- function undoUnorderedListStyle(text) {
885
- const lines = text.split("\n");
886
- const unorderedListPrefix = "- ";
887
- const shouldUndoUnorderedList = lines.every((line) => line.startsWith(unorderedListPrefix));
888
- let result = lines;
889
- if (shouldUndoUnorderedList) {
890
- result = lines.map((line) => line.slice(unorderedListPrefix.length));
891
- }
892
- return {
893
- text: result.join("\n"),
894
- processed: shouldUndoUnorderedList
895
- };
804
+ return { text, selectionStart, selectionEnd };
805
+ }
806
+ function undoOrderedListStyle(text) {
807
+ const lines = text.split("\n");
808
+ const orderedListRegex = /^\d+\.\s+/;
809
+ const shouldUndoOrderedList = lines.every((line) => orderedListRegex.test(line));
810
+ let result = lines;
811
+ if (shouldUndoOrderedList) {
812
+ result = lines.map((line) => line.replace(orderedListRegex, ""));
896
813
  }
897
- function makePrefix(index, unorderedList) {
898
- if (unorderedList) {
899
- return "- ";
900
- } else {
901
- return `${index + 1}. `;
902
- }
814
+ return {
815
+ text: result.join("\n"),
816
+ processed: shouldUndoOrderedList
817
+ };
818
+ }
819
+ function undoUnorderedListStyle(text) {
820
+ const lines = text.split("\n");
821
+ const unorderedListPrefix = "- ";
822
+ const shouldUndoUnorderedList = lines.every((line) => line.startsWith(unorderedListPrefix));
823
+ let result = lines;
824
+ if (shouldUndoUnorderedList) {
825
+ result = lines.map((line) => line.slice(unorderedListPrefix.length));
903
826
  }
904
- function clearExistingListStyle(style, selectedText) {
905
- let undoResult;
906
- let undoResultOppositeList;
907
- let pristineText;
908
- if (style.orderedList) {
909
- undoResult = undoOrderedListStyle(selectedText);
910
- undoResultOppositeList = undoUnorderedListStyle(undoResult.text);
911
- pristineText = undoResultOppositeList.text;
912
- } else {
913
- undoResult = undoUnorderedListStyle(selectedText);
914
- undoResultOppositeList = undoOrderedListStyle(undoResult.text);
915
- pristineText = undoResultOppositeList.text;
916
- }
917
- return [undoResult, undoResultOppositeList, pristineText];
827
+ return {
828
+ text: result.join("\n"),
829
+ processed: shouldUndoUnorderedList
830
+ };
831
+ }
832
+ function makePrefix(index, unorderedList) {
833
+ if (unorderedList) {
834
+ return "- ";
835
+ } else {
836
+ return `${index + 1}. `;
918
837
  }
919
- function listStyle(textarea, style) {
920
- const noInitialSelection = textarea.selectionStart === textarea.selectionEnd;
921
- let selectionStart = textarea.selectionStart;
922
- let selectionEnd = textarea.selectionEnd;
923
- expandSelectionToLine(textarea);
924
- const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
925
- const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText);
926
- const prefixedLines = pristineText.split("\n").map((value, index) => {
927
- return `${makePrefix(index, style.unorderedList)}${value}`;
928
- });
929
- const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {
930
- return previousValue + makePrefix(currentIndex, style.unorderedList).length;
931
- }, 0);
932
- const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {
933
- return previousValue + makePrefix(currentIndex, !style.unorderedList).length;
934
- }, 0);
935
- if (undoResult.processed) {
936
- if (noInitialSelection) {
937
- selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0);
938
- selectionEnd = selectionStart;
939
- } else {
940
- selectionStart = textarea.selectionStart;
941
- selectionEnd = textarea.selectionEnd - totalPrefixLength;
942
- }
943
- return { text: pristineText, selectionStart, selectionEnd };
944
- }
945
- const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea);
946
- const text = newlinesToAppend + prefixedLines.join("\n") + newlinesToPrepend;
838
+ }
839
+ function clearExistingListStyle(style, selectedText) {
840
+ let undoResult;
841
+ let undoResultOppositeList;
842
+ let pristineText;
843
+ if (style.orderedList) {
844
+ undoResult = undoOrderedListStyle(selectedText);
845
+ undoResultOppositeList = undoUnorderedListStyle(undoResult.text);
846
+ pristineText = undoResultOppositeList.text;
847
+ } else {
848
+ undoResult = undoUnorderedListStyle(selectedText);
849
+ undoResultOppositeList = undoOrderedListStyle(undoResult.text);
850
+ pristineText = undoResultOppositeList.text;
851
+ }
852
+ return [undoResult, undoResultOppositeList, pristineText];
853
+ }
854
+ function listStyle(textarea, style) {
855
+ const noInitialSelection = textarea.selectionStart === textarea.selectionEnd;
856
+ let selectionStart = textarea.selectionStart;
857
+ let selectionEnd = textarea.selectionEnd;
858
+ expandSelectionToLine(textarea);
859
+ const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
860
+ const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText);
861
+ const prefixedLines = pristineText.split("\n").map((value, index) => {
862
+ return `${makePrefix(index, style.unorderedList)}${value}`;
863
+ });
864
+ const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {
865
+ return previousValue + makePrefix(currentIndex, style.unorderedList).length;
866
+ }, 0);
867
+ const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {
868
+ return previousValue + makePrefix(currentIndex, !style.unorderedList).length;
869
+ }, 0);
870
+ if (undoResult.processed) {
947
871
  if (noInitialSelection) {
948
- selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0);
872
+ selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0);
949
873
  selectionEnd = selectionStart;
950
874
  } else {
951
- if (undoResultOppositeList.processed) {
952
- selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0);
953
- selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList;
954
- } else {
955
- selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0);
956
- selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength;
957
- }
875
+ selectionStart = textarea.selectionStart;
876
+ selectionEnd = textarea.selectionEnd - totalPrefixLength;
877
+ }
878
+ return { text: pristineText, selectionStart, selectionEnd };
879
+ }
880
+ const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea);
881
+ const text = newlinesToAppend + prefixedLines.join("\n") + newlinesToPrepend;
882
+ if (noInitialSelection) {
883
+ selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0);
884
+ selectionEnd = selectionStart;
885
+ } else {
886
+ if (undoResultOppositeList.processed) {
887
+ selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0);
888
+ selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList;
889
+ } else {
890
+ selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0);
891
+ selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength;
958
892
  }
959
- return { text, selectionStart, selectionEnd };
960
- }
961
- function applyListStyle(textarea, style) {
962
- const result = applyLineOperation(
963
- textarea,
964
- (ta) => listStyle(ta, style),
965
- {
966
- // Custom selection adjustment for lists
967
- adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {
968
- const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd);
969
- const orderedListRegex = /^\d+\.\s+/;
970
- const unorderedListRegex = /^- /;
971
- const hasOrderedList = orderedListRegex.test(currentLine);
972
- const hasUnorderedList = unorderedListRegex.test(currentLine);
973
- const isRemovingCurrent = style.orderedList && hasOrderedList || style.unorderedList && hasUnorderedList;
974
- if (selStart === selEnd) {
975
- if (isRemovingCurrent) {
976
- const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex);
977
- const prefixLength = prefixMatch ? prefixMatch[0].length : 0;
978
- return {
979
- start: Math.max(selStart - prefixLength, lineStart),
980
- end: Math.max(selStart - prefixLength, lineStart)
981
- };
982
- } else if (hasOrderedList || hasUnorderedList) {
983
- const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex);
984
- const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0;
985
- const newPrefixLength = style.unorderedList ? 2 : 3;
986
- const adjustment = newPrefixLength - oldPrefixLength;
987
- return {
988
- start: selStart + adjustment,
989
- end: selStart + adjustment
990
- };
991
- } else {
992
- const prefixLength = style.unorderedList ? 2 : 3;
993
- return {
994
- start: selStart + prefixLength,
995
- end: selStart + prefixLength
996
- };
997
- }
893
+ }
894
+ return { text, selectionStart, selectionEnd };
895
+ }
896
+ function applyListStyle(textarea, style) {
897
+ const result = applyLineOperation(
898
+ textarea,
899
+ (ta) => listStyle(ta, style),
900
+ {
901
+ // Custom selection adjustment for lists
902
+ adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {
903
+ const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd);
904
+ const orderedListRegex = /^\d+\.\s+/;
905
+ const unorderedListRegex = /^- /;
906
+ const hasOrderedList = orderedListRegex.test(currentLine);
907
+ const hasUnorderedList = unorderedListRegex.test(currentLine);
908
+ const isRemovingCurrent = style.orderedList && hasOrderedList || style.unorderedList && hasUnorderedList;
909
+ if (selStart === selEnd) {
910
+ if (isRemovingCurrent) {
911
+ const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex);
912
+ const prefixLength = prefixMatch ? prefixMatch[0].length : 0;
913
+ return {
914
+ start: Math.max(selStart - prefixLength, lineStart),
915
+ end: Math.max(selStart - prefixLength, lineStart)
916
+ };
917
+ } else if (hasOrderedList || hasUnorderedList) {
918
+ const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex);
919
+ const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0;
920
+ const newPrefixLength = style.unorderedList ? 2 : 3;
921
+ const adjustment = newPrefixLength - oldPrefixLength;
922
+ return {
923
+ start: selStart + adjustment,
924
+ end: selStart + adjustment
925
+ };
998
926
  } else {
999
- if (isRemovingCurrent) {
1000
- const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex);
1001
- const prefixLength = prefixMatch ? prefixMatch[0].length : 0;
1002
- return {
1003
- start: Math.max(selStart - prefixLength, lineStart),
1004
- end: Math.max(selEnd - prefixLength, lineStart)
1005
- };
1006
- } else if (hasOrderedList || hasUnorderedList) {
1007
- const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex);
1008
- const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0;
1009
- const newPrefixLength = style.unorderedList ? 2 : 3;
1010
- const adjustment = newPrefixLength - oldPrefixLength;
1011
- return {
1012
- start: selStart + adjustment,
1013
- end: selEnd + adjustment
1014
- };
1015
- } else {
1016
- const prefixLength = style.unorderedList ? 2 : 3;
1017
- return {
1018
- start: selStart + prefixLength,
1019
- end: selEnd + prefixLength
1020
- };
1021
- }
927
+ const prefixLength = style.unorderedList ? 2 : 3;
928
+ return {
929
+ start: selStart + prefixLength,
930
+ end: selStart + prefixLength
931
+ };
1022
932
  }
1023
- }
1024
- }
1025
- );
1026
- insertText(textarea, result);
1027
- }
1028
- function getActiveFormats2(textarea) {
1029
- if (!textarea)
1030
- return [];
1031
- const formats = [];
1032
- const { selectionStart, selectionEnd, value } = textarea;
1033
- const lines = value.split("\n");
1034
- let lineStart = 0;
1035
- let currentLine = "";
1036
- for (const line of lines) {
1037
- if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {
1038
- currentLine = line;
1039
- break;
1040
- }
1041
- lineStart += line.length + 1;
1042
- }
1043
- if (currentLine.startsWith("- ")) {
1044
- if (currentLine.startsWith("- [ ] ") || currentLine.startsWith("- [x] ")) {
1045
- formats.push("task-list");
1046
- } else {
1047
- formats.push("bullet-list");
1048
- }
1049
- }
1050
- if (/^\d+\.\s/.test(currentLine)) {
1051
- formats.push("numbered-list");
1052
- }
1053
- if (currentLine.startsWith("> ")) {
1054
- formats.push("quote");
1055
- }
1056
- if (currentLine.startsWith("# "))
1057
- formats.push("header");
1058
- if (currentLine.startsWith("## "))
1059
- formats.push("header-2");
1060
- if (currentLine.startsWith("### "))
1061
- formats.push("header-3");
1062
- const lookBehind = Math.max(0, selectionStart - 10);
1063
- const lookAhead = Math.min(value.length, selectionEnd + 10);
1064
- const surrounding = value.slice(lookBehind, lookAhead);
1065
- if (surrounding.includes("**")) {
1066
- const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
1067
- const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
1068
- const lastOpenBold = beforeCursor.lastIndexOf("**");
1069
- const nextCloseBold = afterCursor.indexOf("**");
1070
- if (lastOpenBold !== -1 && nextCloseBold !== -1) {
1071
- formats.push("bold");
1072
- }
1073
- }
1074
- if (surrounding.includes("_")) {
1075
- const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
1076
- const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
1077
- const lastOpenItalic = beforeCursor.lastIndexOf("_");
1078
- const nextCloseItalic = afterCursor.indexOf("_");
1079
- if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {
1080
- formats.push("italic");
1081
- }
1082
- }
1083
- if (surrounding.includes("`")) {
1084
- const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
1085
- const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
1086
- if (beforeCursor.includes("`") && afterCursor.includes("`")) {
1087
- formats.push("code");
1088
- }
1089
- }
1090
- if (surrounding.includes("[") && surrounding.includes("]")) {
1091
- const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
1092
- const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
1093
- const lastOpenBracket = beforeCursor.lastIndexOf("[");
1094
- const nextCloseBracket = afterCursor.indexOf("]");
1095
- if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {
1096
- const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10);
1097
- if (afterBracket.startsWith("(")) {
1098
- formats.push("link");
1099
- }
1100
- }
1101
- }
1102
- return formats;
1103
- }
1104
- function hasFormat(textarea, format) {
1105
- const activeFormats = getActiveFormats2(textarea);
1106
- return activeFormats.includes(format);
1107
- }
1108
- function expandSelection(textarea, options = {}) {
1109
- if (!textarea)
1110
- return;
1111
- const { toWord, toLine, toFormat } = options;
1112
- const { selectionStart, selectionEnd, value } = textarea;
1113
- if (toLine) {
1114
- const lines = value.split("\n");
1115
- let lineStart = 0;
1116
- let lineEnd = 0;
1117
- let currentPos = 0;
1118
- for (const line of lines) {
1119
- if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {
1120
- lineStart = currentPos;
1121
- lineEnd = currentPos + line.length;
1122
- break;
1123
- }
1124
- currentPos += line.length + 1;
1125
- }
1126
- textarea.selectionStart = lineStart;
1127
- textarea.selectionEnd = lineEnd;
1128
- } else if (toWord && selectionStart === selectionEnd) {
1129
- let start = selectionStart;
1130
- let end = selectionEnd;
1131
- while (start > 0 && !/\s/.test(value[start - 1])) {
1132
- start--;
1133
- }
1134
- while (end < value.length && !/\s/.test(value[end])) {
1135
- end++;
1136
- }
1137
- textarea.selectionStart = start;
1138
- textarea.selectionEnd = end;
1139
- }
1140
- }
1141
- function toggleBold3(textarea) {
1142
- if (!textarea || textarea.disabled || textarea.readOnly)
1143
- return;
1144
- debugLog("toggleBold", "Starting");
1145
- debugSelection(textarea, "Before");
1146
- const style = mergeWithDefaults(FORMATS.bold);
1147
- const result = blockStyle(textarea, style);
1148
- debugResult(result);
1149
- insertText(textarea, result);
1150
- debugSelection(textarea, "After");
1151
- }
1152
- function toggleItalic3(textarea) {
1153
- if (!textarea || textarea.disabled || textarea.readOnly)
1154
- return;
1155
- const style = mergeWithDefaults(FORMATS.italic);
1156
- const result = blockStyle(textarea, style);
1157
- insertText(textarea, result);
1158
- }
1159
- function toggleCode2(textarea) {
1160
- if (!textarea || textarea.disabled || textarea.readOnly)
1161
- return;
1162
- const style = mergeWithDefaults(FORMATS.code);
1163
- const result = blockStyle(textarea, style);
1164
- insertText(textarea, result);
1165
- }
1166
- function insertLink3(textarea, options = {}) {
1167
- if (!textarea || textarea.disabled || textarea.readOnly)
1168
- return;
1169
- const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
1170
- let style = mergeWithDefaults(FORMATS.link);
1171
- const isURL = selectedText && selectedText.match(/^https?:\/\//);
1172
- if (isURL && !options.url) {
1173
- style.suffix = `](${selectedText})`;
1174
- style.replaceNext = "";
1175
- } else if (options.url) {
1176
- style.suffix = `](${options.url})`;
1177
- style.replaceNext = "";
1178
- }
1179
- if (options.text && !selectedText) {
1180
- const pos = textarea.selectionStart;
1181
- textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos);
1182
- textarea.selectionStart = pos;
1183
- textarea.selectionEnd = pos + options.text.length;
1184
- }
1185
- const result = blockStyle(textarea, style);
1186
- insertText(textarea, result);
1187
- }
1188
- function toggleBulletList3(textarea) {
1189
- if (!textarea || textarea.disabled || textarea.readOnly)
1190
- return;
1191
- const style = mergeWithDefaults(FORMATS.bulletList);
1192
- applyListStyle(textarea, style);
1193
- }
1194
- function toggleNumberedList3(textarea) {
1195
- if (!textarea || textarea.disabled || textarea.readOnly)
1196
- return;
1197
- const style = mergeWithDefaults(FORMATS.numberedList);
1198
- applyListStyle(textarea, style);
1199
- }
1200
- function toggleQuote2(textarea) {
1201
- if (!textarea || textarea.disabled || textarea.readOnly)
1202
- return;
1203
- debugLog("toggleQuote", "Starting");
1204
- debugSelection(textarea, "Initial");
1205
- const style = mergeWithDefaults(FORMATS.quote);
1206
- const result = applyLineOperation(
1207
- textarea,
1208
- (ta) => multilineStyle(ta, style),
1209
- { prefix: style.prefix }
1210
- );
1211
- debugResult(result);
1212
- insertText(textarea, result);
1213
- debugSelection(textarea, "Final");
1214
- }
1215
- function toggleTaskList2(textarea) {
1216
- if (!textarea || textarea.disabled || textarea.readOnly)
1217
- return;
1218
- const style = mergeWithDefaults(FORMATS.taskList);
1219
- const result = applyLineOperation(
1220
- textarea,
1221
- (ta) => multilineStyle(ta, style),
1222
- { prefix: style.prefix }
1223
- );
1224
- insertText(textarea, result);
1225
- }
1226
- function insertHeader(textarea, level = 1, toggle = false) {
1227
- if (!textarea || textarea.disabled || textarea.readOnly)
1228
- return;
1229
- if (level < 1 || level > 6)
1230
- level = 1;
1231
- debugLog("insertHeader", `============ START ============`);
1232
- debugLog("insertHeader", `Level: ${level}, Toggle: ${toggle}`);
1233
- debugLog("insertHeader", `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);
1234
- const headerKey = `header${level === 1 ? "1" : level}`;
1235
- const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1);
1236
- debugLog("insertHeader", `Style prefix: "${style.prefix}"`);
1237
- const value = textarea.value;
1238
- const originalStart = textarea.selectionStart;
1239
- const originalEnd = textarea.selectionEnd;
1240
- let lineStart = originalStart;
1241
- while (lineStart > 0 && value[lineStart - 1] !== "\n") {
1242
- lineStart--;
1243
- }
1244
- let lineEnd = originalEnd;
1245
- while (lineEnd < value.length && value[lineEnd] !== "\n") {
1246
- lineEnd++;
1247
- }
1248
- const currentLineContent = value.slice(lineStart, lineEnd);
1249
- debugLog("insertHeader", `Current line (before): "${currentLineContent}"`);
1250
- const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\s*/);
1251
- const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0;
1252
- const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0;
1253
- debugLog("insertHeader", `Existing header check:`);
1254
- debugLog("insertHeader", ` - Match: ${existingHeaderMatch ? `"${existingHeaderMatch[0]}"` : "none"}`);
1255
- debugLog("insertHeader", ` - Existing level: ${existingLevel}`);
1256
- debugLog("insertHeader", ` - Existing prefix length: ${existingPrefixLength}`);
1257
- debugLog("insertHeader", ` - Target level: ${level}`);
1258
- const shouldToggleOff = toggle && existingLevel === level;
1259
- debugLog("insertHeader", `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);
1260
- const result = applyLineOperation(
1261
- textarea,
1262
- (ta) => {
1263
- const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd);
1264
- debugLog("insertHeader", `Line in operation: "${currentLine}"`);
1265
- const cleanedLine = currentLine.replace(/^#{1,6}\s*/, "");
1266
- debugLog("insertHeader", `Cleaned line: "${cleanedLine}"`);
1267
- let newLine;
1268
- if (shouldToggleOff) {
1269
- debugLog("insertHeader", "ACTION: Toggling OFF - removing header");
1270
- newLine = cleanedLine;
1271
- } else if (existingLevel > 0) {
1272
- debugLog("insertHeader", `ACTION: Replacing H${existingLevel} with H${level}`);
1273
- newLine = style.prefix + cleanedLine;
1274
933
  } else {
1275
- debugLog("insertHeader", "ACTION: Adding new header");
1276
- newLine = style.prefix + cleanedLine;
1277
- }
1278
- debugLog("insertHeader", `New line: "${newLine}"`);
1279
- return {
1280
- text: newLine,
1281
- selectionStart: ta.selectionStart,
1282
- selectionEnd: ta.selectionEnd
1283
- };
1284
- },
1285
- {
1286
- prefix: style.prefix,
1287
- // Custom selection adjustment for headers
1288
- adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {
1289
- debugLog("insertHeader", `Adjusting selection:`);
1290
- debugLog("insertHeader", ` - isRemoving param: ${isRemoving}`);
1291
- debugLog("insertHeader", ` - shouldToggleOff: ${shouldToggleOff}`);
1292
- debugLog("insertHeader", ` - selStart: ${selStart}, selEnd: ${selEnd}`);
1293
- debugLog("insertHeader", ` - lineStartPos: ${lineStartPos}`);
1294
- if (shouldToggleOff) {
1295
- const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos);
1296
- debugLog("insertHeader", ` - Removing header, adjusting by -${existingPrefixLength}`);
934
+ if (isRemovingCurrent) {
935
+ const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex);
936
+ const prefixLength = prefixMatch ? prefixMatch[0].length : 0;
1297
937
  return {
1298
- start: adjustment,
1299
- end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)
938
+ start: Math.max(selStart - prefixLength, lineStart),
939
+ end: Math.max(selEnd - prefixLength, lineStart)
1300
940
  };
1301
- } else if (existingPrefixLength > 0) {
1302
- const prefixDiff = style.prefix.length - existingPrefixLength;
1303
- debugLog("insertHeader", ` - Replacing header, adjusting by ${prefixDiff}`);
941
+ } else if (hasOrderedList || hasUnorderedList) {
942
+ const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex);
943
+ const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0;
944
+ const newPrefixLength = style.unorderedList ? 2 : 3;
945
+ const adjustment = newPrefixLength - oldPrefixLength;
1304
946
  return {
1305
- start: selStart + prefixDiff,
1306
- end: selEnd + prefixDiff
947
+ start: selStart + adjustment,
948
+ end: selEnd + adjustment
1307
949
  };
1308
950
  } else {
1309
- debugLog("insertHeader", ` - Adding header, adjusting by +${style.prefix.length}`);
951
+ const prefixLength = style.unorderedList ? 2 : 3;
1310
952
  return {
1311
- start: selStart + style.prefix.length,
1312
- end: selEnd + style.prefix.length
953
+ start: selStart + prefixLength,
954
+ end: selEnd + prefixLength
1313
955
  };
1314
956
  }
1315
957
  }
1316
958
  }
1317
- );
1318
- debugLog("insertHeader", `Final result: text="${result.text}", cursor=${result.selectionStart}-${result.selectionEnd}`);
1319
- debugLog("insertHeader", `============ END ============`);
1320
- insertText(textarea, result);
1321
- }
1322
- function toggleH12(textarea) {
1323
- insertHeader(textarea, 1, true);
1324
- }
1325
- function toggleH22(textarea) {
1326
- insertHeader(textarea, 2, true);
1327
- }
1328
- function toggleH32(textarea) {
1329
- insertHeader(textarea, 3, true);
1330
- }
1331
- function getActiveFormats22(textarea) {
1332
- return getActiveFormats2(textarea);
1333
- }
1334
- function hasFormat2(textarea, format) {
1335
- return hasFormat(textarea, format);
1336
- }
1337
- function expandSelection2(textarea, options = {}) {
1338
- expandSelection(textarea, options);
1339
- }
1340
- function applyCustomFormat(textarea, format) {
1341
- if (!textarea || textarea.disabled || textarea.readOnly)
1342
- return;
1343
- const style = mergeWithDefaults(format);
1344
- let result;
1345
- if (style.multiline) {
1346
- const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
1347
- if (isMultipleLines(selectedText)) {
1348
- result = multilineStyle(textarea, style);
959
+ }
960
+ );
961
+ insertText(textarea, result);
962
+ }
963
+ function getActiveFormats(textarea) {
964
+ if (!textarea)
965
+ return [];
966
+ const formats = [];
967
+ const { selectionStart, selectionEnd, value } = textarea;
968
+ const lines = value.split("\n");
969
+ let lineStart = 0;
970
+ let currentLine = "";
971
+ for (const line of lines) {
972
+ if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {
973
+ currentLine = line;
974
+ break;
975
+ }
976
+ lineStart += line.length + 1;
977
+ }
978
+ if (currentLine.startsWith("- ")) {
979
+ if (currentLine.startsWith("- [ ] ") || currentLine.startsWith("- [x] ")) {
980
+ formats.push("task-list");
981
+ } else {
982
+ formats.push("bullet-list");
983
+ }
984
+ }
985
+ if (/^\d+\.\s/.test(currentLine)) {
986
+ formats.push("numbered-list");
987
+ }
988
+ if (currentLine.startsWith("> ")) {
989
+ formats.push("quote");
990
+ }
991
+ if (currentLine.startsWith("# "))
992
+ formats.push("header");
993
+ if (currentLine.startsWith("## "))
994
+ formats.push("header-2");
995
+ if (currentLine.startsWith("### "))
996
+ formats.push("header-3");
997
+ const lookBehind = Math.max(0, selectionStart - 10);
998
+ const lookAhead = Math.min(value.length, selectionEnd + 10);
999
+ const surrounding = value.slice(lookBehind, lookAhead);
1000
+ if (surrounding.includes("**")) {
1001
+ const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
1002
+ const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
1003
+ const lastOpenBold = beforeCursor.lastIndexOf("**");
1004
+ const nextCloseBold = afterCursor.indexOf("**");
1005
+ if (lastOpenBold !== -1 && nextCloseBold !== -1) {
1006
+ formats.push("bold");
1007
+ }
1008
+ }
1009
+ if (surrounding.includes("_")) {
1010
+ const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
1011
+ const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
1012
+ const lastOpenItalic = beforeCursor.lastIndexOf("_");
1013
+ const nextCloseItalic = afterCursor.indexOf("_");
1014
+ if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {
1015
+ formats.push("italic");
1016
+ }
1017
+ }
1018
+ if (surrounding.includes("`")) {
1019
+ const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
1020
+ const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
1021
+ if (beforeCursor.includes("`") && afterCursor.includes("`")) {
1022
+ formats.push("code");
1023
+ }
1024
+ }
1025
+ if (surrounding.includes("[") && surrounding.includes("]")) {
1026
+ const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
1027
+ const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
1028
+ const lastOpenBracket = beforeCursor.lastIndexOf("[");
1029
+ const nextCloseBracket = afterCursor.indexOf("]");
1030
+ if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {
1031
+ const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10);
1032
+ if (afterBracket.startsWith("(")) {
1033
+ formats.push("link");
1034
+ }
1035
+ }
1036
+ }
1037
+ return formats;
1038
+ }
1039
+ function toggleBold(textarea) {
1040
+ if (!textarea || textarea.disabled || textarea.readOnly)
1041
+ return;
1042
+ debugLog("toggleBold", "Starting");
1043
+ debugSelection(textarea, "Before");
1044
+ const style = mergeWithDefaults(FORMATS.bold);
1045
+ const result = blockStyle(textarea, style);
1046
+ debugResult(result);
1047
+ insertText(textarea, result);
1048
+ debugSelection(textarea, "After");
1049
+ }
1050
+ function toggleItalic(textarea) {
1051
+ if (!textarea || textarea.disabled || textarea.readOnly)
1052
+ return;
1053
+ const style = mergeWithDefaults(FORMATS.italic);
1054
+ const result = blockStyle(textarea, style);
1055
+ insertText(textarea, result);
1056
+ }
1057
+ function toggleCode(textarea) {
1058
+ if (!textarea || textarea.disabled || textarea.readOnly)
1059
+ return;
1060
+ const style = mergeWithDefaults(FORMATS.code);
1061
+ const result = blockStyle(textarea, style);
1062
+ insertText(textarea, result);
1063
+ }
1064
+ function insertLink(textarea, options = {}) {
1065
+ if (!textarea || textarea.disabled || textarea.readOnly)
1066
+ return;
1067
+ const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
1068
+ let style = mergeWithDefaults(FORMATS.link);
1069
+ const isURL = selectedText && selectedText.match(/^https?:\/\//);
1070
+ if (isURL && !options.url) {
1071
+ style.suffix = `](${selectedText})`;
1072
+ style.replaceNext = "";
1073
+ } else if (options.url) {
1074
+ style.suffix = `](${options.url})`;
1075
+ style.replaceNext = "";
1076
+ }
1077
+ if (options.text && !selectedText) {
1078
+ const pos = textarea.selectionStart;
1079
+ textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos);
1080
+ textarea.selectionStart = pos;
1081
+ textarea.selectionEnd = pos + options.text.length;
1082
+ }
1083
+ const result = blockStyle(textarea, style);
1084
+ insertText(textarea, result);
1085
+ }
1086
+ function toggleBulletList(textarea) {
1087
+ if (!textarea || textarea.disabled || textarea.readOnly)
1088
+ return;
1089
+ const style = mergeWithDefaults(FORMATS.bulletList);
1090
+ applyListStyle(textarea, style);
1091
+ }
1092
+ function toggleNumberedList(textarea) {
1093
+ if (!textarea || textarea.disabled || textarea.readOnly)
1094
+ return;
1095
+ const style = mergeWithDefaults(FORMATS.numberedList);
1096
+ applyListStyle(textarea, style);
1097
+ }
1098
+ function toggleQuote(textarea) {
1099
+ if (!textarea || textarea.disabled || textarea.readOnly)
1100
+ return;
1101
+ debugLog("toggleQuote", "Starting");
1102
+ debugSelection(textarea, "Initial");
1103
+ const style = mergeWithDefaults(FORMATS.quote);
1104
+ const result = applyLineOperation(
1105
+ textarea,
1106
+ (ta) => multilineStyle(ta, style),
1107
+ { prefix: style.prefix }
1108
+ );
1109
+ debugResult(result);
1110
+ insertText(textarea, result);
1111
+ debugSelection(textarea, "Final");
1112
+ }
1113
+ function toggleTaskList(textarea) {
1114
+ if (!textarea || textarea.disabled || textarea.readOnly)
1115
+ return;
1116
+ const style = mergeWithDefaults(FORMATS.taskList);
1117
+ const result = applyLineOperation(
1118
+ textarea,
1119
+ (ta) => multilineStyle(ta, style),
1120
+ { prefix: style.prefix }
1121
+ );
1122
+ insertText(textarea, result);
1123
+ }
1124
+ function insertHeader(textarea, level = 1, toggle = false) {
1125
+ if (!textarea || textarea.disabled || textarea.readOnly)
1126
+ return;
1127
+ if (level < 1 || level > 6)
1128
+ level = 1;
1129
+ debugLog("insertHeader", `============ START ============`);
1130
+ debugLog("insertHeader", `Level: ${level}, Toggle: ${toggle}`);
1131
+ debugLog("insertHeader", `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);
1132
+ const headerKey = `header${level === 1 ? "1" : level}`;
1133
+ const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1);
1134
+ debugLog("insertHeader", `Style prefix: "${style.prefix}"`);
1135
+ const value = textarea.value;
1136
+ const originalStart = textarea.selectionStart;
1137
+ const originalEnd = textarea.selectionEnd;
1138
+ let lineStart = originalStart;
1139
+ while (lineStart > 0 && value[lineStart - 1] !== "\n") {
1140
+ lineStart--;
1141
+ }
1142
+ let lineEnd = originalEnd;
1143
+ while (lineEnd < value.length && value[lineEnd] !== "\n") {
1144
+ lineEnd++;
1145
+ }
1146
+ const currentLineContent = value.slice(lineStart, lineEnd);
1147
+ debugLog("insertHeader", `Current line (before): "${currentLineContent}"`);
1148
+ const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\s*/);
1149
+ const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0;
1150
+ const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0;
1151
+ debugLog("insertHeader", `Existing header check:`);
1152
+ debugLog("insertHeader", ` - Match: ${existingHeaderMatch ? `"${existingHeaderMatch[0]}"` : "none"}`);
1153
+ debugLog("insertHeader", ` - Existing level: ${existingLevel}`);
1154
+ debugLog("insertHeader", ` - Existing prefix length: ${existingPrefixLength}`);
1155
+ debugLog("insertHeader", ` - Target level: ${level}`);
1156
+ const shouldToggleOff = toggle && existingLevel === level;
1157
+ debugLog("insertHeader", `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);
1158
+ const result = applyLineOperation(
1159
+ textarea,
1160
+ (ta) => {
1161
+ const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd);
1162
+ debugLog("insertHeader", `Line in operation: "${currentLine}"`);
1163
+ const cleanedLine = currentLine.replace(/^#{1,6}\s*/, "");
1164
+ debugLog("insertHeader", `Cleaned line: "${cleanedLine}"`);
1165
+ let newLine;
1166
+ if (shouldToggleOff) {
1167
+ debugLog("insertHeader", "ACTION: Toggling OFF - removing header");
1168
+ newLine = cleanedLine;
1169
+ } else if (existingLevel > 0) {
1170
+ debugLog("insertHeader", `ACTION: Replacing H${existingLevel} with H${level}`);
1171
+ newLine = style.prefix + cleanedLine;
1349
1172
  } else {
1350
- result = blockStyle(textarea, style);
1173
+ debugLog("insertHeader", "ACTION: Adding new header");
1174
+ newLine = style.prefix + cleanedLine;
1175
+ }
1176
+ debugLog("insertHeader", `New line: "${newLine}"`);
1177
+ return {
1178
+ text: newLine,
1179
+ selectionStart: ta.selectionStart,
1180
+ selectionEnd: ta.selectionEnd
1181
+ };
1182
+ },
1183
+ {
1184
+ prefix: style.prefix,
1185
+ // Custom selection adjustment for headers
1186
+ adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {
1187
+ debugLog("insertHeader", `Adjusting selection:`);
1188
+ debugLog("insertHeader", ` - isRemoving param: ${isRemoving}`);
1189
+ debugLog("insertHeader", ` - shouldToggleOff: ${shouldToggleOff}`);
1190
+ debugLog("insertHeader", ` - selStart: ${selStart}, selEnd: ${selEnd}`);
1191
+ debugLog("insertHeader", ` - lineStartPos: ${lineStartPos}`);
1192
+ if (shouldToggleOff) {
1193
+ const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos);
1194
+ debugLog("insertHeader", ` - Removing header, adjusting by -${existingPrefixLength}`);
1195
+ return {
1196
+ start: adjustment,
1197
+ end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)
1198
+ };
1199
+ } else if (existingPrefixLength > 0) {
1200
+ const prefixDiff = style.prefix.length - existingPrefixLength;
1201
+ debugLog("insertHeader", ` - Replacing header, adjusting by ${prefixDiff}`);
1202
+ return {
1203
+ start: selStart + prefixDiff,
1204
+ end: selEnd + prefixDiff
1205
+ };
1206
+ } else {
1207
+ debugLog("insertHeader", ` - Adding header, adjusting by +${style.prefix.length}`);
1208
+ return {
1209
+ start: selStart + style.prefix.length,
1210
+ end: selEnd + style.prefix.length
1211
+ };
1212
+ }
1351
1213
  }
1352
- } else {
1353
- result = blockStyle(textarea, style);
1354
- }
1355
- insertText(textarea, result);
1356
- }
1357
- var src_default = {
1358
- toggleBold: toggleBold3,
1359
- toggleItalic: toggleItalic3,
1360
- toggleCode: toggleCode2,
1361
- insertLink: insertLink3,
1362
- toggleBulletList: toggleBulletList3,
1363
- toggleNumberedList: toggleNumberedList3,
1364
- toggleQuote: toggleQuote2,
1365
- toggleTaskList: toggleTaskList2,
1366
- insertHeader,
1367
- toggleH1: toggleH12,
1368
- toggleH2: toggleH22,
1369
- toggleH3: toggleH32,
1370
- getActiveFormats: getActiveFormats22,
1371
- hasFormat: hasFormat2,
1372
- expandSelection: expandSelection2,
1373
- applyCustomFormat,
1374
- preserveSelection,
1375
- setUndoMethod,
1376
- setDebugMode,
1377
- getDebugMode
1378
- };
1379
- return __toCommonJS2(src_exports);
1380
- })();
1214
+ }
1215
+ );
1216
+ debugLog("insertHeader", `Final result: text="${result.text}", cursor=${result.selectionStart}-${result.selectionEnd}`);
1217
+ debugLog("insertHeader", `============ END ============`);
1218
+ insertText(textarea, result);
1219
+ }
1220
+ function toggleH1(textarea) {
1221
+ insertHeader(textarea, 1, true);
1222
+ }
1223
+ function toggleH2(textarea) {
1224
+ insertHeader(textarea, 2, true);
1225
+ }
1226
+ function toggleH3(textarea) {
1227
+ insertHeader(textarea, 3, true);
1228
+ }
1229
+ function getActiveFormats2(textarea) {
1230
+ return getActiveFormats(textarea);
1231
+ }
1381
1232
 
1382
1233
  // src/shortcuts.js
1383
1234
  var ShortcutsManager = class {
@@ -1446,19 +1297,19 @@ var ShortcutsManager = class {
1446
1297
  try {
1447
1298
  switch (action) {
1448
1299
  case "toggleBold":
1449
- (void 0)(textarea);
1300
+ toggleBold(textarea);
1450
1301
  break;
1451
1302
  case "toggleItalic":
1452
- (void 0)(textarea);
1303
+ toggleItalic(textarea);
1453
1304
  break;
1454
1305
  case "insertLink":
1455
- (void 0)(textarea);
1306
+ insertLink(textarea);
1456
1307
  break;
1457
1308
  case "toggleBulletList":
1458
- (void 0)(textarea);
1309
+ toggleBulletList(textarea);
1459
1310
  break;
1460
1311
  case "toggleNumberedList":
1461
- (void 0)(textarea);
1312
+ toggleNumberedList(textarea);
1462
1313
  break;
1463
1314
  }
1464
1315
  textarea.dispatchEvent(new Event("input", { bubbles: true }));
@@ -2546,37 +2397,37 @@ var Toolbar = class {
2546
2397
  try {
2547
2398
  switch (action) {
2548
2399
  case "toggleBold":
2549
- (void 0)(textarea);
2400
+ toggleBold(textarea);
2550
2401
  break;
2551
2402
  case "toggleItalic":
2552
- (void 0)(textarea);
2403
+ toggleItalic(textarea);
2553
2404
  break;
2554
2405
  case "insertH1":
2555
- (void 0)(textarea);
2406
+ toggleH1(textarea);
2556
2407
  break;
2557
2408
  case "insertH2":
2558
- (void 0)(textarea);
2409
+ toggleH2(textarea);
2559
2410
  break;
2560
2411
  case "insertH3":
2561
- (void 0)(textarea);
2412
+ toggleH3(textarea);
2562
2413
  break;
2563
2414
  case "insertLink":
2564
- (void 0)(textarea);
2415
+ insertLink(textarea);
2565
2416
  break;
2566
2417
  case "toggleCode":
2567
- (void 0)(textarea);
2418
+ toggleCode(textarea);
2568
2419
  break;
2569
2420
  case "toggleBulletList":
2570
- (void 0)(textarea);
2421
+ toggleBulletList(textarea);
2571
2422
  break;
2572
2423
  case "toggleNumberedList":
2573
- (void 0)(textarea);
2424
+ toggleNumberedList(textarea);
2574
2425
  break;
2575
2426
  case "toggleQuote":
2576
- (void 0)(textarea);
2427
+ toggleQuote(textarea);
2577
2428
  break;
2578
2429
  case "toggleTaskList":
2579
- (void 0)(textarea);
2430
+ toggleTaskList(textarea);
2580
2431
  break;
2581
2432
  case "toggle-plain":
2582
2433
  const isPlain = this.editor.container.classList.contains("plain-mode");
@@ -2596,7 +2447,7 @@ var Toolbar = class {
2596
2447
  if (!textarea)
2597
2448
  return;
2598
2449
  try {
2599
- const activeFormats = (void 0)(textarea);
2450
+ const activeFormats = getActiveFormats2(textarea);
2600
2451
  Object.entries(this.buttons).forEach(([name, button]) => {
2601
2452
  let isActive = false;
2602
2453
  switch (name) {
@@ -3272,21 +3123,35 @@ var _OverType = class _OverType {
3272
3123
  const after = value.substring(end);
3273
3124
  const lines = selection.split("\n");
3274
3125
  const outdented = lines.map((line) => line.replace(/^ /, "")).join("\n");
3275
- this.textarea.value = before + outdented + after;
3276
- this.textarea.selectionStart = start;
3277
- this.textarea.selectionEnd = start + outdented.length;
3126
+ if (document.execCommand) {
3127
+ this.textarea.setSelectionRange(start, end);
3128
+ document.execCommand("insertText", false, outdented);
3129
+ } else {
3130
+ this.textarea.value = before + outdented + after;
3131
+ this.textarea.selectionStart = start;
3132
+ this.textarea.selectionEnd = start + outdented.length;
3133
+ }
3278
3134
  } else if (start !== end) {
3279
3135
  const before = value.substring(0, start);
3280
3136
  const selection = value.substring(start, end);
3281
3137
  const after = value.substring(end);
3282
3138
  const lines = selection.split("\n");
3283
3139
  const indented = lines.map((line) => " " + line).join("\n");
3284
- this.textarea.value = before + indented + after;
3285
- this.textarea.selectionStart = start;
3286
- this.textarea.selectionEnd = start + indented.length;
3140
+ if (document.execCommand) {
3141
+ this.textarea.setSelectionRange(start, end);
3142
+ document.execCommand("insertText", false, indented);
3143
+ } else {
3144
+ this.textarea.value = before + indented + after;
3145
+ this.textarea.selectionStart = start;
3146
+ this.textarea.selectionEnd = start + indented.length;
3147
+ }
3287
3148
  } else {
3288
- this.textarea.value = value.substring(0, start) + " " + value.substring(end);
3289
- this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;
3149
+ if (document.execCommand) {
3150
+ document.execCommand("insertText", false, " ");
3151
+ } else {
3152
+ this.textarea.value = value.substring(0, start) + " " + value.substring(end);
3153
+ this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;
3154
+ }
3290
3155
  }
3291
3156
  this.textarea.dispatchEvent(new Event("input", { bubbles: true }));
3292
3157
  return;