overtype 1.2.0 → 1.2.2

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.2
3
3
  * A lightweight markdown editor library with perfect WYSIWYG alignment
4
4
  * @license MIT
5
5
  * @author Demo User
@@ -258,11 +258,22 @@ var MarkdownParser = class {
258
258
  static parse(text, activeLine = -1, showActiveLineRaw = false) {
259
259
  this.resetLinkIndex();
260
260
  const lines = text.split("\n");
261
+ let inCodeBlock = false;
261
262
  const parsedLines = lines.map((line, index) => {
262
263
  if (showActiveLineRaw && index === activeLine) {
263
264
  const content = this.escapeHtml(line) || " ";
264
265
  return `<div class="raw-line">${content}</div>`;
265
266
  }
267
+ const codeFenceRegex = /^```[^`]*$/;
268
+ if (codeFenceRegex.test(line)) {
269
+ inCodeBlock = !inCodeBlock;
270
+ return this.parseLine(line);
271
+ }
272
+ if (inCodeBlock) {
273
+ const escaped = this.escapeHtml(line);
274
+ const indented = this.preserveIndentation(escaped, line);
275
+ return `<div>${indented || "&nbsp;"}</div>`;
276
+ }
266
277
  return this.parseLine(line);
267
278
  });
268
279
  const html = parsedLines.join("");
@@ -302,23 +313,22 @@ var MarkdownParser = class {
302
313
  if (lang) {
303
314
  codeElement.className = `language-${lang}`;
304
315
  }
305
- container.insertBefore(currentCodeBlock, child);
306
- child.remove();
316
+ container.insertBefore(currentCodeBlock, child.nextSibling);
317
+ currentCodeBlock._codeElement = codeElement;
307
318
  continue;
308
319
  } else {
309
320
  inCodeBlock = false;
310
321
  currentCodeBlock = null;
311
- child.remove();
312
322
  continue;
313
323
  }
314
324
  }
315
325
  }
316
326
  if (inCodeBlock && currentCodeBlock && child.tagName === "DIV" && !child.querySelector(".code-fence")) {
317
- const codeElement = currentCodeBlock.querySelector("code");
327
+ const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector("code");
318
328
  if (codeElement.textContent.length > 0) {
319
329
  codeElement.textContent += "\n";
320
330
  }
321
- const lineText = child.innerHTML.replace(/&nbsp;/g, " ").replace(/<[^>]*>/g, "");
331
+ const lineText = child.textContent.replace(/\u00A0/g, " ");
322
332
  codeElement.textContent += lineText;
323
333
  child.remove();
324
334
  continue;
@@ -371,15 +381,19 @@ var MarkdownParser = class {
371
381
  }
372
382
  return match;
373
383
  });
374
- const codeBlockRegex = /<div><span class="code-fence">```([^<]*)<\/span><\/div>(.*?)<div><span class="code-fence">```<\/span><\/div>/gs;
375
- processed = processed.replace(codeBlockRegex, (match, lang, content) => {
384
+ const codeBlockRegex = /<div><span class="code-fence">(```[^<]*)<\/span><\/div>(.*?)<div><span class="code-fence">(```)<\/span><\/div>/gs;
385
+ processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {
376
386
  const lines = content.match(/<div>(.*?)<\/div>/gs) || [];
377
387
  const codeContent = lines.map((line) => {
378
- const text = line.replace(/<div>(.*?)<\/div>/s, "$1").replace(/&nbsp;/g, " ").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&amp;/g, "&");
388
+ const text = line.replace(/<div>(.*?)<\/div>/s, "$1").replace(/&nbsp;/g, " ");
379
389
  return text;
380
390
  }).join("\n");
381
- const langClass = lang ? ` class="language-${lang.trim()}"` : "";
382
- return `<pre class="code-block"><code${langClass}>${this.escapeHtml(codeContent)}</code></pre>`;
391
+ const lang = openFence.slice(3).trim();
392
+ const langClass = lang ? ` class="language-${lang}"` : "";
393
+ let result = `<div><span class="code-fence">${openFence}</span></div>`;
394
+ result += `<pre class="code-block"><code${langClass}>${codeContent}</code></pre>`;
395
+ result += `<div><span class="code-fence">${closeFence}</span></div>`;
396
+ return result;
383
397
  });
384
398
  return processed;
385
399
  }
@@ -387,997 +401,848 @@ var MarkdownParser = class {
387
401
  // Track link index for anchor naming
388
402
  __publicField(MarkdownParser, "linkIndex", 0);
389
403
 
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))
404
+ // node_modules/markdown-actions/dist/markdown-actions.esm.js
405
+ var __defProp2 = Object.defineProperty;
406
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
407
+ var __hasOwnProp2 = Object.prototype.hasOwnProperty;
408
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
409
+ var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
410
+ var __spreadValues = (a, b) => {
411
+ for (var prop in b || (b = {}))
412
+ if (__hasOwnProp2.call(b, prop))
413
+ __defNormalProp2(a, prop, b[prop]);
414
+ if (__getOwnPropSymbols)
415
+ for (var prop of __getOwnPropSymbols(b)) {
416
+ if (__propIsEnum.call(b, prop))
402
417
  __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
418
  }
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: "###### " }
419
+ return a;
420
+ };
421
+ var FORMATS = {
422
+ bold: {
423
+ prefix: "**",
424
+ suffix: "**",
425
+ trimFirst: true
426
+ },
427
+ italic: {
428
+ prefix: "_",
429
+ suffix: "_",
430
+ trimFirst: true
431
+ },
432
+ code: {
433
+ prefix: "`",
434
+ suffix: "`",
435
+ blockPrefix: "```",
436
+ blockSuffix: "```"
437
+ },
438
+ link: {
439
+ prefix: "[",
440
+ suffix: "](url)",
441
+ replaceNext: "url",
442
+ scanFor: "https?://"
443
+ },
444
+ bulletList: {
445
+ prefix: "- ",
446
+ multiline: true,
447
+ unorderedList: true
448
+ },
449
+ numberedList: {
450
+ prefix: "1. ",
451
+ multiline: true,
452
+ orderedList: true
453
+ },
454
+ quote: {
455
+ prefix: "> ",
456
+ multiline: true,
457
+ surroundWithNewlines: true
458
+ },
459
+ taskList: {
460
+ prefix: "- [ ] ",
461
+ multiline: true,
462
+ surroundWithNewlines: true
463
+ },
464
+ header1: { prefix: "# " },
465
+ header2: { prefix: "## " },
466
+ header3: { prefix: "### " },
467
+ header4: { prefix: "#### " },
468
+ header5: { prefix: "##### " },
469
+ header6: { prefix: "###### " }
470
+ };
471
+ function getDefaultStyle() {
472
+ return {
473
+ prefix: "",
474
+ suffix: "",
475
+ blockPrefix: "",
476
+ blockSuffix: "",
477
+ multiline: false,
478
+ replaceNext: "",
479
+ prefixSpace: false,
480
+ scanFor: "",
481
+ surroundWithNewlines: false,
482
+ orderedList: false,
483
+ unorderedList: false,
484
+ trimFirst: false
496
485
  };
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);
486
+ }
487
+ function mergeWithDefaults(format) {
488
+ return __spreadValues(__spreadValues({}, getDefaultStyle()), format);
489
+ }
490
+ var debugMode = false;
491
+ function getDebugMode() {
492
+ return debugMode;
493
+ }
494
+ function debugLog(funcName, message, data) {
495
+ if (!debugMode)
496
+ return;
497
+ console.group(`\u{1F50D} ${funcName}`);
498
+ console.log(message);
499
+ if (data) {
500
+ console.log("Data:", data);
501
+ }
502
+ console.groupEnd();
503
+ }
504
+ function debugSelection(textarea, label) {
505
+ if (!debugMode)
506
+ return;
507
+ const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
508
+ console.group(`\u{1F4CD} Selection: ${label}`);
509
+ console.log("Position:", `${textarea.selectionStart}-${textarea.selectionEnd}`);
510
+ console.log("Selected text:", JSON.stringify(selected));
511
+ console.log("Length:", selected.length);
512
+ const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);
513
+ const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));
514
+ console.log("Context:", JSON.stringify(before) + "[SELECTION]" + JSON.stringify(after));
515
+ console.groupEnd();
516
+ }
517
+ function debugResult(result) {
518
+ if (!debugMode)
519
+ return;
520
+ console.group("\u{1F4DD} Result");
521
+ console.log("Text to insert:", JSON.stringify(result.text));
522
+ console.log("New selection:", `${result.selectionStart}-${result.selectionEnd}`);
523
+ console.groupEnd();
524
+ }
525
+ var canInsertText = null;
526
+ function insertText(textarea, { text, selectionStart, selectionEnd }) {
527
+ const debugMode2 = getDebugMode();
528
+ if (debugMode2) {
529
+ console.group("\u{1F527} insertText");
530
+ console.log("Current selection:", `${textarea.selectionStart}-${textarea.selectionEnd}`);
531
+ console.log("Text to insert:", JSON.stringify(text));
532
+ console.log("New selection to set:", selectionStart, "-", selectionEnd);
533
+ }
534
+ textarea.focus();
535
+ const originalSelectionStart = textarea.selectionStart;
536
+ const originalSelectionEnd = textarea.selectionEnd;
537
+ const before = textarea.value.slice(0, originalSelectionStart);
538
+ const after = textarea.value.slice(originalSelectionEnd);
539
+ if (debugMode2) {
540
+ console.log("Before text (last 20):", JSON.stringify(before.slice(-20)));
541
+ console.log("After text (first 20):", JSON.stringify(after.slice(0, 20)));
542
+ console.log("Selected text being replaced:", JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));
543
+ }
544
+ const originalValue = textarea.value;
545
+ const hasSelection = originalSelectionStart !== originalSelectionEnd;
546
+ if (canInsertText === null || canInsertText === true) {
547
+ textarea.contentEditable = "true";
548
+ try {
549
+ canInsertText = document.execCommand("insertText", false, text);
550
+ if (debugMode2)
551
+ console.log("execCommand returned:", canInsertText, "for text with", text.split("\n").length, "lines");
552
+ } catch (error) {
553
+ canInsertText = false;
554
+ if (debugMode2)
555
+ console.log("execCommand threw error:", error);
530
556
  }
531
- console.groupEnd();
557
+ textarea.contentEditable = "false";
532
558
  }
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();
545
- }
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();
559
+ if (debugMode2) {
560
+ console.log("canInsertText before:", canInsertText);
561
+ console.log("execCommand result:", canInsertText);
553
562
  }
554
- var canInsertText = null;
555
- function insertText(textarea, { text, selectionStart, selectionEnd }) {
556
- const debugMode2 = getDebugMode();
557
- 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);
562
- }
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
- }
563
+ if (canInsertText) {
564
+ const expectedValue = before + text + after;
565
+ const actualValue = textarea.value;
588
566
  if (debugMode2) {
589
- console.log("canInsertText before:", canInsertText);
590
- console.log("execCommand result:", canInsertText);
567
+ console.log("Expected length:", expectedValue.length);
568
+ console.log("Actual length:", actualValue.length);
591
569
  }
592
- if (canInsertText) {
593
- const expectedValue = before + text + after;
594
- const actualValue = textarea.value;
570
+ if (actualValue !== expectedValue) {
595
571
  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
- }
572
+ console.log("execCommand changed the value but not as expected");
573
+ console.log("Expected:", JSON.stringify(expectedValue.slice(0, 100)));
574
+ console.log("Actual:", JSON.stringify(actualValue.slice(0, 100)));
605
575
  }
606
576
  }
607
- if (!canInsertText) {
577
+ }
578
+ if (!canInsertText) {
579
+ if (debugMode2)
580
+ console.log("Using manual insertion");
581
+ if (textarea.value === originalValue) {
608
582
  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");
583
+ console.log("Value unchanged, doing manual replacement");
584
+ try {
585
+ document.execCommand("ms-beginUndoUnit");
586
+ } catch (e) {
626
587
  }
627
- }
628
- if (debugMode2)
629
- console.log("Setting selection range:", selectionStart, selectionEnd);
630
- if (selectionStart != null && selectionEnd != null) {
631
- textarea.setSelectionRange(selectionStart, selectionEnd);
588
+ textarea.value = before + text + after;
589
+ try {
590
+ document.execCommand("ms-endUndoUnit");
591
+ } catch (e) {
592
+ }
593
+ textarea.dispatchEvent(new CustomEvent("input", { bubbles: true, cancelable: true }));
632
594
  } 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;
595
+ if (debugMode2)
596
+ console.log("Value was changed by execCommand, skipping manual insertion");
651
597
  }
652
598
  }
653
- function isMultipleLines(string) {
654
- return string.trim().split("\n").length > 1;
599
+ if (debugMode2)
600
+ console.log("Setting selection range:", selectionStart, selectionEnd);
601
+ if (selectionStart != null && selectionEnd != null) {
602
+ textarea.setSelectionRange(selectionStart, selectionEnd);
603
+ } else {
604
+ textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd);
655
605
  }
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;
606
+ if (debugMode2) {
607
+ console.log("Final value length:", textarea.value.length);
608
+ console.groupEnd();
662
609
  }
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;
610
+ }
611
+ function isMultipleLines(string) {
612
+ return string.trim().split("\n").length > 1;
613
+ }
614
+ function wordSelectionStart(text, i) {
615
+ let index = i;
616
+ while (text[index] && text[index - 1] != null && !text[index - 1].match(/\s/)) {
617
+ index--;
670
618
  }
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
- }
619
+ return index;
620
+ }
621
+ function wordSelectionEnd(text, i, multiline) {
622
+ let index = i;
623
+ const breakpoint = multiline ? /\n/ : /\s/;
624
+ while (text[index] && !text[index].match(breakpoint)) {
625
+ index++;
688
626
  }
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;
627
+ return index;
628
+ }
629
+ function expandSelectionToLine(textarea) {
630
+ const lines = textarea.value.split("\n");
631
+ let counter = 0;
632
+ for (let index = 0; index < lines.length; index++) {
633
+ const lineLength = lines[index].length + 1;
634
+ if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {
635
+ textarea.selectionStart = counter;
636
+ }
637
+ if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {
638
+ if (index === lines.length - 1) {
639
+ textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length);
640
+ } else {
641
+ textarea.selectionEnd = counter + lineLength - 1;
701
642
  }
702
643
  }
703
- return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
644
+ counter += lineLength;
704
645
  }
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);
646
+ }
647
+ function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {
648
+ if (textarea.selectionStart === textarea.selectionEnd) {
649
+ textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart);
650
+ textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline);
651
+ } else {
652
+ const expandedSelectionStart = textarea.selectionStart - prefixToUse.length;
653
+ const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length;
654
+ const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse;
655
+ const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse;
656
+ if (beginsWithPrefix && endsWithSuffix) {
657
+ textarea.selectionStart = expandedSelectionStart;
658
+ textarea.selectionEnd = expandedSelectionEnd;
659
+ }
660
+ }
661
+ return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
662
+ }
663
+ function newlinesToSurroundSelectedText(textarea) {
664
+ const beforeSelection = textarea.value.slice(0, textarea.selectionStart);
665
+ const afterSelection = textarea.value.slice(textarea.selectionEnd);
666
+ const breaksBefore = beforeSelection.match(/\n*$/);
667
+ const breaksAfter = afterSelection.match(/^\n*/);
668
+ const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0;
669
+ const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0;
670
+ let newlinesToAppend = "";
671
+ let newlinesToPrepend = "";
672
+ if (beforeSelection.match(/\S/) && newlinesBeforeSelection < 2) {
673
+ newlinesToAppend = "\n".repeat(2 - newlinesBeforeSelection);
674
+ }
675
+ if (afterSelection.match(/\S/) && newlinesAfterSelection < 2) {
676
+ newlinesToPrepend = "\n".repeat(2 - newlinesAfterSelection);
677
+ }
678
+ return { newlinesToAppend, newlinesToPrepend };
679
+ }
680
+ function applyLineOperation(textarea, operation, options = {}) {
681
+ const originalStart = textarea.selectionStart;
682
+ const originalEnd = textarea.selectionEnd;
683
+ const noInitialSelection = originalStart === originalEnd;
684
+ const value = textarea.value;
685
+ let lineStart = originalStart;
686
+ while (lineStart > 0 && value[lineStart - 1] !== "\n") {
687
+ lineStart--;
688
+ }
689
+ if (noInitialSelection) {
690
+ let lineEnd = originalStart;
691
+ while (lineEnd < value.length && value[lineEnd] !== "\n") {
692
+ lineEnd++;
719
693
  }
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;
694
+ textarea.selectionStart = lineStart;
695
+ textarea.selectionEnd = lineEnd;
696
+ } else {
697
+ expandSelectionToLine(textarea);
730
698
  }
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
- }
699
+ const result = operation(textarea);
700
+ if (options.adjustSelection) {
701
+ const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
702
+ const isRemoving = selectedText.startsWith(options.prefix);
703
+ const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart);
704
+ result.selectionStart = adjusted.start;
705
+ result.selectionEnd = adjusted.end;
706
+ } else if (options.prefix) {
707
+ const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
708
+ const isRemoving = selectedText.startsWith(options.prefix);
740
709
  if (noInitialSelection) {
741
- let lineEnd = originalStart;
742
- while (lineEnd < value.length && value[lineEnd] !== "\n") {
743
- lineEnd++;
710
+ if (isRemoving) {
711
+ result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart);
712
+ result.selectionEnd = result.selectionStart;
713
+ } else {
714
+ result.selectionStart = originalStart + options.prefix.length;
715
+ result.selectionEnd = result.selectionStart;
744
716
  }
745
- textarea.selectionStart = lineStart;
746
- textarea.selectionEnd = lineEnd;
747
717
  } 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
- }
718
+ if (isRemoving) {
719
+ result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart);
720
+ result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart);
768
721
  } 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
- }
722
+ result.selectionStart = originalStart + options.prefix.length;
723
+ result.selectionEnd = originalEnd + options.prefix.length;
776
724
  }
777
725
  }
778
- return result;
779
726
  }
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}
727
+ return result;
728
+ }
729
+ function blockStyle(textarea, style) {
730
+ let newlinesToAppend;
731
+ let newlinesToPrepend;
732
+ const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style;
733
+ const originalSelectionStart = textarea.selectionStart;
734
+ const originalSelectionEnd = textarea.selectionEnd;
735
+ let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
736
+ let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}
788
737
  ` : prefix;
789
- let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `
738
+ let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `
790
739
  ${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 };
740
+ if (prefixSpace) {
741
+ const beforeSelection = textarea.value[textarea.selectionStart - 1];
742
+ if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\s/)) {
743
+ prefixToUse = ` ${prefixToUse}`;
744
+ }
745
+ }
746
+ selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline);
747
+ let selectionStart = textarea.selectionStart;
748
+ let selectionEnd = textarea.selectionEnd;
749
+ const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0;
750
+ if (surroundWithNewlines) {
751
+ const ref = newlinesToSurroundSelectedText(textarea);
752
+ newlinesToAppend = ref.newlinesToAppend;
753
+ newlinesToPrepend = ref.newlinesToPrepend;
754
+ prefixToUse = newlinesToAppend + prefix;
755
+ suffixToUse += newlinesToPrepend;
756
+ }
757
+ if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {
758
+ const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length);
759
+ if (originalSelectionStart === originalSelectionEnd) {
760
+ let position = originalSelectionStart - prefixToUse.length;
761
+ position = Math.max(position, selectionStart);
762
+ position = Math.min(position, selectionStart + replacementText.length);
763
+ selectionStart = selectionEnd = position;
837
764
  } 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
- }
765
+ selectionEnd = selectionStart + replacementText.length;
766
+ }
767
+ return { text: replacementText, selectionStart, selectionEnd };
768
+ } else if (!hasReplaceNext) {
769
+ let replacementText = prefixToUse + selectedText + suffixToUse;
770
+ selectionStart = originalSelectionStart + prefixToUse.length;
771
+ selectionEnd = originalSelectionEnd + prefixToUse.length;
772
+ const whitespaceEdges = selectedText.match(/^\s*|\s*$/g);
773
+ if (trimFirst && whitespaceEdges) {
774
+ const leadingWhitespace = whitespaceEdges[0] || "";
775
+ const trailingWhitespace = whitespaceEdges[1] || "";
776
+ replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace;
777
+ selectionStart += leadingWhitespace.length;
778
+ selectionEnd -= trailingWhitespace.length;
779
+ }
780
+ return { text: replacementText, selectionStart, selectionEnd };
781
+ } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {
782
+ suffixToUse = suffixToUse.replace(replaceNext, selectedText);
783
+ const replacementText = prefixToUse + suffixToUse;
784
+ selectionStart = selectionEnd = selectionStart + prefixToUse.length;
785
+ return { text: replacementText, selectionStart, selectionEnd };
786
+ } else {
787
+ const replacementText = prefixToUse + selectedText + suffixToUse;
788
+ selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext);
789
+ selectionEnd = selectionStart + replaceNext.length;
790
+ return { text: replacementText, selectionStart, selectionEnd };
843
791
  }
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");
792
+ }
793
+ function multilineStyle(textarea, style) {
794
+ const { prefix, suffix, surroundWithNewlines } = style;
795
+ let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
796
+ let selectionStart = textarea.selectionStart;
797
+ let selectionEnd = textarea.selectionEnd;
798
+ const lines = text.split("\n");
799
+ const undoStyle = lines.every((line) => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)));
800
+ if (undoStyle) {
801
+ text = lines.map((line) => {
802
+ let result = line.slice(prefix.length);
803
+ if (suffix) {
804
+ result = result.slice(0, result.length - suffix.length);
805
+ }
806
+ return result;
807
+ }).join("\n");
808
+ selectionEnd = selectionStart + text.length;
809
+ } else {
810
+ text = lines.map((line) => prefix + line + (suffix || "")).join("\n");
811
+ if (surroundWithNewlines) {
812
+ const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea);
813
+ selectionStart += newlinesToAppend.length;
859
814
  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
- }
868
- }
869
- return { text, selectionStart, selectionEnd };
870
- }
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, ""));
815
+ text = newlinesToAppend + text + newlinesToPrepend;
878
816
  }
879
- return {
880
- text: result.join("\n"),
881
- processed: shouldUndoOrderedList
882
- };
883
817
  }
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
- };
818
+ return { text, selectionStart, selectionEnd };
819
+ }
820
+ function undoOrderedListStyle(text) {
821
+ const lines = text.split("\n");
822
+ const orderedListRegex = /^\d+\.\s+/;
823
+ const shouldUndoOrderedList = lines.every((line) => orderedListRegex.test(line));
824
+ let result = lines;
825
+ if (shouldUndoOrderedList) {
826
+ result = lines.map((line) => line.replace(orderedListRegex, ""));
896
827
  }
897
- function makePrefix(index, unorderedList) {
898
- if (unorderedList) {
899
- return "- ";
900
- } else {
901
- return `${index + 1}. `;
902
- }
828
+ return {
829
+ text: result.join("\n"),
830
+ processed: shouldUndoOrderedList
831
+ };
832
+ }
833
+ function undoUnorderedListStyle(text) {
834
+ const lines = text.split("\n");
835
+ const unorderedListPrefix = "- ";
836
+ const shouldUndoUnorderedList = lines.every((line) => line.startsWith(unorderedListPrefix));
837
+ let result = lines;
838
+ if (shouldUndoUnorderedList) {
839
+ result = lines.map((line) => line.slice(unorderedListPrefix.length));
903
840
  }
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];
841
+ return {
842
+ text: result.join("\n"),
843
+ processed: shouldUndoUnorderedList
844
+ };
845
+ }
846
+ function makePrefix(index, unorderedList) {
847
+ if (unorderedList) {
848
+ return "- ";
849
+ } else {
850
+ return `${index + 1}. `;
918
851
  }
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;
852
+ }
853
+ function clearExistingListStyle(style, selectedText) {
854
+ let undoResult;
855
+ let undoResultOppositeList;
856
+ let pristineText;
857
+ if (style.orderedList) {
858
+ undoResult = undoOrderedListStyle(selectedText);
859
+ undoResultOppositeList = undoUnorderedListStyle(undoResult.text);
860
+ pristineText = undoResultOppositeList.text;
861
+ } else {
862
+ undoResult = undoUnorderedListStyle(selectedText);
863
+ undoResultOppositeList = undoOrderedListStyle(undoResult.text);
864
+ pristineText = undoResultOppositeList.text;
865
+ }
866
+ return [undoResult, undoResultOppositeList, pristineText];
867
+ }
868
+ function listStyle(textarea, style) {
869
+ const noInitialSelection = textarea.selectionStart === textarea.selectionEnd;
870
+ let selectionStart = textarea.selectionStart;
871
+ let selectionEnd = textarea.selectionEnd;
872
+ expandSelectionToLine(textarea);
873
+ const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
874
+ const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText);
875
+ const prefixedLines = pristineText.split("\n").map((value, index) => {
876
+ return `${makePrefix(index, style.unorderedList)}${value}`;
877
+ });
878
+ const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {
879
+ return previousValue + makePrefix(currentIndex, style.unorderedList).length;
880
+ }, 0);
881
+ const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {
882
+ return previousValue + makePrefix(currentIndex, !style.unorderedList).length;
883
+ }, 0);
884
+ if (undoResult.processed) {
947
885
  if (noInitialSelection) {
948
- selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0);
886
+ selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0);
949
887
  selectionEnd = selectionStart;
950
888
  } 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
- }
889
+ selectionStart = textarea.selectionStart;
890
+ selectionEnd = textarea.selectionEnd - totalPrefixLength;
891
+ }
892
+ return { text: pristineText, selectionStart, selectionEnd };
893
+ }
894
+ const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea);
895
+ const text = newlinesToAppend + prefixedLines.join("\n") + newlinesToPrepend;
896
+ if (noInitialSelection) {
897
+ selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0);
898
+ selectionEnd = selectionStart;
899
+ } else {
900
+ if (undoResultOppositeList.processed) {
901
+ selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0);
902
+ selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList;
903
+ } else {
904
+ selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0);
905
+ selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength;
958
906
  }
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
- }
907
+ }
908
+ return { text, selectionStart, selectionEnd };
909
+ }
910
+ function applyListStyle(textarea, style) {
911
+ const result = applyLineOperation(
912
+ textarea,
913
+ (ta) => listStyle(ta, style),
914
+ {
915
+ // Custom selection adjustment for lists
916
+ adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {
917
+ const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd);
918
+ const orderedListRegex = /^\d+\.\s+/;
919
+ const unorderedListRegex = /^- /;
920
+ const hasOrderedList = orderedListRegex.test(currentLine);
921
+ const hasUnorderedList = unorderedListRegex.test(currentLine);
922
+ const isRemovingCurrent = style.orderedList && hasOrderedList || style.unorderedList && hasUnorderedList;
923
+ if (selStart === selEnd) {
924
+ if (isRemovingCurrent) {
925
+ const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex);
926
+ const prefixLength = prefixMatch ? prefixMatch[0].length : 0;
927
+ return {
928
+ start: Math.max(selStart - prefixLength, lineStart),
929
+ end: Math.max(selStart - prefixLength, lineStart)
930
+ };
931
+ } else if (hasOrderedList || hasUnorderedList) {
932
+ const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex);
933
+ const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0;
934
+ const newPrefixLength = style.unorderedList ? 2 : 3;
935
+ const adjustment = newPrefixLength - oldPrefixLength;
936
+ return {
937
+ start: selStart + adjustment,
938
+ end: selStart + adjustment
939
+ };
998
940
  } 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
- }
941
+ const prefixLength = style.unorderedList ? 2 : 3;
942
+ return {
943
+ start: selStart + prefixLength,
944
+ end: selStart + prefixLength
945
+ };
1022
946
  }
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
947
  } 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}`);
948
+ if (isRemovingCurrent) {
949
+ const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex);
950
+ const prefixLength = prefixMatch ? prefixMatch[0].length : 0;
1297
951
  return {
1298
- start: adjustment,
1299
- end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)
952
+ start: Math.max(selStart - prefixLength, lineStart),
953
+ end: Math.max(selEnd - prefixLength, lineStart)
1300
954
  };
1301
- } else if (existingPrefixLength > 0) {
1302
- const prefixDiff = style.prefix.length - existingPrefixLength;
1303
- debugLog("insertHeader", ` - Replacing header, adjusting by ${prefixDiff}`);
955
+ } else if (hasOrderedList || hasUnorderedList) {
956
+ const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex);
957
+ const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0;
958
+ const newPrefixLength = style.unorderedList ? 2 : 3;
959
+ const adjustment = newPrefixLength - oldPrefixLength;
1304
960
  return {
1305
- start: selStart + prefixDiff,
1306
- end: selEnd + prefixDiff
961
+ start: selStart + adjustment,
962
+ end: selEnd + adjustment
1307
963
  };
1308
964
  } else {
1309
- debugLog("insertHeader", ` - Adding header, adjusting by +${style.prefix.length}`);
965
+ const prefixLength = style.unorderedList ? 2 : 3;
1310
966
  return {
1311
- start: selStart + style.prefix.length,
1312
- end: selEnd + style.prefix.length
967
+ start: selStart + prefixLength,
968
+ end: selEnd + prefixLength
1313
969
  };
1314
970
  }
1315
971
  }
1316
972
  }
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);
973
+ }
974
+ );
975
+ insertText(textarea, result);
976
+ }
977
+ function getActiveFormats(textarea) {
978
+ if (!textarea)
979
+ return [];
980
+ const formats = [];
981
+ const { selectionStart, selectionEnd, value } = textarea;
982
+ const lines = value.split("\n");
983
+ let lineStart = 0;
984
+ let currentLine = "";
985
+ for (const line of lines) {
986
+ if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {
987
+ currentLine = line;
988
+ break;
989
+ }
990
+ lineStart += line.length + 1;
991
+ }
992
+ if (currentLine.startsWith("- ")) {
993
+ if (currentLine.startsWith("- [ ] ") || currentLine.startsWith("- [x] ")) {
994
+ formats.push("task-list");
995
+ } else {
996
+ formats.push("bullet-list");
997
+ }
998
+ }
999
+ if (/^\d+\.\s/.test(currentLine)) {
1000
+ formats.push("numbered-list");
1001
+ }
1002
+ if (currentLine.startsWith("> ")) {
1003
+ formats.push("quote");
1004
+ }
1005
+ if (currentLine.startsWith("# "))
1006
+ formats.push("header");
1007
+ if (currentLine.startsWith("## "))
1008
+ formats.push("header-2");
1009
+ if (currentLine.startsWith("### "))
1010
+ formats.push("header-3");
1011
+ const lookBehind = Math.max(0, selectionStart - 10);
1012
+ const lookAhead = Math.min(value.length, selectionEnd + 10);
1013
+ const surrounding = value.slice(lookBehind, lookAhead);
1014
+ if (surrounding.includes("**")) {
1015
+ const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
1016
+ const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
1017
+ const lastOpenBold = beforeCursor.lastIndexOf("**");
1018
+ const nextCloseBold = afterCursor.indexOf("**");
1019
+ if (lastOpenBold !== -1 && nextCloseBold !== -1) {
1020
+ formats.push("bold");
1021
+ }
1022
+ }
1023
+ if (surrounding.includes("_")) {
1024
+ const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
1025
+ const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
1026
+ const lastOpenItalic = beforeCursor.lastIndexOf("_");
1027
+ const nextCloseItalic = afterCursor.indexOf("_");
1028
+ if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {
1029
+ formats.push("italic");
1030
+ }
1031
+ }
1032
+ if (surrounding.includes("`")) {
1033
+ const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
1034
+ const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
1035
+ if (beforeCursor.includes("`") && afterCursor.includes("`")) {
1036
+ formats.push("code");
1037
+ }
1038
+ }
1039
+ if (surrounding.includes("[") && surrounding.includes("]")) {
1040
+ const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
1041
+ const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
1042
+ const lastOpenBracket = beforeCursor.lastIndexOf("[");
1043
+ const nextCloseBracket = afterCursor.indexOf("]");
1044
+ if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {
1045
+ const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10);
1046
+ if (afterBracket.startsWith("(")) {
1047
+ formats.push("link");
1048
+ }
1049
+ }
1050
+ }
1051
+ return formats;
1052
+ }
1053
+ function toggleBold(textarea) {
1054
+ if (!textarea || textarea.disabled || textarea.readOnly)
1055
+ return;
1056
+ debugLog("toggleBold", "Starting");
1057
+ debugSelection(textarea, "Before");
1058
+ const style = mergeWithDefaults(FORMATS.bold);
1059
+ const result = blockStyle(textarea, style);
1060
+ debugResult(result);
1061
+ insertText(textarea, result);
1062
+ debugSelection(textarea, "After");
1063
+ }
1064
+ function toggleItalic(textarea) {
1065
+ if (!textarea || textarea.disabled || textarea.readOnly)
1066
+ return;
1067
+ const style = mergeWithDefaults(FORMATS.italic);
1068
+ const result = blockStyle(textarea, style);
1069
+ insertText(textarea, result);
1070
+ }
1071
+ function toggleCode(textarea) {
1072
+ if (!textarea || textarea.disabled || textarea.readOnly)
1073
+ return;
1074
+ const style = mergeWithDefaults(FORMATS.code);
1075
+ const result = blockStyle(textarea, style);
1076
+ insertText(textarea, result);
1077
+ }
1078
+ function insertLink(textarea, options = {}) {
1079
+ if (!textarea || textarea.disabled || textarea.readOnly)
1080
+ return;
1081
+ const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
1082
+ let style = mergeWithDefaults(FORMATS.link);
1083
+ const isURL = selectedText && selectedText.match(/^https?:\/\//);
1084
+ if (isURL && !options.url) {
1085
+ style.suffix = `](${selectedText})`;
1086
+ style.replaceNext = "";
1087
+ } else if (options.url) {
1088
+ style.suffix = `](${options.url})`;
1089
+ style.replaceNext = "";
1090
+ }
1091
+ if (options.text && !selectedText) {
1092
+ const pos = textarea.selectionStart;
1093
+ textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos);
1094
+ textarea.selectionStart = pos;
1095
+ textarea.selectionEnd = pos + options.text.length;
1096
+ }
1097
+ const result = blockStyle(textarea, style);
1098
+ insertText(textarea, result);
1099
+ }
1100
+ function toggleBulletList(textarea) {
1101
+ if (!textarea || textarea.disabled || textarea.readOnly)
1102
+ return;
1103
+ const style = mergeWithDefaults(FORMATS.bulletList);
1104
+ applyListStyle(textarea, style);
1105
+ }
1106
+ function toggleNumberedList(textarea) {
1107
+ if (!textarea || textarea.disabled || textarea.readOnly)
1108
+ return;
1109
+ const style = mergeWithDefaults(FORMATS.numberedList);
1110
+ applyListStyle(textarea, style);
1111
+ }
1112
+ function toggleQuote(textarea) {
1113
+ if (!textarea || textarea.disabled || textarea.readOnly)
1114
+ return;
1115
+ debugLog("toggleQuote", "Starting");
1116
+ debugSelection(textarea, "Initial");
1117
+ const style = mergeWithDefaults(FORMATS.quote);
1118
+ const result = applyLineOperation(
1119
+ textarea,
1120
+ (ta) => multilineStyle(ta, style),
1121
+ { prefix: style.prefix }
1122
+ );
1123
+ debugResult(result);
1124
+ insertText(textarea, result);
1125
+ debugSelection(textarea, "Final");
1126
+ }
1127
+ function toggleTaskList(textarea) {
1128
+ if (!textarea || textarea.disabled || textarea.readOnly)
1129
+ return;
1130
+ const style = mergeWithDefaults(FORMATS.taskList);
1131
+ const result = applyLineOperation(
1132
+ textarea,
1133
+ (ta) => multilineStyle(ta, style),
1134
+ { prefix: style.prefix }
1135
+ );
1136
+ insertText(textarea, result);
1137
+ }
1138
+ function insertHeader(textarea, level = 1, toggle = false) {
1139
+ if (!textarea || textarea.disabled || textarea.readOnly)
1140
+ return;
1141
+ if (level < 1 || level > 6)
1142
+ level = 1;
1143
+ debugLog("insertHeader", `============ START ============`);
1144
+ debugLog("insertHeader", `Level: ${level}, Toggle: ${toggle}`);
1145
+ debugLog("insertHeader", `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);
1146
+ const headerKey = `header${level === 1 ? "1" : level}`;
1147
+ const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1);
1148
+ debugLog("insertHeader", `Style prefix: "${style.prefix}"`);
1149
+ const value = textarea.value;
1150
+ const originalStart = textarea.selectionStart;
1151
+ const originalEnd = textarea.selectionEnd;
1152
+ let lineStart = originalStart;
1153
+ while (lineStart > 0 && value[lineStart - 1] !== "\n") {
1154
+ lineStart--;
1155
+ }
1156
+ let lineEnd = originalEnd;
1157
+ while (lineEnd < value.length && value[lineEnd] !== "\n") {
1158
+ lineEnd++;
1159
+ }
1160
+ const currentLineContent = value.slice(lineStart, lineEnd);
1161
+ debugLog("insertHeader", `Current line (before): "${currentLineContent}"`);
1162
+ const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\s*/);
1163
+ const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0;
1164
+ const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0;
1165
+ debugLog("insertHeader", `Existing header check:`);
1166
+ debugLog("insertHeader", ` - Match: ${existingHeaderMatch ? `"${existingHeaderMatch[0]}"` : "none"}`);
1167
+ debugLog("insertHeader", ` - Existing level: ${existingLevel}`);
1168
+ debugLog("insertHeader", ` - Existing prefix length: ${existingPrefixLength}`);
1169
+ debugLog("insertHeader", ` - Target level: ${level}`);
1170
+ const shouldToggleOff = toggle && existingLevel === level;
1171
+ debugLog("insertHeader", `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);
1172
+ const result = applyLineOperation(
1173
+ textarea,
1174
+ (ta) => {
1175
+ const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd);
1176
+ debugLog("insertHeader", `Line in operation: "${currentLine}"`);
1177
+ const cleanedLine = currentLine.replace(/^#{1,6}\s*/, "");
1178
+ debugLog("insertHeader", `Cleaned line: "${cleanedLine}"`);
1179
+ let newLine;
1180
+ if (shouldToggleOff) {
1181
+ debugLog("insertHeader", "ACTION: Toggling OFF - removing header");
1182
+ newLine = cleanedLine;
1183
+ } else if (existingLevel > 0) {
1184
+ debugLog("insertHeader", `ACTION: Replacing H${existingLevel} with H${level}`);
1185
+ newLine = style.prefix + cleanedLine;
1349
1186
  } else {
1350
- result = blockStyle(textarea, style);
1187
+ debugLog("insertHeader", "ACTION: Adding new header");
1188
+ newLine = style.prefix + cleanedLine;
1189
+ }
1190
+ debugLog("insertHeader", `New line: "${newLine}"`);
1191
+ return {
1192
+ text: newLine,
1193
+ selectionStart: ta.selectionStart,
1194
+ selectionEnd: ta.selectionEnd
1195
+ };
1196
+ },
1197
+ {
1198
+ prefix: style.prefix,
1199
+ // Custom selection adjustment for headers
1200
+ adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {
1201
+ debugLog("insertHeader", `Adjusting selection:`);
1202
+ debugLog("insertHeader", ` - isRemoving param: ${isRemoving}`);
1203
+ debugLog("insertHeader", ` - shouldToggleOff: ${shouldToggleOff}`);
1204
+ debugLog("insertHeader", ` - selStart: ${selStart}, selEnd: ${selEnd}`);
1205
+ debugLog("insertHeader", ` - lineStartPos: ${lineStartPos}`);
1206
+ if (shouldToggleOff) {
1207
+ const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos);
1208
+ debugLog("insertHeader", ` - Removing header, adjusting by -${existingPrefixLength}`);
1209
+ return {
1210
+ start: adjustment,
1211
+ end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)
1212
+ };
1213
+ } else if (existingPrefixLength > 0) {
1214
+ const prefixDiff = style.prefix.length - existingPrefixLength;
1215
+ debugLog("insertHeader", ` - Replacing header, adjusting by ${prefixDiff}`);
1216
+ return {
1217
+ start: selStart + prefixDiff,
1218
+ end: selEnd + prefixDiff
1219
+ };
1220
+ } else {
1221
+ debugLog("insertHeader", ` - Adding header, adjusting by +${style.prefix.length}`);
1222
+ return {
1223
+ start: selStart + style.prefix.length,
1224
+ end: selEnd + style.prefix.length
1225
+ };
1226
+ }
1351
1227
  }
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
- })();
1228
+ }
1229
+ );
1230
+ debugLog("insertHeader", `Final result: text="${result.text}", cursor=${result.selectionStart}-${result.selectionEnd}`);
1231
+ debugLog("insertHeader", `============ END ============`);
1232
+ insertText(textarea, result);
1233
+ }
1234
+ function toggleH1(textarea) {
1235
+ insertHeader(textarea, 1, true);
1236
+ }
1237
+ function toggleH2(textarea) {
1238
+ insertHeader(textarea, 2, true);
1239
+ }
1240
+ function toggleH3(textarea) {
1241
+ insertHeader(textarea, 3, true);
1242
+ }
1243
+ function getActiveFormats2(textarea) {
1244
+ return getActiveFormats(textarea);
1245
+ }
1381
1246
 
1382
1247
  // src/shortcuts.js
1383
1248
  var ShortcutsManager = class {
@@ -1446,19 +1311,19 @@ var ShortcutsManager = class {
1446
1311
  try {
1447
1312
  switch (action) {
1448
1313
  case "toggleBold":
1449
- (void 0)(textarea);
1314
+ toggleBold(textarea);
1450
1315
  break;
1451
1316
  case "toggleItalic":
1452
- (void 0)(textarea);
1317
+ toggleItalic(textarea);
1453
1318
  break;
1454
1319
  case "insertLink":
1455
- (void 0)(textarea);
1320
+ insertLink(textarea);
1456
1321
  break;
1457
1322
  case "toggleBulletList":
1458
- (void 0)(textarea);
1323
+ toggleBulletList(textarea);
1459
1324
  break;
1460
1325
  case "toggleNumberedList":
1461
- (void 0)(textarea);
1326
+ toggleNumberedList(textarea);
1462
1327
  break;
1463
1328
  }
1464
1329
  textarea.dispatchEvent(new Event("input", { bubbles: true }));
@@ -1669,11 +1534,17 @@ function generateStyles(options = {}) {
1669
1534
  position: relative !important; /* Override reset - needed for absolute children */
1670
1535
  overflow: visible !important; /* Allow dropdown to overflow container */
1671
1536
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
1537
+ text-align: left !important;
1672
1538
  ${themeVars ? `
1673
1539
  /* Theme Variables */
1674
1540
  ${themeVars}` : ""}
1675
1541
  }
1676
1542
 
1543
+ /* Force left alignment for all elements in the editor */
1544
+ .overtype-container .overtype-wrapper * {
1545
+ text-align: left !important;
1546
+ }
1547
+
1677
1548
  /* Auto-resize mode styles */
1678
1549
  .overtype-container.overtype-auto-resize {
1679
1550
  height: auto !important;
@@ -2546,37 +2417,37 @@ var Toolbar = class {
2546
2417
  try {
2547
2418
  switch (action) {
2548
2419
  case "toggleBold":
2549
- (void 0)(textarea);
2420
+ toggleBold(textarea);
2550
2421
  break;
2551
2422
  case "toggleItalic":
2552
- (void 0)(textarea);
2423
+ toggleItalic(textarea);
2553
2424
  break;
2554
2425
  case "insertH1":
2555
- (void 0)(textarea);
2426
+ toggleH1(textarea);
2556
2427
  break;
2557
2428
  case "insertH2":
2558
- (void 0)(textarea);
2429
+ toggleH2(textarea);
2559
2430
  break;
2560
2431
  case "insertH3":
2561
- (void 0)(textarea);
2432
+ toggleH3(textarea);
2562
2433
  break;
2563
2434
  case "insertLink":
2564
- (void 0)(textarea);
2435
+ insertLink(textarea);
2565
2436
  break;
2566
2437
  case "toggleCode":
2567
- (void 0)(textarea);
2438
+ toggleCode(textarea);
2568
2439
  break;
2569
2440
  case "toggleBulletList":
2570
- (void 0)(textarea);
2441
+ toggleBulletList(textarea);
2571
2442
  break;
2572
2443
  case "toggleNumberedList":
2573
- (void 0)(textarea);
2444
+ toggleNumberedList(textarea);
2574
2445
  break;
2575
2446
  case "toggleQuote":
2576
- (void 0)(textarea);
2447
+ toggleQuote(textarea);
2577
2448
  break;
2578
2449
  case "toggleTaskList":
2579
- (void 0)(textarea);
2450
+ toggleTaskList(textarea);
2580
2451
  break;
2581
2452
  case "toggle-plain":
2582
2453
  const isPlain = this.editor.container.classList.contains("plain-mode");
@@ -2596,7 +2467,7 @@ var Toolbar = class {
2596
2467
  if (!textarea)
2597
2468
  return;
2598
2469
  try {
2599
- const activeFormats = (void 0)(textarea);
2470
+ const activeFormats = getActiveFormats2(textarea);
2600
2471
  Object.entries(this.buttons).forEach(([name, button]) => {
2601
2472
  let isActive = false;
2602
2473
  switch (name) {
@@ -3228,17 +3099,6 @@ var _OverType = class _OverType {
3228
3099
  closeFence.style.display = "block";
3229
3100
  openParent.classList.add("code-block-line");
3230
3101
  closeParent.classList.add("code-block-line");
3231
- let currentDiv = openParent.nextElementSibling;
3232
- while (currentDiv && currentDiv !== closeParent) {
3233
- if (currentDiv.tagName === "DIV") {
3234
- currentDiv.classList.add("code-block-line");
3235
- const plainText = currentDiv.textContent;
3236
- currentDiv.textContent = plainText;
3237
- }
3238
- currentDiv = currentDiv.nextElementSibling;
3239
- if (!currentDiv)
3240
- break;
3241
- }
3242
3102
  }
3243
3103
  }
3244
3104
  /**
@@ -3272,21 +3132,35 @@ var _OverType = class _OverType {
3272
3132
  const after = value.substring(end);
3273
3133
  const lines = selection.split("\n");
3274
3134
  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;
3135
+ if (document.execCommand) {
3136
+ this.textarea.setSelectionRange(start, end);
3137
+ document.execCommand("insertText", false, outdented);
3138
+ } else {
3139
+ this.textarea.value = before + outdented + after;
3140
+ this.textarea.selectionStart = start;
3141
+ this.textarea.selectionEnd = start + outdented.length;
3142
+ }
3278
3143
  } else if (start !== end) {
3279
3144
  const before = value.substring(0, start);
3280
3145
  const selection = value.substring(start, end);
3281
3146
  const after = value.substring(end);
3282
3147
  const lines = selection.split("\n");
3283
3148
  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;
3149
+ if (document.execCommand) {
3150
+ this.textarea.setSelectionRange(start, end);
3151
+ document.execCommand("insertText", false, indented);
3152
+ } else {
3153
+ this.textarea.value = before + indented + after;
3154
+ this.textarea.selectionStart = start;
3155
+ this.textarea.selectionEnd = start + indented.length;
3156
+ }
3287
3157
  } else {
3288
- this.textarea.value = value.substring(0, start) + " " + value.substring(end);
3289
- this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;
3158
+ if (document.execCommand) {
3159
+ document.execCommand("insertText", false, " ");
3160
+ } else {
3161
+ this.textarea.value = value.substring(0, start) + " " + value.substring(end);
3162
+ this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;
3163
+ }
3290
3164
  }
3291
3165
  this.textarea.dispatchEvent(new Event("input", { bubbles: true }));
3292
3166
  return;