markdown-actions 1.1.2 → 1.2.0

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.
@@ -36,6 +36,7 @@ var markdownActions = (() => {
36
36
  __export(src_exports, {
37
37
  applyCustomFormat: () => applyCustomFormat,
38
38
  default: () => src_default,
39
+ detectMarkers: () => detectMarkers,
39
40
  expandSelection: () => expandSelection2,
40
41
  getActiveFormats: () => getActiveFormats2,
41
42
  getDebugMode: () => getDebugMode,
@@ -507,20 +508,20 @@ ${blockSuffix}` : suffix;
507
508
  }
508
509
  function undoUnorderedListStyle(text) {
509
510
  const lines = text.split("\n");
510
- const unorderedListPrefix = "- ";
511
- const shouldUndoUnorderedList = lines.every((line) => line.startsWith(unorderedListPrefix));
511
+ const unorderedListRegex = /^[-*+] /;
512
+ const shouldUndoUnorderedList = lines.every((line) => unorderedListRegex.test(line));
512
513
  let result = lines;
513
514
  if (shouldUndoUnorderedList) {
514
- result = lines.map((line) => line.slice(unorderedListPrefix.length));
515
+ result = lines.map((line) => line.replace(unorderedListRegex, ""));
515
516
  }
516
517
  return {
517
518
  text: result.join("\n"),
518
519
  processed: shouldUndoUnorderedList
519
520
  };
520
521
  }
521
- function makePrefix(index, unorderedList) {
522
+ function makePrefix(index, unorderedList, bulletMarker = "-") {
522
523
  if (unorderedList) {
523
- return "- ";
524
+ return `${bulletMarker} `;
524
525
  } else {
525
526
  return `${index + 1}. `;
526
527
  }
@@ -548,7 +549,7 @@ ${blockSuffix}` : suffix;
548
549
  const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
549
550
  const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText);
550
551
  const prefixedLines = pristineText.split("\n").map((value, index) => {
551
- return `${makePrefix(index, style.unorderedList)}${value}`;
552
+ return `${makePrefix(index, style.unorderedList, style.bulletMarker)}${value}`;
552
553
  });
553
554
  const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {
554
555
  return previousValue + makePrefix(currentIndex, style.unorderedList).length;
@@ -591,7 +592,7 @@ ${blockSuffix}` : suffix;
591
592
  adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {
592
593
  const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd);
593
594
  const orderedListRegex = /^\d+\.\s+/;
594
- const unorderedListRegex = /^- /;
595
+ const unorderedListRegex = /^[-*+] /;
595
596
  const hasOrderedList = orderedListRegex.test(currentLine);
596
597
  const hasUnorderedList = unorderedListRegex.test(currentLine);
597
598
  const isRemovingCurrent = style.orderedList && hasOrderedList || style.unorderedList && hasUnorderedList;
@@ -666,8 +667,8 @@ ${blockSuffix}` : suffix;
666
667
  }
667
668
  lineStart += line.length + 1;
668
669
  }
669
- if (currentLine.startsWith("- ")) {
670
- if (currentLine.startsWith("- [ ] ") || currentLine.startsWith("- [x] ")) {
670
+ if (/^[-*+] /.test(currentLine)) {
671
+ if (/^[-*+] \[[ xX]\] /.test(currentLine)) {
671
672
  formats.push("task-list");
672
673
  } else {
673
674
  formats.push("bullet-list");
@@ -688,36 +689,30 @@ ${blockSuffix}` : suffix;
688
689
  const lookBehind = Math.max(0, selectionStart - 10);
689
690
  const lookAhead = Math.min(value.length, selectionEnd + 10);
690
691
  const surrounding = value.slice(lookBehind, lookAhead);
691
- if (surrounding.includes("**")) {
692
- const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
693
- const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
694
- const lastOpenBold = beforeCursor.lastIndexOf("**");
695
- const nextCloseBold = afterCursor.indexOf("**");
696
- if (lastOpenBold !== -1 && nextCloseBold !== -1) {
697
- formats.push("bold");
698
- }
692
+ const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
693
+ const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
694
+ if (["**", "__"].some((marker) => surrounding.includes(marker) && beforeCursor.lastIndexOf(marker) !== -1 && afterCursor.indexOf(marker) !== -1)) {
695
+ formats.push("bold");
699
696
  }
700
- if (surrounding.includes("_")) {
701
- const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
702
- const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
703
- const lastOpenItalic = beforeCursor.lastIndexOf("_");
704
- const nextCloseItalic = afterCursor.indexOf("_");
705
- if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {
706
- formats.push("italic");
707
- }
697
+ const singleMarker = (ch) => {
698
+ const c = ch === "*" ? "\\*" : ch;
699
+ return new RegExp(`(^|[^${c}])${c}[^${c}]*$`).test(beforeCursor) && new RegExp(`^[^${c}]*${c}(?!${c})`).test(afterCursor);
700
+ };
701
+ if (surrounding.includes("_") && singleMarker("_") || surrounding.includes("*") && singleMarker("*")) {
702
+ formats.push("italic");
708
703
  }
709
704
  if (surrounding.includes("`")) {
710
- const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
711
- const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
712
- if (beforeCursor.includes("`") && afterCursor.includes("`")) {
705
+ const beforeCursor2 = value.slice(Math.max(0, selectionStart - 100), selectionStart);
706
+ const afterCursor2 = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
707
+ if (beforeCursor2.includes("`") && afterCursor2.includes("`")) {
713
708
  formats.push("code");
714
709
  }
715
710
  }
716
711
  if (surrounding.includes("[") && surrounding.includes("]")) {
717
- const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
718
- const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
719
- const lastOpenBracket = beforeCursor.lastIndexOf("[");
720
- const nextCloseBracket = afterCursor.indexOf("]");
712
+ const beforeCursor2 = value.slice(Math.max(0, selectionStart - 100), selectionStart);
713
+ const afterCursor2 = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
714
+ const lastOpenBracket = beforeCursor2.lastIndexOf("[");
715
+ const nextCloseBracket = afterCursor2.indexOf("]");
721
716
  if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {
722
717
  const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10);
723
718
  if (afterBracket.startsWith("(")) {
@@ -765,23 +760,129 @@ ${blockSuffix}` : suffix;
765
760
  }
766
761
  }
767
762
 
763
+ // src/operations/inline.js
764
+ var isEmphasis = (ch) => ch === "*" || ch === "_";
765
+ var OPENING_PUNCTUATION = /[(\[{"'“‘]/;
766
+ var CLOSING_PUNCTUATION = /[.,;:!?)\]}"'”’]/;
767
+ function carries(kind, n) {
768
+ return kind === "bold" ? n >= 2 : n % 2 === 1;
769
+ }
770
+ function runLength(text, ch, fromEnd) {
771
+ let n = 0;
772
+ while (n < text.length && text[fromEnd ? text.length - 1 - n : n] === ch)
773
+ n++;
774
+ return n;
775
+ }
776
+ function findWrap(value, start, end, kind) {
777
+ const size = kind === "bold" ? 2 : 1;
778
+ let open = start;
779
+ while (open > 0 && isEmphasis(value[open - 1]))
780
+ open--;
781
+ let close = end;
782
+ while (close < value.length && isEmphasis(value[close]))
783
+ close++;
784
+ const before = value.slice(open, start);
785
+ const after = value.slice(end, close);
786
+ for (const ch of ["*", "_"]) {
787
+ if (carries(kind, runLength(before, ch, true)) && carries(kind, runLength(after, ch, false))) {
788
+ return { open: start - size, close: end, size };
789
+ }
790
+ const outerBefore = runLength(before, ch, false);
791
+ if (outerBefore < before.length && carries(kind, outerBefore) && carries(kind, runLength(after, ch, true))) {
792
+ return { open, close: close - size, size };
793
+ }
794
+ }
795
+ return null;
796
+ }
797
+ function targetRange(value, selectionStart, selectionEnd) {
798
+ let start = selectionStart;
799
+ let end = selectionEnd;
800
+ if (start === end) {
801
+ start = wordSelectionStart(value, start);
802
+ end = wordSelectionEnd(value, end, false);
803
+ while (start < end && OPENING_PUNCTUATION.test(value[start]))
804
+ start++;
805
+ while (end > start && CLOSING_PUNCTUATION.test(value[end - 1]))
806
+ end--;
807
+ }
808
+ while (start < end && /\s/.test(value[start]))
809
+ start++;
810
+ while (end > start && /\s/.test(value[end - 1]))
811
+ end--;
812
+ while (start < end && isEmphasis(value[start]))
813
+ start++;
814
+ while (end > start && isEmphasis(value[end - 1]))
815
+ end--;
816
+ return { start, end };
817
+ }
818
+ var clamp = (n, low, high) => Math.min(Math.max(n, low), high);
819
+ function inlineStyle(textarea, kind, marker) {
820
+ const value = textarea.value;
821
+ const caretStart = textarea.selectionStart;
822
+ const caretEnd = textarea.selectionEnd;
823
+ const hadSelection = caretStart !== caretEnd;
824
+ const { start, end } = targetRange(value, caretStart, caretEnd);
825
+ const wrap = start < end ? findWrap(value, start, end, kind) : null;
826
+ if (wrap) {
827
+ textarea.selectionStart = wrap.open;
828
+ textarea.selectionEnd = wrap.close + wrap.size;
829
+ const newStart = start - wrap.size;
830
+ const newEnd = end - wrap.size;
831
+ const caret2 = clamp(caretStart - wrap.size, newStart, newEnd);
832
+ return {
833
+ text: value.slice(wrap.open + wrap.size, wrap.close),
834
+ selectionStart: hadSelection ? newStart : caret2,
835
+ selectionEnd: hadSelection ? newEnd : caret2
836
+ };
837
+ }
838
+ textarea.selectionStart = start;
839
+ textarea.selectionEnd = end;
840
+ const caret = clamp(caretStart, start, end) + marker.length;
841
+ return {
842
+ text: marker + value.slice(start, end) + marker,
843
+ selectionStart: hadSelection ? start + marker.length : caret,
844
+ selectionEnd: hadSelection ? end + marker.length : caret
845
+ };
846
+ }
847
+
848
+ // src/core/markers.js
849
+ var MARKERS = {
850
+ bold: ["**", "__"],
851
+ italic: ["_", "*"],
852
+ bullet: ["-", "*", "+"]
853
+ };
854
+ function resolveMarker(kind, marker) {
855
+ return MARKERS[kind].indexOf(marker) !== -1 ? marker : MARKERS[kind][0];
856
+ }
857
+ var DETECT = {
858
+ bullet: /^[ \t]*([-*+])[ \t]+\S/m,
859
+ bold: /(\*\*|__)(?=[^\s*_])[^\n]*?[^\s*_]\1/,
860
+ italic: /(?:^|[^*_\w])([*_])(?=[^\s*_])[^\n*_]*?[^\s*_]\1(?![*_\w])/
861
+ };
862
+ function detectMarkers(text) {
863
+ const found = {};
864
+ Object.keys(DETECT).forEach((kind) => {
865
+ const match = DETECT[kind].exec(text || "");
866
+ found[kind] = match ? match[1] : null;
867
+ });
868
+ return found;
869
+ }
870
+
768
871
  // src/index.js
769
- function toggleBold(textarea) {
872
+ function toggleBold(textarea, options = {}) {
770
873
  if (!textarea || textarea.disabled || textarea.readOnly)
771
874
  return;
772
875
  debugLog("toggleBold", "Starting");
773
876
  debugSelection(textarea, "Before");
774
- const style = mergeWithDefaults(FORMATS.bold);
775
- const result = blockStyle(textarea, style);
877
+ const result = inlineStyle(textarea, "bold", resolveMarker("bold", options.marker));
776
878
  debugResult(result);
777
879
  insertText(textarea, result);
778
880
  debugSelection(textarea, "After");
779
881
  }
780
- function toggleItalic(textarea) {
882
+ function toggleItalic(textarea, options = {}) {
781
883
  if (!textarea || textarea.disabled || textarea.readOnly)
782
884
  return;
783
- const style = mergeWithDefaults(FORMATS.italic);
784
- const result = blockStyle(textarea, style);
885
+ const result = inlineStyle(textarea, "italic", resolveMarker("italic", options.marker));
785
886
  insertText(textarea, result);
786
887
  }
787
888
  function toggleCode(textarea) {
@@ -813,10 +914,11 @@ ${blockSuffix}` : suffix;
813
914
  const result = blockStyle(textarea, style);
814
915
  insertText(textarea, result);
815
916
  }
816
- function toggleBulletList(textarea) {
917
+ function toggleBulletList(textarea, options = {}) {
817
918
  if (!textarea || textarea.disabled || textarea.readOnly)
818
919
  return;
819
920
  const style = mergeWithDefaults(FORMATS.bulletList);
921
+ style.bulletMarker = resolveMarker("bullet", options.marker);
820
922
  applyListStyle(textarea, style);
821
923
  }
822
924
  function toggleNumberedList(textarea) {
@@ -999,6 +1101,7 @@ ${blockSuffix}` : suffix;
999
1101
  hasFormat: hasFormat2,
1000
1102
  expandSelection: expandSelection2,
1001
1103
  applyCustomFormat,
1104
+ detectMarkers,
1002
1105
  preserveSelection,
1003
1106
  setUndoMethod,
1004
1107
  setDebugMode,