overtype 2.1.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -3
- package/dist/overtype-webcomponent.esm.js +1918 -1852
- package/dist/overtype-webcomponent.esm.js.map +3 -3
- package/dist/overtype-webcomponent.js +1323 -1257
- package/dist/overtype-webcomponent.js.map +3 -3
- package/dist/overtype-webcomponent.min.js +33 -33
- package/dist/overtype.cjs +1918 -1852
- package/dist/overtype.cjs.map +3 -3
- package/dist/overtype.esm.js +1918 -1852
- package/dist/overtype.esm.js.map +3 -3
- package/dist/overtype.js +1323 -1257
- package/dist/overtype.js.map +3 -3
- package/dist/overtype.min.js +36 -36
- package/package.json +1 -1
- package/src/link-tooltip.js +18 -4
- package/src/overtype.js +131 -2
- package/src/shortcuts.js +11 -76
- package/src/toolbar-buttons.js +25 -12
- package/src/toolbar.js +27 -48
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OverType v2.0
|
|
2
|
+
* OverType v2.1.0
|
|
3
3
|
* A lightweight markdown editor library with perfect WYSIWYG alignment
|
|
4
4
|
* @license MIT
|
|
5
5
|
* @author David Miranda
|
|
@@ -733,1968 +733,1926 @@ __publicField(MarkdownParser, "LIST_PATTERNS", {
|
|
|
733
733
|
checkbox: /^(\s*)-\s+\[([ x])\]\s+(.*)$/
|
|
734
734
|
});
|
|
735
735
|
|
|
736
|
-
//
|
|
737
|
-
var
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
741
|
-
var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
742
|
-
var __spreadValues = (a, b) => {
|
|
743
|
-
for (var prop in b || (b = {}))
|
|
744
|
-
if (__hasOwnProp.call(b, prop))
|
|
745
|
-
__defNormalProp2(a, prop, b[prop]);
|
|
746
|
-
if (__getOwnPropSymbols)
|
|
747
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
748
|
-
if (__propIsEnum.call(b, prop))
|
|
749
|
-
__defNormalProp2(a, prop, b[prop]);
|
|
750
|
-
}
|
|
751
|
-
return a;
|
|
752
|
-
};
|
|
753
|
-
var FORMATS = {
|
|
754
|
-
bold: {
|
|
755
|
-
prefix: "**",
|
|
756
|
-
suffix: "**",
|
|
757
|
-
trimFirst: true
|
|
758
|
-
},
|
|
759
|
-
italic: {
|
|
760
|
-
prefix: "_",
|
|
761
|
-
suffix: "_",
|
|
762
|
-
trimFirst: true
|
|
763
|
-
},
|
|
764
|
-
code: {
|
|
765
|
-
prefix: "`",
|
|
766
|
-
suffix: "`",
|
|
767
|
-
blockPrefix: "```",
|
|
768
|
-
blockSuffix: "```"
|
|
769
|
-
},
|
|
770
|
-
link: {
|
|
771
|
-
prefix: "[",
|
|
772
|
-
suffix: "](url)",
|
|
773
|
-
replaceNext: "url",
|
|
774
|
-
scanFor: "https?://"
|
|
775
|
-
},
|
|
776
|
-
bulletList: {
|
|
777
|
-
prefix: "- ",
|
|
778
|
-
multiline: true,
|
|
779
|
-
unorderedList: true
|
|
780
|
-
},
|
|
781
|
-
numberedList: {
|
|
782
|
-
prefix: "1. ",
|
|
783
|
-
multiline: true,
|
|
784
|
-
orderedList: true
|
|
785
|
-
},
|
|
786
|
-
quote: {
|
|
787
|
-
prefix: "> ",
|
|
788
|
-
multiline: true,
|
|
789
|
-
surroundWithNewlines: true
|
|
790
|
-
},
|
|
791
|
-
taskList: {
|
|
792
|
-
prefix: "- [ ] ",
|
|
793
|
-
multiline: true,
|
|
794
|
-
surroundWithNewlines: true
|
|
795
|
-
},
|
|
796
|
-
header1: { prefix: "# " },
|
|
797
|
-
header2: { prefix: "## " },
|
|
798
|
-
header3: { prefix: "### " },
|
|
799
|
-
header4: { prefix: "#### " },
|
|
800
|
-
header5: { prefix: "##### " },
|
|
801
|
-
header6: { prefix: "###### " }
|
|
802
|
-
};
|
|
803
|
-
function getDefaultStyle() {
|
|
804
|
-
return {
|
|
805
|
-
prefix: "",
|
|
806
|
-
suffix: "",
|
|
807
|
-
blockPrefix: "",
|
|
808
|
-
blockSuffix: "",
|
|
809
|
-
multiline: false,
|
|
810
|
-
replaceNext: "",
|
|
811
|
-
prefixSpace: false,
|
|
812
|
-
scanFor: "",
|
|
813
|
-
surroundWithNewlines: false,
|
|
814
|
-
orderedList: false,
|
|
815
|
-
unorderedList: false,
|
|
816
|
-
trimFirst: false
|
|
817
|
-
};
|
|
818
|
-
}
|
|
819
|
-
function mergeWithDefaults(format) {
|
|
820
|
-
return __spreadValues(__spreadValues({}, getDefaultStyle()), format);
|
|
821
|
-
}
|
|
822
|
-
var debugMode = false;
|
|
823
|
-
function getDebugMode() {
|
|
824
|
-
return debugMode;
|
|
825
|
-
}
|
|
826
|
-
function debugLog(funcName, message, data) {
|
|
827
|
-
if (!debugMode)
|
|
828
|
-
return;
|
|
829
|
-
console.group(`\u{1F50D} ${funcName}`);
|
|
830
|
-
console.log(message);
|
|
831
|
-
if (data) {
|
|
832
|
-
console.log("Data:", data);
|
|
833
|
-
}
|
|
834
|
-
console.groupEnd();
|
|
835
|
-
}
|
|
836
|
-
function debugSelection(textarea, label) {
|
|
837
|
-
if (!debugMode)
|
|
838
|
-
return;
|
|
839
|
-
const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
840
|
-
console.group(`\u{1F4CD} Selection: ${label}`);
|
|
841
|
-
console.log("Position:", `${textarea.selectionStart}-${textarea.selectionEnd}`);
|
|
842
|
-
console.log("Selected text:", JSON.stringify(selected));
|
|
843
|
-
console.log("Length:", selected.length);
|
|
844
|
-
const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);
|
|
845
|
-
const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));
|
|
846
|
-
console.log("Context:", JSON.stringify(before) + "[SELECTION]" + JSON.stringify(after));
|
|
847
|
-
console.groupEnd();
|
|
848
|
-
}
|
|
849
|
-
function debugResult(result) {
|
|
850
|
-
if (!debugMode)
|
|
851
|
-
return;
|
|
852
|
-
console.group("\u{1F4DD} Result");
|
|
853
|
-
console.log("Text to insert:", JSON.stringify(result.text));
|
|
854
|
-
console.log("New selection:", `${result.selectionStart}-${result.selectionEnd}`);
|
|
855
|
-
console.groupEnd();
|
|
856
|
-
}
|
|
857
|
-
var canInsertText = null;
|
|
858
|
-
function insertText(textarea, { text, selectionStart, selectionEnd }) {
|
|
859
|
-
const debugMode2 = getDebugMode();
|
|
860
|
-
if (debugMode2) {
|
|
861
|
-
console.group("\u{1F527} insertText");
|
|
862
|
-
console.log("Current selection:", `${textarea.selectionStart}-${textarea.selectionEnd}`);
|
|
863
|
-
console.log("Text to insert:", JSON.stringify(text));
|
|
864
|
-
console.log("New selection to set:", selectionStart, "-", selectionEnd);
|
|
865
|
-
}
|
|
866
|
-
textarea.focus();
|
|
867
|
-
const originalSelectionStart = textarea.selectionStart;
|
|
868
|
-
const originalSelectionEnd = textarea.selectionEnd;
|
|
869
|
-
const before = textarea.value.slice(0, originalSelectionStart);
|
|
870
|
-
const after = textarea.value.slice(originalSelectionEnd);
|
|
871
|
-
if (debugMode2) {
|
|
872
|
-
console.log("Before text (last 20):", JSON.stringify(before.slice(-20)));
|
|
873
|
-
console.log("After text (first 20):", JSON.stringify(after.slice(0, 20)));
|
|
874
|
-
console.log("Selected text being replaced:", JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));
|
|
875
|
-
}
|
|
876
|
-
const originalValue = textarea.value;
|
|
877
|
-
const hasSelection = originalSelectionStart !== originalSelectionEnd;
|
|
878
|
-
if (canInsertText === null || canInsertText === true) {
|
|
879
|
-
textarea.contentEditable = "true";
|
|
880
|
-
try {
|
|
881
|
-
canInsertText = document.execCommand("insertText", false, text);
|
|
882
|
-
if (debugMode2)
|
|
883
|
-
console.log("execCommand returned:", canInsertText, "for text with", text.split("\n").length, "lines");
|
|
884
|
-
} catch (error) {
|
|
885
|
-
canInsertText = false;
|
|
886
|
-
if (debugMode2)
|
|
887
|
-
console.log("execCommand threw error:", error);
|
|
888
|
-
}
|
|
889
|
-
textarea.contentEditable = "false";
|
|
890
|
-
}
|
|
891
|
-
if (debugMode2) {
|
|
892
|
-
console.log("canInsertText before:", canInsertText);
|
|
893
|
-
console.log("execCommand result:", canInsertText);
|
|
736
|
+
// src/shortcuts.js
|
|
737
|
+
var ShortcutsManager = class {
|
|
738
|
+
constructor(editor) {
|
|
739
|
+
this.editor = editor;
|
|
894
740
|
}
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
741
|
+
/**
|
|
742
|
+
* Handle keydown events - called by OverType
|
|
743
|
+
* @param {KeyboardEvent} event - The keyboard event
|
|
744
|
+
* @returns {boolean} Whether the event was handled
|
|
745
|
+
*/
|
|
746
|
+
handleKeydown(event) {
|
|
747
|
+
const isMac = navigator.platform.toLowerCase().includes("mac");
|
|
748
|
+
const modKey = isMac ? event.metaKey : event.ctrlKey;
|
|
749
|
+
if (!modKey)
|
|
750
|
+
return false;
|
|
751
|
+
let actionId = null;
|
|
752
|
+
switch (event.key.toLowerCase()) {
|
|
753
|
+
case "b":
|
|
754
|
+
if (!event.shiftKey)
|
|
755
|
+
actionId = "toggleBold";
|
|
756
|
+
break;
|
|
757
|
+
case "i":
|
|
758
|
+
if (!event.shiftKey)
|
|
759
|
+
actionId = "toggleItalic";
|
|
760
|
+
break;
|
|
761
|
+
case "k":
|
|
762
|
+
if (!event.shiftKey)
|
|
763
|
+
actionId = "insertLink";
|
|
764
|
+
break;
|
|
765
|
+
case "7":
|
|
766
|
+
if (event.shiftKey)
|
|
767
|
+
actionId = "toggleNumberedList";
|
|
768
|
+
break;
|
|
769
|
+
case "8":
|
|
770
|
+
if (event.shiftKey)
|
|
771
|
+
actionId = "toggleBulletList";
|
|
772
|
+
break;
|
|
901
773
|
}
|
|
902
|
-
if (
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
console.log("Actual:", JSON.stringify(actualValue.slice(0, 100)));
|
|
907
|
-
}
|
|
774
|
+
if (actionId) {
|
|
775
|
+
event.preventDefault();
|
|
776
|
+
this.editor.performAction(actionId, event);
|
|
777
|
+
return true;
|
|
908
778
|
}
|
|
779
|
+
return false;
|
|
909
780
|
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
if (debugMode2)
|
|
915
|
-
console.log("Value unchanged, doing manual replacement");
|
|
916
|
-
try {
|
|
917
|
-
document.execCommand("ms-beginUndoUnit");
|
|
918
|
-
} catch (e) {
|
|
919
|
-
}
|
|
920
|
-
textarea.value = before + text + after;
|
|
921
|
-
try {
|
|
922
|
-
document.execCommand("ms-endUndoUnit");
|
|
923
|
-
} catch (e) {
|
|
924
|
-
}
|
|
925
|
-
textarea.dispatchEvent(new CustomEvent("input", { bubbles: true, cancelable: true }));
|
|
926
|
-
} else {
|
|
927
|
-
if (debugMode2)
|
|
928
|
-
console.log("Value was changed by execCommand, skipping manual insertion");
|
|
929
|
-
}
|
|
781
|
+
/**
|
|
782
|
+
* Cleanup
|
|
783
|
+
*/
|
|
784
|
+
destroy() {
|
|
930
785
|
}
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
786
|
+
};
|
|
787
|
+
|
|
788
|
+
// src/themes.js
|
|
789
|
+
var solar = {
|
|
790
|
+
name: "solar",
|
|
791
|
+
colors: {
|
|
792
|
+
bgPrimary: "#faf0ca",
|
|
793
|
+
// Lemon Chiffon - main background
|
|
794
|
+
bgSecondary: "#ffffff",
|
|
795
|
+
// White - editor background
|
|
796
|
+
text: "#0d3b66",
|
|
797
|
+
// Yale Blue - main text
|
|
798
|
+
textPrimary: "#0d3b66",
|
|
799
|
+
// Yale Blue - primary text (same as text)
|
|
800
|
+
textSecondary: "#5a7a9b",
|
|
801
|
+
// Muted blue - secondary text
|
|
802
|
+
h1: "#f95738",
|
|
803
|
+
// Tomato - h1 headers
|
|
804
|
+
h2: "#ee964b",
|
|
805
|
+
// Sandy Brown - h2 headers
|
|
806
|
+
h3: "#3d8a51",
|
|
807
|
+
// Forest green - h3 headers
|
|
808
|
+
strong: "#ee964b",
|
|
809
|
+
// Sandy Brown - bold text
|
|
810
|
+
em: "#f95738",
|
|
811
|
+
// Tomato - italic text
|
|
812
|
+
del: "#ee964b",
|
|
813
|
+
// Sandy Brown - deleted text (same as strong)
|
|
814
|
+
link: "#0d3b66",
|
|
815
|
+
// Yale Blue - links
|
|
816
|
+
code: "#0d3b66",
|
|
817
|
+
// Yale Blue - inline code
|
|
818
|
+
codeBg: "rgba(244, 211, 94, 0.4)",
|
|
819
|
+
// Naples Yellow with transparency
|
|
820
|
+
blockquote: "#5a7a9b",
|
|
821
|
+
// Muted blue - blockquotes
|
|
822
|
+
hr: "#5a7a9b",
|
|
823
|
+
// Muted blue - horizontal rules
|
|
824
|
+
syntaxMarker: "rgba(13, 59, 102, 0.52)",
|
|
825
|
+
// Yale Blue with transparency
|
|
826
|
+
syntax: "#999999",
|
|
827
|
+
// Gray - syntax highlighting fallback
|
|
828
|
+
cursor: "#f95738",
|
|
829
|
+
// Tomato - cursor
|
|
830
|
+
selection: "rgba(244, 211, 94, 0.4)",
|
|
831
|
+
// Naples Yellow with transparency
|
|
832
|
+
listMarker: "#ee964b",
|
|
833
|
+
// Sandy Brown - list markers
|
|
834
|
+
rawLine: "#5a7a9b",
|
|
835
|
+
// Muted blue - raw line indicators
|
|
836
|
+
border: "#e0e0e0",
|
|
837
|
+
// Light gray - borders
|
|
838
|
+
hoverBg: "#f0f0f0",
|
|
839
|
+
// Very light gray - hover backgrounds
|
|
840
|
+
primary: "#0d3b66",
|
|
841
|
+
// Yale Blue - primary accent
|
|
842
|
+
// Toolbar colors
|
|
843
|
+
toolbarBg: "#ffffff",
|
|
844
|
+
// White - toolbar background
|
|
845
|
+
toolbarIcon: "#0d3b66",
|
|
846
|
+
// Yale Blue - icon color
|
|
847
|
+
toolbarHover: "#f5f5f5",
|
|
848
|
+
// Light gray - hover background
|
|
849
|
+
toolbarActive: "#faf0ca"
|
|
850
|
+
// Lemon Chiffon - active button background
|
|
937
851
|
}
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
852
|
+
};
|
|
853
|
+
var cave = {
|
|
854
|
+
name: "cave",
|
|
855
|
+
colors: {
|
|
856
|
+
bgPrimary: "#141E26",
|
|
857
|
+
// Deep ocean - main background
|
|
858
|
+
bgSecondary: "#1D2D3E",
|
|
859
|
+
// Darker charcoal - editor background
|
|
860
|
+
text: "#c5dde8",
|
|
861
|
+
// Light blue-gray - main text
|
|
862
|
+
textPrimary: "#c5dde8",
|
|
863
|
+
// Light blue-gray - primary text (same as text)
|
|
864
|
+
textSecondary: "#9fcfec",
|
|
865
|
+
// Brighter blue - secondary text
|
|
866
|
+
h1: "#d4a5ff",
|
|
867
|
+
// Rich lavender - h1 headers
|
|
868
|
+
h2: "#f6ae2d",
|
|
869
|
+
// Hunyadi Yellow - h2 headers
|
|
870
|
+
h3: "#9fcfec",
|
|
871
|
+
// Brighter blue - h3 headers
|
|
872
|
+
strong: "#f6ae2d",
|
|
873
|
+
// Hunyadi Yellow - bold text
|
|
874
|
+
em: "#9fcfec",
|
|
875
|
+
// Brighter blue - italic text
|
|
876
|
+
del: "#f6ae2d",
|
|
877
|
+
// Hunyadi Yellow - deleted text (same as strong)
|
|
878
|
+
link: "#9fcfec",
|
|
879
|
+
// Brighter blue - links
|
|
880
|
+
code: "#c5dde8",
|
|
881
|
+
// Light blue-gray - inline code
|
|
882
|
+
codeBg: "#1a232b",
|
|
883
|
+
// Very dark blue - code background
|
|
884
|
+
blockquote: "#9fcfec",
|
|
885
|
+
// Brighter blue - same as italic
|
|
886
|
+
hr: "#c5dde8",
|
|
887
|
+
// Light blue-gray - horizontal rules
|
|
888
|
+
syntaxMarker: "rgba(159, 207, 236, 0.73)",
|
|
889
|
+
// Brighter blue semi-transparent
|
|
890
|
+
syntax: "#7a8c98",
|
|
891
|
+
// Muted gray-blue - syntax highlighting fallback
|
|
892
|
+
cursor: "#f26419",
|
|
893
|
+
// Orange Pantone - cursor
|
|
894
|
+
selection: "rgba(51, 101, 138, 0.4)",
|
|
895
|
+
// Lapis Lazuli with transparency
|
|
896
|
+
listMarker: "#f6ae2d",
|
|
897
|
+
// Hunyadi Yellow - list markers
|
|
898
|
+
rawLine: "#9fcfec",
|
|
899
|
+
// Brighter blue - raw line indicators
|
|
900
|
+
border: "#2a3f52",
|
|
901
|
+
// Dark blue-gray - borders
|
|
902
|
+
hoverBg: "#243546",
|
|
903
|
+
// Slightly lighter charcoal - hover backgrounds
|
|
904
|
+
primary: "#9fcfec",
|
|
905
|
+
// Brighter blue - primary accent
|
|
906
|
+
// Toolbar colors for dark theme
|
|
907
|
+
toolbarBg: "#1D2D3E",
|
|
908
|
+
// Darker charcoal - toolbar background
|
|
909
|
+
toolbarIcon: "#c5dde8",
|
|
910
|
+
// Light blue-gray - icon color
|
|
911
|
+
toolbarHover: "#243546",
|
|
912
|
+
// Slightly lighter charcoal - hover background
|
|
913
|
+
toolbarActive: "#2a3f52"
|
|
914
|
+
// Even lighter - active button background
|
|
941
915
|
}
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
916
|
+
};
|
|
917
|
+
var themes = {
|
|
918
|
+
solar,
|
|
919
|
+
cave,
|
|
920
|
+
// Aliases for backward compatibility
|
|
921
|
+
light: solar,
|
|
922
|
+
dark: cave
|
|
923
|
+
};
|
|
924
|
+
function getTheme(theme) {
|
|
925
|
+
if (typeof theme === "string") {
|
|
926
|
+
const themeObj = themes[theme] || themes.solar;
|
|
927
|
+
return { ...themeObj, name: theme };
|
|
950
928
|
}
|
|
951
|
-
return
|
|
929
|
+
return theme;
|
|
952
930
|
}
|
|
953
|
-
function
|
|
954
|
-
|
|
955
|
-
const
|
|
956
|
-
|
|
957
|
-
|
|
931
|
+
function themeToCSSVars(colors) {
|
|
932
|
+
const vars = [];
|
|
933
|
+
for (const [key, value] of Object.entries(colors)) {
|
|
934
|
+
const varName = key.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
935
|
+
vars.push(`--${varName}: ${value};`);
|
|
958
936
|
}
|
|
959
|
-
return
|
|
937
|
+
return vars.join("\n");
|
|
960
938
|
}
|
|
961
|
-
function
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
textarea.selectionStart = counter;
|
|
939
|
+
function mergeTheme(baseTheme, customColors = {}) {
|
|
940
|
+
return {
|
|
941
|
+
...baseTheme,
|
|
942
|
+
colors: {
|
|
943
|
+
...baseTheme.colors,
|
|
944
|
+
...customColors
|
|
968
945
|
}
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
946
|
+
};
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
// src/styles.js
|
|
950
|
+
function generateStyles(options = {}) {
|
|
951
|
+
const {
|
|
952
|
+
fontSize = "14px",
|
|
953
|
+
lineHeight = 1.6,
|
|
954
|
+
/* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */
|
|
955
|
+
fontFamily = '"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',
|
|
956
|
+
padding = "20px",
|
|
957
|
+
theme = null,
|
|
958
|
+
mobile = {}
|
|
959
|
+
} = options;
|
|
960
|
+
const mobileStyles = Object.keys(mobile).length > 0 ? `
|
|
961
|
+
@media (max-width: 640px) {
|
|
962
|
+
.overtype-wrapper .overtype-input,
|
|
963
|
+
.overtype-wrapper .overtype-preview {
|
|
964
|
+
${Object.entries(mobile).map(([prop, val]) => {
|
|
965
|
+
const cssProp = prop.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
966
|
+
return `${cssProp}: ${val} !important;`;
|
|
967
|
+
}).join("\n ")}
|
|
974
968
|
}
|
|
975
969
|
}
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
970
|
+
` : "";
|
|
971
|
+
const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : "";
|
|
972
|
+
return `
|
|
973
|
+
/* OverType Editor Styles */
|
|
974
|
+
|
|
975
|
+
/* Middle-ground CSS Reset - Prevent parent styles from leaking in */
|
|
976
|
+
.overtype-container * {
|
|
977
|
+
/* Box model - these commonly leak */
|
|
978
|
+
margin: 0 !important;
|
|
979
|
+
padding: 0 !important;
|
|
980
|
+
border: 0 !important;
|
|
981
|
+
|
|
982
|
+
/* Layout - these can break our layout */
|
|
983
|
+
/* Don't reset position - it breaks dropdowns */
|
|
984
|
+
float: none !important;
|
|
985
|
+
clear: none !important;
|
|
986
|
+
|
|
987
|
+
/* Typography - only reset decorative aspects */
|
|
988
|
+
text-decoration: none !important;
|
|
989
|
+
text-transform: none !important;
|
|
990
|
+
letter-spacing: normal !important;
|
|
991
|
+
|
|
992
|
+
/* Visual effects that can interfere */
|
|
993
|
+
box-shadow: none !important;
|
|
994
|
+
text-shadow: none !important;
|
|
995
|
+
|
|
996
|
+
/* Ensure box-sizing is consistent */
|
|
997
|
+
box-sizing: border-box !important;
|
|
998
|
+
|
|
999
|
+
/* Keep inheritance for these */
|
|
1000
|
+
/* font-family, color, line-height, font-size - inherit */
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
/* Container base styles after reset */
|
|
1004
|
+
.overtype-container {
|
|
1005
|
+
display: flex !important;
|
|
1006
|
+
flex-direction: column !important;
|
|
1007
|
+
width: 100% !important;
|
|
1008
|
+
height: 100% !important;
|
|
1009
|
+
position: relative !important; /* Override reset - needed for absolute children */
|
|
1010
|
+
overflow: visible !important; /* Allow dropdown to overflow container */
|
|
1011
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
|
|
1012
|
+
text-align: left !important;
|
|
1013
|
+
${themeVars ? `
|
|
1014
|
+
/* Theme Variables */
|
|
1015
|
+
${themeVars}` : ""}
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
/* Force left alignment for all elements in the editor */
|
|
1019
|
+
.overtype-container .overtype-wrapper * {
|
|
1020
|
+
text-align: left !important;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
/* Auto-resize mode styles */
|
|
1024
|
+
.overtype-container.overtype-auto-resize {
|
|
1025
|
+
height: auto !important;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
.overtype-container.overtype-auto-resize .overtype-wrapper {
|
|
1029
|
+
flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */
|
|
1030
|
+
height: auto !important;
|
|
1031
|
+
min-height: 60px !important;
|
|
1032
|
+
overflow: visible !important;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
.overtype-wrapper {
|
|
1036
|
+
position: relative !important; /* Override reset - needed for absolute children */
|
|
1037
|
+
width: 100% !important;
|
|
1038
|
+
flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */
|
|
1039
|
+
min-height: 60px !important; /* Minimum usable height */
|
|
1040
|
+
overflow: hidden !important;
|
|
1041
|
+
background: var(--bg-secondary, #ffffff) !important;
|
|
1042
|
+
z-index: 1; /* Below toolbar and dropdown */
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
/* Critical alignment styles - must be identical for both layers */
|
|
1046
|
+
.overtype-wrapper .overtype-input,
|
|
1047
|
+
.overtype-wrapper .overtype-preview {
|
|
1048
|
+
/* Positioning - must be identical */
|
|
1049
|
+
position: absolute !important; /* Override reset - required for overlay */
|
|
1050
|
+
top: 0 !important;
|
|
1051
|
+
left: 0 !important;
|
|
1052
|
+
width: 100% !important;
|
|
1053
|
+
height: 100% !important;
|
|
1054
|
+
|
|
1055
|
+
/* Font properties - any difference breaks alignment */
|
|
1056
|
+
font-family: ${fontFamily} !important;
|
|
1057
|
+
font-variant-ligatures: none !important; /* keep metrics stable for code */
|
|
1058
|
+
font-size: var(--instance-font-size, ${fontSize}) !important;
|
|
1059
|
+
line-height: var(--instance-line-height, ${lineHeight}) !important;
|
|
1060
|
+
font-weight: normal !important;
|
|
1061
|
+
font-style: normal !important;
|
|
1062
|
+
font-variant: normal !important;
|
|
1063
|
+
font-stretch: normal !important;
|
|
1064
|
+
font-kerning: none !important;
|
|
1065
|
+
font-feature-settings: normal !important;
|
|
1066
|
+
|
|
1067
|
+
/* Box model - must match exactly */
|
|
1068
|
+
padding: var(--instance-padding, ${padding}) !important;
|
|
1069
|
+
margin: 0 !important;
|
|
1070
|
+
border: none !important;
|
|
1071
|
+
outline: none !important;
|
|
1072
|
+
box-sizing: border-box !important;
|
|
1073
|
+
|
|
1074
|
+
/* Text layout - critical for character positioning */
|
|
1075
|
+
white-space: pre-wrap !important;
|
|
1076
|
+
word-wrap: break-word !important;
|
|
1077
|
+
word-break: normal !important;
|
|
1078
|
+
overflow-wrap: break-word !important;
|
|
1079
|
+
tab-size: 2 !important;
|
|
1080
|
+
-moz-tab-size: 2 !important;
|
|
1081
|
+
text-align: left !important;
|
|
1082
|
+
text-indent: 0 !important;
|
|
1083
|
+
letter-spacing: normal !important;
|
|
1084
|
+
word-spacing: normal !important;
|
|
1085
|
+
|
|
1086
|
+
/* Text rendering */
|
|
1087
|
+
text-transform: none !important;
|
|
1088
|
+
text-rendering: auto !important;
|
|
1089
|
+
-webkit-font-smoothing: auto !important;
|
|
1090
|
+
-webkit-text-size-adjust: 100% !important;
|
|
1091
|
+
|
|
1092
|
+
/* Direction and writing */
|
|
1093
|
+
direction: ltr !important;
|
|
1094
|
+
writing-mode: horizontal-tb !important;
|
|
1095
|
+
unicode-bidi: normal !important;
|
|
1096
|
+
text-orientation: mixed !important;
|
|
1097
|
+
|
|
1098
|
+
/* Visual effects that could shift perception */
|
|
1099
|
+
text-shadow: none !important;
|
|
1100
|
+
filter: none !important;
|
|
1101
|
+
transform: none !important;
|
|
1102
|
+
zoom: 1 !important;
|
|
1103
|
+
|
|
1104
|
+
/* Vertical alignment */
|
|
1105
|
+
vertical-align: baseline !important;
|
|
1106
|
+
|
|
1107
|
+
/* Size constraints */
|
|
1108
|
+
min-width: 0 !important;
|
|
1109
|
+
min-height: 0 !important;
|
|
1110
|
+
max-width: none !important;
|
|
1111
|
+
max-height: none !important;
|
|
1112
|
+
|
|
1113
|
+
/* Overflow */
|
|
1114
|
+
overflow-y: auto !important;
|
|
1115
|
+
overflow-x: auto !important;
|
|
1116
|
+
/* overscroll-behavior removed to allow scroll-through to parent */
|
|
1117
|
+
scrollbar-width: auto !important;
|
|
1118
|
+
scrollbar-gutter: auto !important;
|
|
1119
|
+
|
|
1120
|
+
/* Animation/transition - disabled to prevent movement */
|
|
1121
|
+
animation: none !important;
|
|
1122
|
+
transition: none !important;
|
|
991
1123
|
}
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
let lineStart = originalStart;
|
|
1018
|
-
while (lineStart > 0 && value[lineStart - 1] !== "\n") {
|
|
1019
|
-
lineStart--;
|
|
1020
|
-
}
|
|
1021
|
-
if (noInitialSelection) {
|
|
1022
|
-
let lineEnd = originalStart;
|
|
1023
|
-
while (lineEnd < value.length && value[lineEnd] !== "\n") {
|
|
1024
|
-
lineEnd++;
|
|
1124
|
+
|
|
1125
|
+
/* Input layer styles */
|
|
1126
|
+
.overtype-wrapper .overtype-input {
|
|
1127
|
+
/* Layer positioning */
|
|
1128
|
+
z-index: 1 !important;
|
|
1129
|
+
|
|
1130
|
+
/* Text visibility */
|
|
1131
|
+
color: transparent !important;
|
|
1132
|
+
caret-color: var(--cursor, #f95738) !important;
|
|
1133
|
+
background-color: transparent !important;
|
|
1134
|
+
|
|
1135
|
+
/* Textarea-specific */
|
|
1136
|
+
resize: none !important;
|
|
1137
|
+
appearance: none !important;
|
|
1138
|
+
-webkit-appearance: none !important;
|
|
1139
|
+
-moz-appearance: none !important;
|
|
1140
|
+
|
|
1141
|
+
/* Prevent mobile zoom on focus */
|
|
1142
|
+
touch-action: manipulation !important;
|
|
1143
|
+
|
|
1144
|
+
/* Disable autofill and spellcheck */
|
|
1145
|
+
autocomplete: off !important;
|
|
1146
|
+
autocorrect: off !important;
|
|
1147
|
+
autocapitalize: off !important;
|
|
1148
|
+
spellcheck: false !important;
|
|
1025
1149
|
}
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
expandSelectionToLine(textarea);
|
|
1030
|
-
}
|
|
1031
|
-
const result = operation(textarea);
|
|
1032
|
-
if (options.adjustSelection) {
|
|
1033
|
-
const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
1034
|
-
const isRemoving = selectedText.startsWith(options.prefix);
|
|
1035
|
-
const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart);
|
|
1036
|
-
result.selectionStart = adjusted.start;
|
|
1037
|
-
result.selectionEnd = adjusted.end;
|
|
1038
|
-
} else if (options.prefix) {
|
|
1039
|
-
const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
1040
|
-
const isRemoving = selectedText.startsWith(options.prefix);
|
|
1041
|
-
if (noInitialSelection) {
|
|
1042
|
-
if (isRemoving) {
|
|
1043
|
-
result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart);
|
|
1044
|
-
result.selectionEnd = result.selectionStart;
|
|
1045
|
-
} else {
|
|
1046
|
-
result.selectionStart = originalStart + options.prefix.length;
|
|
1047
|
-
result.selectionEnd = result.selectionStart;
|
|
1048
|
-
}
|
|
1049
|
-
} else {
|
|
1050
|
-
if (isRemoving) {
|
|
1051
|
-
result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart);
|
|
1052
|
-
result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart);
|
|
1053
|
-
} else {
|
|
1054
|
-
result.selectionStart = originalStart + options.prefix.length;
|
|
1055
|
-
result.selectionEnd = originalEnd + options.prefix.length;
|
|
1056
|
-
}
|
|
1150
|
+
|
|
1151
|
+
.overtype-wrapper .overtype-input::selection {
|
|
1152
|
+
background-color: var(--selection, rgba(244, 211, 94, 0.4));
|
|
1057
1153
|
}
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
if (prefixSpace) {
|
|
1073
|
-
const beforeSelection = textarea.value[textarea.selectionStart - 1];
|
|
1074
|
-
if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\s/)) {
|
|
1075
|
-
prefixToUse = ` ${prefixToUse}`;
|
|
1154
|
+
|
|
1155
|
+
/* Preview layer styles */
|
|
1156
|
+
.overtype-wrapper .overtype-preview {
|
|
1157
|
+
/* Layer positioning */
|
|
1158
|
+
z-index: 0 !important;
|
|
1159
|
+
pointer-events: none !important;
|
|
1160
|
+
color: var(--text, #0d3b66) !important;
|
|
1161
|
+
background-color: transparent !important;
|
|
1162
|
+
|
|
1163
|
+
/* Prevent text selection */
|
|
1164
|
+
user-select: none !important;
|
|
1165
|
+
-webkit-user-select: none !important;
|
|
1166
|
+
-moz-user-select: none !important;
|
|
1167
|
+
-ms-user-select: none !important;
|
|
1076
1168
|
}
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
position = Math.min(position, selectionStart + replacementText.length);
|
|
1095
|
-
selectionStart = selectionEnd = position;
|
|
1096
|
-
} else {
|
|
1097
|
-
selectionEnd = selectionStart + replacementText.length;
|
|
1169
|
+
|
|
1170
|
+
/* Defensive styles for preview child divs */
|
|
1171
|
+
.overtype-wrapper .overtype-preview div {
|
|
1172
|
+
/* Reset any inherited styles */
|
|
1173
|
+
margin: 0 !important;
|
|
1174
|
+
padding: 0 !important;
|
|
1175
|
+
border: none !important;
|
|
1176
|
+
text-align: left !important;
|
|
1177
|
+
text-indent: 0 !important;
|
|
1178
|
+
display: block !important;
|
|
1179
|
+
position: static !important;
|
|
1180
|
+
transform: none !important;
|
|
1181
|
+
min-height: 0 !important;
|
|
1182
|
+
max-height: none !important;
|
|
1183
|
+
line-height: inherit !important;
|
|
1184
|
+
font-size: inherit !important;
|
|
1185
|
+
font-family: inherit !important;
|
|
1098
1186
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
selectionEnd = originalSelectionEnd + prefixToUse.length;
|
|
1104
|
-
const whitespaceEdges = selectedText.match(/^\s*|\s*$/g);
|
|
1105
|
-
if (trimFirst && whitespaceEdges) {
|
|
1106
|
-
const leadingWhitespace = whitespaceEdges[0] || "";
|
|
1107
|
-
const trailingWhitespace = whitespaceEdges[1] || "";
|
|
1108
|
-
replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace;
|
|
1109
|
-
selectionStart += leadingWhitespace.length;
|
|
1110
|
-
selectionEnd -= trailingWhitespace.length;
|
|
1187
|
+
|
|
1188
|
+
/* Markdown element styling - NO SIZE CHANGES */
|
|
1189
|
+
.overtype-wrapper .overtype-preview .header {
|
|
1190
|
+
font-weight: bold !important;
|
|
1111
1191
|
}
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
selectionStart = selectionEnd = selectionStart + prefixToUse.length;
|
|
1117
|
-
return { text: replacementText, selectionStart, selectionEnd };
|
|
1118
|
-
} else {
|
|
1119
|
-
const replacementText = prefixToUse + selectedText + suffixToUse;
|
|
1120
|
-
selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext);
|
|
1121
|
-
selectionEnd = selectionStart + replaceNext.length;
|
|
1122
|
-
return { text: replacementText, selectionStart, selectionEnd };
|
|
1123
|
-
}
|
|
1124
|
-
}
|
|
1125
|
-
function multilineStyle(textarea, style) {
|
|
1126
|
-
const { prefix, suffix, surroundWithNewlines } = style;
|
|
1127
|
-
let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
1128
|
-
let selectionStart = textarea.selectionStart;
|
|
1129
|
-
let selectionEnd = textarea.selectionEnd;
|
|
1130
|
-
const lines = text.split("\n");
|
|
1131
|
-
const undoStyle = lines.every((line) => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)));
|
|
1132
|
-
if (undoStyle) {
|
|
1133
|
-
text = lines.map((line) => {
|
|
1134
|
-
let result = line.slice(prefix.length);
|
|
1135
|
-
if (suffix) {
|
|
1136
|
-
result = result.slice(0, result.length - suffix.length);
|
|
1137
|
-
}
|
|
1138
|
-
return result;
|
|
1139
|
-
}).join("\n");
|
|
1140
|
-
selectionEnd = selectionStart + text.length;
|
|
1141
|
-
} else {
|
|
1142
|
-
text = lines.map((line) => prefix + line + (suffix || "")).join("\n");
|
|
1143
|
-
if (surroundWithNewlines) {
|
|
1144
|
-
const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea);
|
|
1145
|
-
selectionStart += newlinesToAppend.length;
|
|
1146
|
-
selectionEnd = selectionStart + text.length;
|
|
1147
|
-
text = newlinesToAppend + text + newlinesToPrepend;
|
|
1192
|
+
|
|
1193
|
+
/* Header colors */
|
|
1194
|
+
.overtype-wrapper .overtype-preview .h1 {
|
|
1195
|
+
color: var(--h1, #f95738) !important;
|
|
1148
1196
|
}
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
}
|
|
1152
|
-
function undoOrderedListStyle(text) {
|
|
1153
|
-
const lines = text.split("\n");
|
|
1154
|
-
const orderedListRegex = /^\d+\.\s+/;
|
|
1155
|
-
const shouldUndoOrderedList = lines.every((line) => orderedListRegex.test(line));
|
|
1156
|
-
let result = lines;
|
|
1157
|
-
if (shouldUndoOrderedList) {
|
|
1158
|
-
result = lines.map((line) => line.replace(orderedListRegex, ""));
|
|
1159
|
-
}
|
|
1160
|
-
return {
|
|
1161
|
-
text: result.join("\n"),
|
|
1162
|
-
processed: shouldUndoOrderedList
|
|
1163
|
-
};
|
|
1164
|
-
}
|
|
1165
|
-
function undoUnorderedListStyle(text) {
|
|
1166
|
-
const lines = text.split("\n");
|
|
1167
|
-
const unorderedListPrefix = "- ";
|
|
1168
|
-
const shouldUndoUnorderedList = lines.every((line) => line.startsWith(unorderedListPrefix));
|
|
1169
|
-
let result = lines;
|
|
1170
|
-
if (shouldUndoUnorderedList) {
|
|
1171
|
-
result = lines.map((line) => line.slice(unorderedListPrefix.length));
|
|
1172
|
-
}
|
|
1173
|
-
return {
|
|
1174
|
-
text: result.join("\n"),
|
|
1175
|
-
processed: shouldUndoUnorderedList
|
|
1176
|
-
};
|
|
1177
|
-
}
|
|
1178
|
-
function makePrefix(index, unorderedList) {
|
|
1179
|
-
if (unorderedList) {
|
|
1180
|
-
return "- ";
|
|
1181
|
-
} else {
|
|
1182
|
-
return `${index + 1}. `;
|
|
1183
|
-
}
|
|
1184
|
-
}
|
|
1185
|
-
function clearExistingListStyle(style, selectedText) {
|
|
1186
|
-
let undoResult;
|
|
1187
|
-
let undoResultOppositeList;
|
|
1188
|
-
let pristineText;
|
|
1189
|
-
if (style.orderedList) {
|
|
1190
|
-
undoResult = undoOrderedListStyle(selectedText);
|
|
1191
|
-
undoResultOppositeList = undoUnorderedListStyle(undoResult.text);
|
|
1192
|
-
pristineText = undoResultOppositeList.text;
|
|
1193
|
-
} else {
|
|
1194
|
-
undoResult = undoUnorderedListStyle(selectedText);
|
|
1195
|
-
undoResultOppositeList = undoOrderedListStyle(undoResult.text);
|
|
1196
|
-
pristineText = undoResultOppositeList.text;
|
|
1197
|
-
}
|
|
1198
|
-
return [undoResult, undoResultOppositeList, pristineText];
|
|
1199
|
-
}
|
|
1200
|
-
function listStyle(textarea, style) {
|
|
1201
|
-
const noInitialSelection = textarea.selectionStart === textarea.selectionEnd;
|
|
1202
|
-
let selectionStart = textarea.selectionStart;
|
|
1203
|
-
let selectionEnd = textarea.selectionEnd;
|
|
1204
|
-
expandSelectionToLine(textarea);
|
|
1205
|
-
const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
1206
|
-
const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText);
|
|
1207
|
-
const prefixedLines = pristineText.split("\n").map((value, index) => {
|
|
1208
|
-
return `${makePrefix(index, style.unorderedList)}${value}`;
|
|
1209
|
-
});
|
|
1210
|
-
const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {
|
|
1211
|
-
return previousValue + makePrefix(currentIndex, style.unorderedList).length;
|
|
1212
|
-
}, 0);
|
|
1213
|
-
const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {
|
|
1214
|
-
return previousValue + makePrefix(currentIndex, !style.unorderedList).length;
|
|
1215
|
-
}, 0);
|
|
1216
|
-
if (undoResult.processed) {
|
|
1217
|
-
if (noInitialSelection) {
|
|
1218
|
-
selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0);
|
|
1219
|
-
selectionEnd = selectionStart;
|
|
1220
|
-
} else {
|
|
1221
|
-
selectionStart = textarea.selectionStart;
|
|
1222
|
-
selectionEnd = textarea.selectionEnd - totalPrefixLength;
|
|
1197
|
+
.overtype-wrapper .overtype-preview .h2 {
|
|
1198
|
+
color: var(--h2, #ee964b) !important;
|
|
1223
1199
|
}
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea);
|
|
1227
|
-
const text = newlinesToAppend + prefixedLines.join("\n") + newlinesToPrepend;
|
|
1228
|
-
if (noInitialSelection) {
|
|
1229
|
-
selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0);
|
|
1230
|
-
selectionEnd = selectionStart;
|
|
1231
|
-
} else {
|
|
1232
|
-
if (undoResultOppositeList.processed) {
|
|
1233
|
-
selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0);
|
|
1234
|
-
selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList;
|
|
1235
|
-
} else {
|
|
1236
|
-
selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0);
|
|
1237
|
-
selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength;
|
|
1200
|
+
.overtype-wrapper .overtype-preview .h3 {
|
|
1201
|
+
color: var(--h3, #3d8a51) !important;
|
|
1238
1202
|
}
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
const orderedListRegex = /^\d+\.\s+/;
|
|
1251
|
-
const unorderedListRegex = /^- /;
|
|
1252
|
-
const hasOrderedList = orderedListRegex.test(currentLine);
|
|
1253
|
-
const hasUnorderedList = unorderedListRegex.test(currentLine);
|
|
1254
|
-
const isRemovingCurrent = style.orderedList && hasOrderedList || style.unorderedList && hasUnorderedList;
|
|
1255
|
-
if (selStart === selEnd) {
|
|
1256
|
-
if (isRemovingCurrent) {
|
|
1257
|
-
const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex);
|
|
1258
|
-
const prefixLength = prefixMatch ? prefixMatch[0].length : 0;
|
|
1259
|
-
return {
|
|
1260
|
-
start: Math.max(selStart - prefixLength, lineStart),
|
|
1261
|
-
end: Math.max(selStart - prefixLength, lineStart)
|
|
1262
|
-
};
|
|
1263
|
-
} else if (hasOrderedList || hasUnorderedList) {
|
|
1264
|
-
const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex);
|
|
1265
|
-
const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0;
|
|
1266
|
-
const newPrefixLength = style.unorderedList ? 2 : 3;
|
|
1267
|
-
const adjustment = newPrefixLength - oldPrefixLength;
|
|
1268
|
-
return {
|
|
1269
|
-
start: selStart + adjustment,
|
|
1270
|
-
end: selStart + adjustment
|
|
1271
|
-
};
|
|
1272
|
-
} else {
|
|
1273
|
-
const prefixLength = style.unorderedList ? 2 : 3;
|
|
1274
|
-
return {
|
|
1275
|
-
start: selStart + prefixLength,
|
|
1276
|
-
end: selStart + prefixLength
|
|
1277
|
-
};
|
|
1278
|
-
}
|
|
1279
|
-
} else {
|
|
1280
|
-
if (isRemovingCurrent) {
|
|
1281
|
-
const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex);
|
|
1282
|
-
const prefixLength = prefixMatch ? prefixMatch[0].length : 0;
|
|
1283
|
-
return {
|
|
1284
|
-
start: Math.max(selStart - prefixLength, lineStart),
|
|
1285
|
-
end: Math.max(selEnd - prefixLength, lineStart)
|
|
1286
|
-
};
|
|
1287
|
-
} else if (hasOrderedList || hasUnorderedList) {
|
|
1288
|
-
const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex);
|
|
1289
|
-
const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0;
|
|
1290
|
-
const newPrefixLength = style.unorderedList ? 2 : 3;
|
|
1291
|
-
const adjustment = newPrefixLength - oldPrefixLength;
|
|
1292
|
-
return {
|
|
1293
|
-
start: selStart + adjustment,
|
|
1294
|
-
end: selEnd + adjustment
|
|
1295
|
-
};
|
|
1296
|
-
} else {
|
|
1297
|
-
const prefixLength = style.unorderedList ? 2 : 3;
|
|
1298
|
-
return {
|
|
1299
|
-
start: selStart + prefixLength,
|
|
1300
|
-
end: selEnd + prefixLength
|
|
1301
|
-
};
|
|
1302
|
-
}
|
|
1303
|
-
}
|
|
1304
|
-
}
|
|
1203
|
+
|
|
1204
|
+
/* Semantic headers - flatten in edit mode */
|
|
1205
|
+
.overtype-wrapper .overtype-preview h1,
|
|
1206
|
+
.overtype-wrapper .overtype-preview h2,
|
|
1207
|
+
.overtype-wrapper .overtype-preview h3 {
|
|
1208
|
+
font-size: inherit !important;
|
|
1209
|
+
font-weight: bold !important;
|
|
1210
|
+
margin: 0 !important;
|
|
1211
|
+
padding: 0 !important;
|
|
1212
|
+
display: inline !important;
|
|
1213
|
+
line-height: inherit !important;
|
|
1305
1214
|
}
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
if (!textarea)
|
|
1311
|
-
return [];
|
|
1312
|
-
const formats = [];
|
|
1313
|
-
const { selectionStart, selectionEnd, value } = textarea;
|
|
1314
|
-
const lines = value.split("\n");
|
|
1315
|
-
let lineStart = 0;
|
|
1316
|
-
let currentLine = "";
|
|
1317
|
-
for (const line of lines) {
|
|
1318
|
-
if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {
|
|
1319
|
-
currentLine = line;
|
|
1320
|
-
break;
|
|
1215
|
+
|
|
1216
|
+
/* Header colors for semantic headers */
|
|
1217
|
+
.overtype-wrapper .overtype-preview h1 {
|
|
1218
|
+
color: var(--h1, #f95738) !important;
|
|
1321
1219
|
}
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
if (currentLine.startsWith("- ")) {
|
|
1325
|
-
if (currentLine.startsWith("- [ ] ") || currentLine.startsWith("- [x] ")) {
|
|
1326
|
-
formats.push("task-list");
|
|
1327
|
-
} else {
|
|
1328
|
-
formats.push("bullet-list");
|
|
1220
|
+
.overtype-wrapper .overtype-preview h2 {
|
|
1221
|
+
color: var(--h2, #ee964b) !important;
|
|
1329
1222
|
}
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
formats.push("numbered-list");
|
|
1333
|
-
}
|
|
1334
|
-
if (currentLine.startsWith("> ")) {
|
|
1335
|
-
formats.push("quote");
|
|
1336
|
-
}
|
|
1337
|
-
if (currentLine.startsWith("# "))
|
|
1338
|
-
formats.push("header");
|
|
1339
|
-
if (currentLine.startsWith("## "))
|
|
1340
|
-
formats.push("header-2");
|
|
1341
|
-
if (currentLine.startsWith("### "))
|
|
1342
|
-
formats.push("header-3");
|
|
1343
|
-
const lookBehind = Math.max(0, selectionStart - 10);
|
|
1344
|
-
const lookAhead = Math.min(value.length, selectionEnd + 10);
|
|
1345
|
-
const surrounding = value.slice(lookBehind, lookAhead);
|
|
1346
|
-
if (surrounding.includes("**")) {
|
|
1347
|
-
const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
|
|
1348
|
-
const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
|
|
1349
|
-
const lastOpenBold = beforeCursor.lastIndexOf("**");
|
|
1350
|
-
const nextCloseBold = afterCursor.indexOf("**");
|
|
1351
|
-
if (lastOpenBold !== -1 && nextCloseBold !== -1) {
|
|
1352
|
-
formats.push("bold");
|
|
1223
|
+
.overtype-wrapper .overtype-preview h3 {
|
|
1224
|
+
color: var(--h3, #3d8a51) !important;
|
|
1353
1225
|
}
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1226
|
+
|
|
1227
|
+
/* Lists - remove styling in edit mode */
|
|
1228
|
+
.overtype-wrapper .overtype-preview ul,
|
|
1229
|
+
.overtype-wrapper .overtype-preview ol {
|
|
1230
|
+
list-style: none !important;
|
|
1231
|
+
margin: 0 !important;
|
|
1232
|
+
padding: 0 !important;
|
|
1233
|
+
display: block !important; /* Lists need to be block for line breaks */
|
|
1362
1234
|
}
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1235
|
+
|
|
1236
|
+
.overtype-wrapper .overtype-preview li {
|
|
1237
|
+
display: block !important; /* Each item on its own line */
|
|
1238
|
+
margin: 0 !important;
|
|
1239
|
+
padding: 0 !important;
|
|
1240
|
+
/* Don't set list-style here - let ul/ol control it */
|
|
1369
1241
|
}
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
const nextCloseBracket = afterCursor.indexOf("]");
|
|
1376
|
-
if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {
|
|
1377
|
-
const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10);
|
|
1378
|
-
if (afterBracket.startsWith("(")) {
|
|
1379
|
-
formats.push("link");
|
|
1380
|
-
}
|
|
1242
|
+
|
|
1243
|
+
/* Bold text */
|
|
1244
|
+
.overtype-wrapper .overtype-preview strong {
|
|
1245
|
+
color: var(--strong, #ee964b) !important;
|
|
1246
|
+
font-weight: bold !important;
|
|
1381
1247
|
}
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
1398
|
-
return;
|
|
1399
|
-
const style = mergeWithDefaults(FORMATS.italic);
|
|
1400
|
-
const result = blockStyle(textarea, style);
|
|
1401
|
-
insertText(textarea, result);
|
|
1402
|
-
}
|
|
1403
|
-
function toggleCode(textarea) {
|
|
1404
|
-
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
1405
|
-
return;
|
|
1406
|
-
const style = mergeWithDefaults(FORMATS.code);
|
|
1407
|
-
const result = blockStyle(textarea, style);
|
|
1408
|
-
insertText(textarea, result);
|
|
1409
|
-
}
|
|
1410
|
-
function insertLink(textarea, options = {}) {
|
|
1411
|
-
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
1412
|
-
return;
|
|
1413
|
-
const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
1414
|
-
let style = mergeWithDefaults(FORMATS.link);
|
|
1415
|
-
const isURL = selectedText && selectedText.match(/^https?:\/\//);
|
|
1416
|
-
if (isURL && !options.url) {
|
|
1417
|
-
style.suffix = `](${selectedText})`;
|
|
1418
|
-
style.replaceNext = "";
|
|
1419
|
-
} else if (options.url) {
|
|
1420
|
-
style.suffix = `](${options.url})`;
|
|
1421
|
-
style.replaceNext = "";
|
|
1422
|
-
}
|
|
1423
|
-
if (options.text && !selectedText) {
|
|
1424
|
-
const pos = textarea.selectionStart;
|
|
1425
|
-
textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos);
|
|
1426
|
-
textarea.selectionStart = pos;
|
|
1427
|
-
textarea.selectionEnd = pos + options.text.length;
|
|
1428
|
-
}
|
|
1429
|
-
const result = blockStyle(textarea, style);
|
|
1430
|
-
insertText(textarea, result);
|
|
1431
|
-
}
|
|
1432
|
-
function toggleBulletList(textarea) {
|
|
1433
|
-
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
1434
|
-
return;
|
|
1435
|
-
const style = mergeWithDefaults(FORMATS.bulletList);
|
|
1436
|
-
applyListStyle(textarea, style);
|
|
1437
|
-
}
|
|
1438
|
-
function toggleNumberedList(textarea) {
|
|
1439
|
-
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
1440
|
-
return;
|
|
1441
|
-
const style = mergeWithDefaults(FORMATS.numberedList);
|
|
1442
|
-
applyListStyle(textarea, style);
|
|
1443
|
-
}
|
|
1444
|
-
function toggleQuote(textarea) {
|
|
1445
|
-
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
1446
|
-
return;
|
|
1447
|
-
debugLog("toggleQuote", "Starting");
|
|
1448
|
-
debugSelection(textarea, "Initial");
|
|
1449
|
-
const style = mergeWithDefaults(FORMATS.quote);
|
|
1450
|
-
const result = applyLineOperation(
|
|
1451
|
-
textarea,
|
|
1452
|
-
(ta) => multilineStyle(ta, style),
|
|
1453
|
-
{ prefix: style.prefix }
|
|
1454
|
-
);
|
|
1455
|
-
debugResult(result);
|
|
1456
|
-
insertText(textarea, result);
|
|
1457
|
-
debugSelection(textarea, "Final");
|
|
1458
|
-
}
|
|
1459
|
-
function toggleTaskList(textarea) {
|
|
1460
|
-
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
1461
|
-
return;
|
|
1462
|
-
const style = mergeWithDefaults(FORMATS.taskList);
|
|
1463
|
-
const result = applyLineOperation(
|
|
1464
|
-
textarea,
|
|
1465
|
-
(ta) => multilineStyle(ta, style),
|
|
1466
|
-
{ prefix: style.prefix }
|
|
1467
|
-
);
|
|
1468
|
-
insertText(textarea, result);
|
|
1469
|
-
}
|
|
1470
|
-
function insertHeader(textarea, level = 1, toggle = false) {
|
|
1471
|
-
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
1472
|
-
return;
|
|
1473
|
-
if (level < 1 || level > 6)
|
|
1474
|
-
level = 1;
|
|
1475
|
-
debugLog("insertHeader", `============ START ============`);
|
|
1476
|
-
debugLog("insertHeader", `Level: ${level}, Toggle: ${toggle}`);
|
|
1477
|
-
debugLog("insertHeader", `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);
|
|
1478
|
-
const headerKey = `header${level === 1 ? "1" : level}`;
|
|
1479
|
-
const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1);
|
|
1480
|
-
debugLog("insertHeader", `Style prefix: "${style.prefix}"`);
|
|
1481
|
-
const value = textarea.value;
|
|
1482
|
-
const originalStart = textarea.selectionStart;
|
|
1483
|
-
const originalEnd = textarea.selectionEnd;
|
|
1484
|
-
let lineStart = originalStart;
|
|
1485
|
-
while (lineStart > 0 && value[lineStart - 1] !== "\n") {
|
|
1486
|
-
lineStart--;
|
|
1487
|
-
}
|
|
1488
|
-
let lineEnd = originalEnd;
|
|
1489
|
-
while (lineEnd < value.length && value[lineEnd] !== "\n") {
|
|
1490
|
-
lineEnd++;
|
|
1491
|
-
}
|
|
1492
|
-
const currentLineContent = value.slice(lineStart, lineEnd);
|
|
1493
|
-
debugLog("insertHeader", `Current line (before): "${currentLineContent}"`);
|
|
1494
|
-
const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\s*/);
|
|
1495
|
-
const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0;
|
|
1496
|
-
const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0;
|
|
1497
|
-
debugLog("insertHeader", `Existing header check:`);
|
|
1498
|
-
debugLog("insertHeader", ` - Match: ${existingHeaderMatch ? `"${existingHeaderMatch[0]}"` : "none"}`);
|
|
1499
|
-
debugLog("insertHeader", ` - Existing level: ${existingLevel}`);
|
|
1500
|
-
debugLog("insertHeader", ` - Existing prefix length: ${existingPrefixLength}`);
|
|
1501
|
-
debugLog("insertHeader", ` - Target level: ${level}`);
|
|
1502
|
-
const shouldToggleOff = toggle && existingLevel === level;
|
|
1503
|
-
debugLog("insertHeader", `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);
|
|
1504
|
-
const result = applyLineOperation(
|
|
1505
|
-
textarea,
|
|
1506
|
-
(ta) => {
|
|
1507
|
-
const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd);
|
|
1508
|
-
debugLog("insertHeader", `Line in operation: "${currentLine}"`);
|
|
1509
|
-
const cleanedLine = currentLine.replace(/^#{1,6}\s*/, "");
|
|
1510
|
-
debugLog("insertHeader", `Cleaned line: "${cleanedLine}"`);
|
|
1511
|
-
let newLine;
|
|
1512
|
-
if (shouldToggleOff) {
|
|
1513
|
-
debugLog("insertHeader", "ACTION: Toggling OFF - removing header");
|
|
1514
|
-
newLine = cleanedLine;
|
|
1515
|
-
} else if (existingLevel > 0) {
|
|
1516
|
-
debugLog("insertHeader", `ACTION: Replacing H${existingLevel} with H${level}`);
|
|
1517
|
-
newLine = style.prefix + cleanedLine;
|
|
1518
|
-
} else {
|
|
1519
|
-
debugLog("insertHeader", "ACTION: Adding new header");
|
|
1520
|
-
newLine = style.prefix + cleanedLine;
|
|
1521
|
-
}
|
|
1522
|
-
debugLog("insertHeader", `New line: "${newLine}"`);
|
|
1523
|
-
return {
|
|
1524
|
-
text: newLine,
|
|
1525
|
-
selectionStart: ta.selectionStart,
|
|
1526
|
-
selectionEnd: ta.selectionEnd
|
|
1527
|
-
};
|
|
1528
|
-
},
|
|
1529
|
-
{
|
|
1530
|
-
prefix: style.prefix,
|
|
1531
|
-
// Custom selection adjustment for headers
|
|
1532
|
-
adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {
|
|
1533
|
-
debugLog("insertHeader", `Adjusting selection:`);
|
|
1534
|
-
debugLog("insertHeader", ` - isRemoving param: ${isRemoving}`);
|
|
1535
|
-
debugLog("insertHeader", ` - shouldToggleOff: ${shouldToggleOff}`);
|
|
1536
|
-
debugLog("insertHeader", ` - selStart: ${selStart}, selEnd: ${selEnd}`);
|
|
1537
|
-
debugLog("insertHeader", ` - lineStartPos: ${lineStartPos}`);
|
|
1538
|
-
if (shouldToggleOff) {
|
|
1539
|
-
const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos);
|
|
1540
|
-
debugLog("insertHeader", ` - Removing header, adjusting by -${existingPrefixLength}`);
|
|
1541
|
-
return {
|
|
1542
|
-
start: adjustment,
|
|
1543
|
-
end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)
|
|
1544
|
-
};
|
|
1545
|
-
} else if (existingPrefixLength > 0) {
|
|
1546
|
-
const prefixDiff = style.prefix.length - existingPrefixLength;
|
|
1547
|
-
debugLog("insertHeader", ` - Replacing header, adjusting by ${prefixDiff}`);
|
|
1548
|
-
return {
|
|
1549
|
-
start: selStart + prefixDiff,
|
|
1550
|
-
end: selEnd + prefixDiff
|
|
1551
|
-
};
|
|
1552
|
-
} else {
|
|
1553
|
-
debugLog("insertHeader", ` - Adding header, adjusting by +${style.prefix.length}`);
|
|
1554
|
-
return {
|
|
1555
|
-
start: selStart + style.prefix.length,
|
|
1556
|
-
end: selEnd + style.prefix.length
|
|
1557
|
-
};
|
|
1558
|
-
}
|
|
1559
|
-
}
|
|
1248
|
+
|
|
1249
|
+
/* Italic text */
|
|
1250
|
+
.overtype-wrapper .overtype-preview em {
|
|
1251
|
+
color: var(--em, #f95738) !important;
|
|
1252
|
+
text-decoration-color: var(--em, #f95738) !important;
|
|
1253
|
+
text-decoration-thickness: 1px !important;
|
|
1254
|
+
font-style: italic !important;
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
/* Strikethrough text */
|
|
1258
|
+
.overtype-wrapper .overtype-preview del {
|
|
1259
|
+
color: var(--del, #ee964b) !important;
|
|
1260
|
+
text-decoration: line-through !important;
|
|
1261
|
+
text-decoration-color: var(--del, #ee964b) !important;
|
|
1262
|
+
text-decoration-thickness: 1px !important;
|
|
1560
1263
|
}
|
|
1561
|
-
);
|
|
1562
|
-
debugLog("insertHeader", `Final result: text="${result.text}", cursor=${result.selectionStart}-${result.selectionEnd}`);
|
|
1563
|
-
debugLog("insertHeader", `============ END ============`);
|
|
1564
|
-
insertText(textarea, result);
|
|
1565
|
-
}
|
|
1566
|
-
function toggleH1(textarea) {
|
|
1567
|
-
insertHeader(textarea, 1, true);
|
|
1568
|
-
}
|
|
1569
|
-
function toggleH2(textarea) {
|
|
1570
|
-
insertHeader(textarea, 2, true);
|
|
1571
|
-
}
|
|
1572
|
-
function toggleH3(textarea) {
|
|
1573
|
-
insertHeader(textarea, 3, true);
|
|
1574
|
-
}
|
|
1575
|
-
function getActiveFormats2(textarea) {
|
|
1576
|
-
return getActiveFormats(textarea);
|
|
1577
|
-
}
|
|
1578
1264
|
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
*/
|
|
1590
|
-
handleKeydown(event) {
|
|
1591
|
-
const isMac = navigator.platform.toLowerCase().includes("mac");
|
|
1592
|
-
const modKey = isMac ? event.metaKey : event.ctrlKey;
|
|
1593
|
-
if (!modKey)
|
|
1594
|
-
return false;
|
|
1595
|
-
let action = null;
|
|
1596
|
-
switch (event.key.toLowerCase()) {
|
|
1597
|
-
case "b":
|
|
1598
|
-
if (!event.shiftKey) {
|
|
1599
|
-
action = "toggleBold";
|
|
1600
|
-
}
|
|
1601
|
-
break;
|
|
1602
|
-
case "i":
|
|
1603
|
-
if (!event.shiftKey) {
|
|
1604
|
-
action = "toggleItalic";
|
|
1605
|
-
}
|
|
1606
|
-
break;
|
|
1607
|
-
case "k":
|
|
1608
|
-
if (!event.shiftKey) {
|
|
1609
|
-
action = "insertLink";
|
|
1610
|
-
}
|
|
1611
|
-
break;
|
|
1612
|
-
case "7":
|
|
1613
|
-
if (event.shiftKey) {
|
|
1614
|
-
action = "toggleNumberedList";
|
|
1615
|
-
}
|
|
1616
|
-
break;
|
|
1617
|
-
case "8":
|
|
1618
|
-
if (event.shiftKey) {
|
|
1619
|
-
action = "toggleBulletList";
|
|
1620
|
-
}
|
|
1621
|
-
break;
|
|
1265
|
+
/* Inline code */
|
|
1266
|
+
.overtype-wrapper .overtype-preview code {
|
|
1267
|
+
background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;
|
|
1268
|
+
color: var(--code, #0d3b66) !important;
|
|
1269
|
+
padding: 0 !important;
|
|
1270
|
+
border-radius: 2px !important;
|
|
1271
|
+
font-family: inherit !important;
|
|
1272
|
+
font-size: inherit !important;
|
|
1273
|
+
line-height: inherit !important;
|
|
1274
|
+
font-weight: normal !important;
|
|
1622
1275
|
}
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
return true;
|
|
1276
|
+
|
|
1277
|
+
/* Code blocks - consolidated pre blocks */
|
|
1278
|
+
.overtype-wrapper .overtype-preview pre {
|
|
1279
|
+
padding: 0 !important;
|
|
1280
|
+
margin: 0 !important;
|
|
1281
|
+
border-radius: 4px !important;
|
|
1282
|
+
overflow-x: auto !important;
|
|
1631
1283
|
}
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
*/
|
|
1638
|
-
async handleAction(action) {
|
|
1639
|
-
const textarea = this.textarea;
|
|
1640
|
-
if (!textarea)
|
|
1641
|
-
return;
|
|
1642
|
-
textarea.focus();
|
|
1643
|
-
try {
|
|
1644
|
-
switch (action) {
|
|
1645
|
-
case "toggleBold":
|
|
1646
|
-
toggleBold(textarea);
|
|
1647
|
-
break;
|
|
1648
|
-
case "toggleItalic":
|
|
1649
|
-
toggleItalic(textarea);
|
|
1650
|
-
break;
|
|
1651
|
-
case "insertLink":
|
|
1652
|
-
insertLink(textarea);
|
|
1653
|
-
break;
|
|
1654
|
-
case "toggleBulletList":
|
|
1655
|
-
toggleBulletList(textarea);
|
|
1656
|
-
break;
|
|
1657
|
-
case "toggleNumberedList":
|
|
1658
|
-
toggleNumberedList(textarea);
|
|
1659
|
-
break;
|
|
1660
|
-
}
|
|
1661
|
-
textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
1662
|
-
} catch (error) {
|
|
1663
|
-
console.error("Error in markdown action:", error);
|
|
1284
|
+
|
|
1285
|
+
/* Code block styling in normal mode - yellow background */
|
|
1286
|
+
.overtype-wrapper .overtype-preview pre.code-block {
|
|
1287
|
+
background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;
|
|
1288
|
+
white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */
|
|
1664
1289
|
}
|
|
1665
|
-
}
|
|
1666
|
-
/**
|
|
1667
|
-
* Cleanup
|
|
1668
|
-
*/
|
|
1669
|
-
destroy() {
|
|
1670
|
-
}
|
|
1671
|
-
};
|
|
1672
1290
|
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
// Lemon Chiffon - main background
|
|
1679
|
-
bgSecondary: "#ffffff",
|
|
1680
|
-
// White - editor background
|
|
1681
|
-
text: "#0d3b66",
|
|
1682
|
-
// Yale Blue - main text
|
|
1683
|
-
textPrimary: "#0d3b66",
|
|
1684
|
-
// Yale Blue - primary text (same as text)
|
|
1685
|
-
textSecondary: "#5a7a9b",
|
|
1686
|
-
// Muted blue - secondary text
|
|
1687
|
-
h1: "#f95738",
|
|
1688
|
-
// Tomato - h1 headers
|
|
1689
|
-
h2: "#ee964b",
|
|
1690
|
-
// Sandy Brown - h2 headers
|
|
1691
|
-
h3: "#3d8a51",
|
|
1692
|
-
// Forest green - h3 headers
|
|
1693
|
-
strong: "#ee964b",
|
|
1694
|
-
// Sandy Brown - bold text
|
|
1695
|
-
em: "#f95738",
|
|
1696
|
-
// Tomato - italic text
|
|
1697
|
-
del: "#ee964b",
|
|
1698
|
-
// Sandy Brown - deleted text (same as strong)
|
|
1699
|
-
link: "#0d3b66",
|
|
1700
|
-
// Yale Blue - links
|
|
1701
|
-
code: "#0d3b66",
|
|
1702
|
-
// Yale Blue - inline code
|
|
1703
|
-
codeBg: "rgba(244, 211, 94, 0.4)",
|
|
1704
|
-
// Naples Yellow with transparency
|
|
1705
|
-
blockquote: "#5a7a9b",
|
|
1706
|
-
// Muted blue - blockquotes
|
|
1707
|
-
hr: "#5a7a9b",
|
|
1708
|
-
// Muted blue - horizontal rules
|
|
1709
|
-
syntaxMarker: "rgba(13, 59, 102, 0.52)",
|
|
1710
|
-
// Yale Blue with transparency
|
|
1711
|
-
syntax: "#999999",
|
|
1712
|
-
// Gray - syntax highlighting fallback
|
|
1713
|
-
cursor: "#f95738",
|
|
1714
|
-
// Tomato - cursor
|
|
1715
|
-
selection: "rgba(244, 211, 94, 0.4)",
|
|
1716
|
-
// Naples Yellow with transparency
|
|
1717
|
-
listMarker: "#ee964b",
|
|
1718
|
-
// Sandy Brown - list markers
|
|
1719
|
-
rawLine: "#5a7a9b",
|
|
1720
|
-
// Muted blue - raw line indicators
|
|
1721
|
-
border: "#e0e0e0",
|
|
1722
|
-
// Light gray - borders
|
|
1723
|
-
hoverBg: "#f0f0f0",
|
|
1724
|
-
// Very light gray - hover backgrounds
|
|
1725
|
-
primary: "#0d3b66",
|
|
1726
|
-
// Yale Blue - primary accent
|
|
1727
|
-
// Toolbar colors
|
|
1728
|
-
toolbarBg: "#ffffff",
|
|
1729
|
-
// White - toolbar background
|
|
1730
|
-
toolbarIcon: "#0d3b66",
|
|
1731
|
-
// Yale Blue - icon color
|
|
1732
|
-
toolbarHover: "#f5f5f5",
|
|
1733
|
-
// Light gray - hover background
|
|
1734
|
-
toolbarActive: "#faf0ca"
|
|
1735
|
-
// Lemon Chiffon - active button background
|
|
1736
|
-
}
|
|
1737
|
-
};
|
|
1738
|
-
var cave = {
|
|
1739
|
-
name: "cave",
|
|
1740
|
-
colors: {
|
|
1741
|
-
bgPrimary: "#141E26",
|
|
1742
|
-
// Deep ocean - main background
|
|
1743
|
-
bgSecondary: "#1D2D3E",
|
|
1744
|
-
// Darker charcoal - editor background
|
|
1745
|
-
text: "#c5dde8",
|
|
1746
|
-
// Light blue-gray - main text
|
|
1747
|
-
textPrimary: "#c5dde8",
|
|
1748
|
-
// Light blue-gray - primary text (same as text)
|
|
1749
|
-
textSecondary: "#9fcfec",
|
|
1750
|
-
// Brighter blue - secondary text
|
|
1751
|
-
h1: "#d4a5ff",
|
|
1752
|
-
// Rich lavender - h1 headers
|
|
1753
|
-
h2: "#f6ae2d",
|
|
1754
|
-
// Hunyadi Yellow - h2 headers
|
|
1755
|
-
h3: "#9fcfec",
|
|
1756
|
-
// Brighter blue - h3 headers
|
|
1757
|
-
strong: "#f6ae2d",
|
|
1758
|
-
// Hunyadi Yellow - bold text
|
|
1759
|
-
em: "#9fcfec",
|
|
1760
|
-
// Brighter blue - italic text
|
|
1761
|
-
del: "#f6ae2d",
|
|
1762
|
-
// Hunyadi Yellow - deleted text (same as strong)
|
|
1763
|
-
link: "#9fcfec",
|
|
1764
|
-
// Brighter blue - links
|
|
1765
|
-
code: "#c5dde8",
|
|
1766
|
-
// Light blue-gray - inline code
|
|
1767
|
-
codeBg: "#1a232b",
|
|
1768
|
-
// Very dark blue - code background
|
|
1769
|
-
blockquote: "#9fcfec",
|
|
1770
|
-
// Brighter blue - same as italic
|
|
1771
|
-
hr: "#c5dde8",
|
|
1772
|
-
// Light blue-gray - horizontal rules
|
|
1773
|
-
syntaxMarker: "rgba(159, 207, 236, 0.73)",
|
|
1774
|
-
// Brighter blue semi-transparent
|
|
1775
|
-
syntax: "#7a8c98",
|
|
1776
|
-
// Muted gray-blue - syntax highlighting fallback
|
|
1777
|
-
cursor: "#f26419",
|
|
1778
|
-
// Orange Pantone - cursor
|
|
1779
|
-
selection: "rgba(51, 101, 138, 0.4)",
|
|
1780
|
-
// Lapis Lazuli with transparency
|
|
1781
|
-
listMarker: "#f6ae2d",
|
|
1782
|
-
// Hunyadi Yellow - list markers
|
|
1783
|
-
rawLine: "#9fcfec",
|
|
1784
|
-
// Brighter blue - raw line indicators
|
|
1785
|
-
border: "#2a3f52",
|
|
1786
|
-
// Dark blue-gray - borders
|
|
1787
|
-
hoverBg: "#243546",
|
|
1788
|
-
// Slightly lighter charcoal - hover backgrounds
|
|
1789
|
-
primary: "#9fcfec",
|
|
1790
|
-
// Brighter blue - primary accent
|
|
1791
|
-
// Toolbar colors for dark theme
|
|
1792
|
-
toolbarBg: "#1D2D3E",
|
|
1793
|
-
// Darker charcoal - toolbar background
|
|
1794
|
-
toolbarIcon: "#c5dde8",
|
|
1795
|
-
// Light blue-gray - icon color
|
|
1796
|
-
toolbarHover: "#243546",
|
|
1797
|
-
// Slightly lighter charcoal - hover background
|
|
1798
|
-
toolbarActive: "#2a3f52"
|
|
1799
|
-
// Even lighter - active button background
|
|
1800
|
-
}
|
|
1801
|
-
};
|
|
1802
|
-
var themes = {
|
|
1803
|
-
solar,
|
|
1804
|
-
cave,
|
|
1805
|
-
// Aliases for backward compatibility
|
|
1806
|
-
light: solar,
|
|
1807
|
-
dark: cave
|
|
1808
|
-
};
|
|
1809
|
-
function getTheme(theme) {
|
|
1810
|
-
if (typeof theme === "string") {
|
|
1811
|
-
const themeObj = themes[theme] || themes.solar;
|
|
1812
|
-
return { ...themeObj, name: theme };
|
|
1813
|
-
}
|
|
1814
|
-
return theme;
|
|
1815
|
-
}
|
|
1816
|
-
function themeToCSSVars(colors) {
|
|
1817
|
-
const vars = [];
|
|
1818
|
-
for (const [key, value] of Object.entries(colors)) {
|
|
1819
|
-
const varName = key.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
1820
|
-
vars.push(`--${varName}: ${value};`);
|
|
1821
|
-
}
|
|
1822
|
-
return vars.join("\n");
|
|
1823
|
-
}
|
|
1824
|
-
function mergeTheme(baseTheme, customColors = {}) {
|
|
1825
|
-
return {
|
|
1826
|
-
...baseTheme,
|
|
1827
|
-
colors: {
|
|
1828
|
-
...baseTheme.colors,
|
|
1829
|
-
...customColors
|
|
1291
|
+
/* Code inside pre blocks - remove background */
|
|
1292
|
+
.overtype-wrapper .overtype-preview pre code {
|
|
1293
|
+
background: transparent !important;
|
|
1294
|
+
color: var(--code, #0d3b66) !important;
|
|
1295
|
+
font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */
|
|
1830
1296
|
}
|
|
1831
|
-
};
|
|
1832
|
-
}
|
|
1833
1297
|
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
fontFamily = '"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',
|
|
1841
|
-
padding = "20px",
|
|
1842
|
-
theme = null,
|
|
1843
|
-
mobile = {}
|
|
1844
|
-
} = options;
|
|
1845
|
-
const mobileStyles = Object.keys(mobile).length > 0 ? `
|
|
1846
|
-
@media (max-width: 640px) {
|
|
1847
|
-
.overtype-wrapper .overtype-input,
|
|
1848
|
-
.overtype-wrapper .overtype-preview {
|
|
1849
|
-
${Object.entries(mobile).map(([prop, val]) => {
|
|
1850
|
-
const cssProp = prop.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
1851
|
-
return `${cssProp}: ${val} !important;`;
|
|
1852
|
-
}).join("\n ")}
|
|
1853
|
-
}
|
|
1298
|
+
/* Blockquotes */
|
|
1299
|
+
.overtype-wrapper .overtype-preview .blockquote {
|
|
1300
|
+
color: var(--blockquote, #5a7a9b) !important;
|
|
1301
|
+
padding: 0 !important;
|
|
1302
|
+
margin: 0 !important;
|
|
1303
|
+
border: none !important;
|
|
1854
1304
|
}
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1305
|
+
|
|
1306
|
+
/* Links */
|
|
1307
|
+
.overtype-wrapper .overtype-preview a {
|
|
1308
|
+
color: var(--link, #0d3b66) !important;
|
|
1309
|
+
text-decoration: underline !important;
|
|
1310
|
+
font-weight: normal !important;
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
.overtype-wrapper .overtype-preview a:hover {
|
|
1314
|
+
text-decoration: underline !important;
|
|
1315
|
+
color: var(--link, #0d3b66) !important;
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
/* Lists - no list styling */
|
|
1319
|
+
.overtype-wrapper .overtype-preview ul,
|
|
1320
|
+
.overtype-wrapper .overtype-preview ol {
|
|
1321
|
+
list-style: none !important;
|
|
1863
1322
|
margin: 0 !important;
|
|
1864
1323
|
padding: 0 !important;
|
|
1865
|
-
border: 0 !important;
|
|
1866
|
-
|
|
1867
|
-
/* Layout - these can break our layout */
|
|
1868
|
-
/* Don't reset position - it breaks dropdowns */
|
|
1869
|
-
float: none !important;
|
|
1870
|
-
clear: none !important;
|
|
1871
|
-
|
|
1872
|
-
/* Typography - only reset decorative aspects */
|
|
1873
|
-
text-decoration: none !important;
|
|
1874
|
-
text-transform: none !important;
|
|
1875
|
-
letter-spacing: normal !important;
|
|
1876
|
-
|
|
1877
|
-
/* Visual effects that can interfere */
|
|
1878
|
-
box-shadow: none !important;
|
|
1879
|
-
text-shadow: none !important;
|
|
1880
|
-
|
|
1881
|
-
/* Ensure box-sizing is consistent */
|
|
1882
|
-
box-sizing: border-box !important;
|
|
1883
|
-
|
|
1884
|
-
/* Keep inheritance for these */
|
|
1885
|
-
/* font-family, color, line-height, font-size - inherit */
|
|
1886
1324
|
}
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1325
|
+
|
|
1326
|
+
|
|
1327
|
+
/* Horizontal rules */
|
|
1328
|
+
.overtype-wrapper .overtype-preview hr {
|
|
1329
|
+
border: none !important;
|
|
1330
|
+
color: var(--hr, #5a7a9b) !important;
|
|
1331
|
+
margin: 0 !important;
|
|
1332
|
+
padding: 0 !important;
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
.overtype-wrapper .overtype-preview .hr-marker {
|
|
1336
|
+
color: var(--hr, #5a7a9b) !important;
|
|
1337
|
+
opacity: 0.6 !important;
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1340
|
+
/* Code fence markers - with background when not in code block */
|
|
1341
|
+
.overtype-wrapper .overtype-preview .code-fence {
|
|
1342
|
+
color: var(--code, #0d3b66) !important;
|
|
1343
|
+
background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;
|
|
1901
1344
|
}
|
|
1902
1345
|
|
|
1903
|
-
/*
|
|
1904
|
-
.overtype-
|
|
1905
|
-
|
|
1346
|
+
/* Code block lines - background for entire code block */
|
|
1347
|
+
.overtype-wrapper .overtype-preview .code-block-line {
|
|
1348
|
+
background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;
|
|
1906
1349
|
}
|
|
1907
1350
|
|
|
1908
|
-
/*
|
|
1909
|
-
.overtype-
|
|
1910
|
-
|
|
1351
|
+
/* Remove background from code fence when inside code block line */
|
|
1352
|
+
.overtype-wrapper .overtype-preview .code-block-line .code-fence {
|
|
1353
|
+
background: transparent !important;
|
|
1911
1354
|
}
|
|
1912
1355
|
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1356
|
+
/* Raw markdown line */
|
|
1357
|
+
.overtype-wrapper .overtype-preview .raw-line {
|
|
1358
|
+
color: var(--raw-line, #5a7a9b) !important;
|
|
1359
|
+
font-style: normal !important;
|
|
1360
|
+
font-weight: normal !important;
|
|
1918
1361
|
}
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
min-height: 60px !important; /* Minimum usable height */
|
|
1925
|
-
overflow: hidden !important;
|
|
1926
|
-
background: var(--bg-secondary, #ffffff) !important;
|
|
1927
|
-
z-index: 1; /* Below toolbar and dropdown */
|
|
1362
|
+
|
|
1363
|
+
/* Syntax markers */
|
|
1364
|
+
.overtype-wrapper .overtype-preview .syntax-marker {
|
|
1365
|
+
color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;
|
|
1366
|
+
opacity: 0.7 !important;
|
|
1928
1367
|
}
|
|
1929
1368
|
|
|
1930
|
-
/*
|
|
1931
|
-
.overtype-wrapper .overtype-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
font-
|
|
1947
|
-
font-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
writing-mode: horizontal-tb !important;
|
|
1980
|
-
unicode-bidi: normal !important;
|
|
1981
|
-
text-orientation: mixed !important;
|
|
1982
|
-
|
|
1983
|
-
/* Visual effects that could shift perception */
|
|
1984
|
-
text-shadow: none !important;
|
|
1985
|
-
filter: none !important;
|
|
1986
|
-
transform: none !important;
|
|
1987
|
-
zoom: 1 !important;
|
|
1988
|
-
|
|
1989
|
-
/* Vertical alignment */
|
|
1990
|
-
vertical-align: baseline !important;
|
|
1991
|
-
|
|
1992
|
-
/* Size constraints */
|
|
1993
|
-
min-width: 0 !important;
|
|
1994
|
-
min-height: 0 !important;
|
|
1995
|
-
max-width: none !important;
|
|
1996
|
-
max-height: none !important;
|
|
1997
|
-
|
|
1998
|
-
/* Overflow */
|
|
1999
|
-
overflow-y: auto !important;
|
|
2000
|
-
overflow-x: auto !important;
|
|
2001
|
-
/* overscroll-behavior removed to allow scroll-through to parent */
|
|
2002
|
-
scrollbar-width: auto !important;
|
|
2003
|
-
scrollbar-gutter: auto !important;
|
|
2004
|
-
|
|
2005
|
-
/* Animation/transition - disabled to prevent movement */
|
|
2006
|
-
animation: none !important;
|
|
2007
|
-
transition: none !important;
|
|
1369
|
+
/* List markers */
|
|
1370
|
+
.overtype-wrapper .overtype-preview .list-marker {
|
|
1371
|
+
color: var(--list-marker, #ee964b) !important;
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
/* Stats bar */
|
|
1375
|
+
|
|
1376
|
+
/* Stats bar - positioned by flexbox */
|
|
1377
|
+
.overtype-stats {
|
|
1378
|
+
height: 40px !important;
|
|
1379
|
+
padding: 0 20px !important;
|
|
1380
|
+
background: #f8f9fa !important;
|
|
1381
|
+
border-top: 1px solid #e0e0e0 !important;
|
|
1382
|
+
display: flex !important;
|
|
1383
|
+
justify-content: space-between !important;
|
|
1384
|
+
align-items: center !important;
|
|
1385
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
|
|
1386
|
+
font-size: 0.85rem !important;
|
|
1387
|
+
color: #666 !important;
|
|
1388
|
+
flex-shrink: 0 !important; /* Don't shrink */
|
|
1389
|
+
z-index: 10001 !important; /* Above link tooltip */
|
|
1390
|
+
position: relative !important; /* Enable z-index */
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
/* Dark theme stats bar */
|
|
1394
|
+
.overtype-container[data-theme="cave"] .overtype-stats {
|
|
1395
|
+
background: var(--bg-secondary, #1D2D3E) !important;
|
|
1396
|
+
border-top: 1px solid rgba(197, 221, 232, 0.1) !important;
|
|
1397
|
+
color: var(--text, #c5dde8) !important;
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
.overtype-stats .overtype-stat {
|
|
1401
|
+
display: flex !important;
|
|
1402
|
+
align-items: center !important;
|
|
1403
|
+
gap: 5px !important;
|
|
1404
|
+
white-space: nowrap !important;
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
.overtype-stats .live-dot {
|
|
1408
|
+
width: 8px !important;
|
|
1409
|
+
height: 8px !important;
|
|
1410
|
+
background: #4caf50 !important;
|
|
1411
|
+
border-radius: 50% !important;
|
|
1412
|
+
animation: overtype-pulse 2s infinite !important;
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
@keyframes overtype-pulse {
|
|
1416
|
+
0%, 100% { opacity: 1; transform: scale(1); }
|
|
1417
|
+
50% { opacity: 0.6; transform: scale(1.2); }
|
|
2008
1418
|
}
|
|
1419
|
+
|
|
2009
1420
|
|
|
2010
|
-
/*
|
|
2011
|
-
.overtype-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
/*
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
1421
|
+
/* Toolbar Styles */
|
|
1422
|
+
.overtype-toolbar {
|
|
1423
|
+
display: flex !important;
|
|
1424
|
+
align-items: center !important;
|
|
1425
|
+
gap: 4px !important;
|
|
1426
|
+
padding: 8px !important; /* Override reset */
|
|
1427
|
+
background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */
|
|
1428
|
+
border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */
|
|
1429
|
+
overflow-x: auto !important; /* Allow horizontal scrolling */
|
|
1430
|
+
overflow-y: hidden !important; /* Hide vertical overflow */
|
|
1431
|
+
-webkit-overflow-scrolling: touch !important;
|
|
1432
|
+
flex-shrink: 0 !important;
|
|
1433
|
+
height: auto !important;
|
|
1434
|
+
position: relative !important; /* Override reset */
|
|
1435
|
+
z-index: 100 !important; /* Ensure toolbar is above wrapper */
|
|
1436
|
+
scrollbar-width: thin; /* Thin scrollbar on Firefox */
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
/* Thin scrollbar styling */
|
|
1440
|
+
.overtype-toolbar::-webkit-scrollbar {
|
|
1441
|
+
height: 4px;
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
.overtype-toolbar::-webkit-scrollbar-track {
|
|
1445
|
+
background: transparent;
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
.overtype-toolbar::-webkit-scrollbar-thumb {
|
|
1449
|
+
background: rgba(0, 0, 0, 0.2);
|
|
1450
|
+
border-radius: 2px;
|
|
2034
1451
|
}
|
|
2035
1452
|
|
|
2036
|
-
.overtype-
|
|
2037
|
-
|
|
1453
|
+
.overtype-toolbar-button {
|
|
1454
|
+
display: flex;
|
|
1455
|
+
align-items: center;
|
|
1456
|
+
justify-content: center;
|
|
1457
|
+
width: 32px;
|
|
1458
|
+
height: 32px;
|
|
1459
|
+
padding: 0;
|
|
1460
|
+
border: none;
|
|
1461
|
+
border-radius: 6px;
|
|
1462
|
+
background: transparent;
|
|
1463
|
+
color: var(--toolbar-icon, var(--text-secondary, #666));
|
|
1464
|
+
cursor: pointer;
|
|
1465
|
+
transition: all 0.2s ease;
|
|
1466
|
+
flex-shrink: 0;
|
|
2038
1467
|
}
|
|
2039
1468
|
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
pointer-events: none !important;
|
|
2045
|
-
color: var(--text, #0d3b66) !important;
|
|
2046
|
-
background-color: transparent !important;
|
|
2047
|
-
|
|
2048
|
-
/* Prevent text selection */
|
|
2049
|
-
user-select: none !important;
|
|
2050
|
-
-webkit-user-select: none !important;
|
|
2051
|
-
-moz-user-select: none !important;
|
|
2052
|
-
-ms-user-select: none !important;
|
|
1469
|
+
.overtype-toolbar-button svg {
|
|
1470
|
+
width: 20px;
|
|
1471
|
+
height: 20px;
|
|
1472
|
+
fill: currentColor;
|
|
2053
1473
|
}
|
|
2054
1474
|
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
margin: 0 !important;
|
|
2059
|
-
padding: 0 !important;
|
|
2060
|
-
border: none !important;
|
|
2061
|
-
text-align: left !important;
|
|
2062
|
-
text-indent: 0 !important;
|
|
2063
|
-
display: block !important;
|
|
2064
|
-
position: static !important;
|
|
2065
|
-
transform: none !important;
|
|
2066
|
-
min-height: 0 !important;
|
|
2067
|
-
max-height: none !important;
|
|
2068
|
-
line-height: inherit !important;
|
|
2069
|
-
font-size: inherit !important;
|
|
2070
|
-
font-family: inherit !important;
|
|
1475
|
+
.overtype-toolbar-button:hover {
|
|
1476
|
+
background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));
|
|
1477
|
+
color: var(--toolbar-icon, var(--text-primary, #333));
|
|
2071
1478
|
}
|
|
2072
1479
|
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
font-weight: bold !important;
|
|
1480
|
+
.overtype-toolbar-button:active {
|
|
1481
|
+
transform: scale(0.95);
|
|
2076
1482
|
}
|
|
2077
1483
|
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
color: var(--
|
|
1484
|
+
.overtype-toolbar-button.active {
|
|
1485
|
+
background: var(--toolbar-active, var(--primary, #007bff));
|
|
1486
|
+
color: var(--toolbar-icon, var(--text-primary, #333));
|
|
2081
1487
|
}
|
|
2082
|
-
|
|
2083
|
-
|
|
1488
|
+
|
|
1489
|
+
.overtype-toolbar-button:disabled {
|
|
1490
|
+
opacity: 0.5;
|
|
1491
|
+
cursor: not-allowed;
|
|
2084
1492
|
}
|
|
2085
|
-
|
|
2086
|
-
|
|
1493
|
+
|
|
1494
|
+
.overtype-toolbar-separator {
|
|
1495
|
+
width: 1px;
|
|
1496
|
+
height: 24px;
|
|
1497
|
+
background: var(--border, #e0e0e0);
|
|
1498
|
+
margin: 0 4px;
|
|
1499
|
+
flex-shrink: 0;
|
|
2087
1500
|
}
|
|
2088
1501
|
|
|
2089
|
-
/*
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
1502
|
+
/* Adjust wrapper when toolbar is present */
|
|
1503
|
+
/* Mobile toolbar adjustments */
|
|
1504
|
+
@media (max-width: 640px) {
|
|
1505
|
+
.overtype-toolbar {
|
|
1506
|
+
padding: 6px;
|
|
1507
|
+
gap: 2px;
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
.overtype-toolbar-button {
|
|
1511
|
+
width: 36px;
|
|
1512
|
+
height: 36px;
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
.overtype-toolbar-separator {
|
|
1516
|
+
margin: 0 2px;
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
/* Plain mode - hide preview and show textarea text */
|
|
1521
|
+
.overtype-container[data-mode="plain"] .overtype-preview {
|
|
1522
|
+
display: none !important;
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
.overtype-container[data-mode="plain"] .overtype-input {
|
|
1526
|
+
color: var(--text, #0d3b66) !important;
|
|
1527
|
+
/* Use system font stack for better plain text readability */
|
|
1528
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
|
1529
|
+
"Helvetica Neue", Arial, sans-serif !important;
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
/* Ensure textarea remains transparent in overlay mode */
|
|
1533
|
+
.overtype-container:not([data-mode="plain"]) .overtype-input {
|
|
1534
|
+
color: transparent !important;
|
|
2099
1535
|
}
|
|
2100
1536
|
|
|
2101
|
-
/*
|
|
2102
|
-
.overtype-
|
|
2103
|
-
|
|
1537
|
+
/* Dropdown menu styles */
|
|
1538
|
+
.overtype-toolbar-button {
|
|
1539
|
+
position: relative !important; /* Override reset - needed for dropdown */
|
|
2104
1540
|
}
|
|
2105
|
-
|
|
2106
|
-
|
|
1541
|
+
|
|
1542
|
+
.overtype-toolbar-button.dropdown-active {
|
|
1543
|
+
background: var(--toolbar-active, var(--hover-bg, #f0f0f0));
|
|
2107
1544
|
}
|
|
2108
|
-
|
|
2109
|
-
|
|
1545
|
+
|
|
1546
|
+
.overtype-dropdown-menu {
|
|
1547
|
+
position: fixed !important; /* Fixed positioning relative to viewport */
|
|
1548
|
+
background: var(--bg-secondary, white) !important; /* Override reset */
|
|
1549
|
+
border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */
|
|
1550
|
+
border-radius: 6px;
|
|
1551
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */
|
|
1552
|
+
z-index: 10000; /* Very high z-index to ensure visibility */
|
|
1553
|
+
min-width: 150px;
|
|
1554
|
+
padding: 4px 0 !important; /* Override reset */
|
|
1555
|
+
/* Position will be set via JavaScript based on button position */
|
|
2110
1556
|
}
|
|
2111
1557
|
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
1558
|
+
.overtype-dropdown-item {
|
|
1559
|
+
display: flex;
|
|
1560
|
+
align-items: center;
|
|
1561
|
+
width: 100%;
|
|
1562
|
+
padding: 8px 12px;
|
|
1563
|
+
border: none;
|
|
1564
|
+
background: none;
|
|
1565
|
+
text-align: left;
|
|
1566
|
+
cursor: pointer;
|
|
1567
|
+
font-size: 14px;
|
|
1568
|
+
color: var(--text, #333);
|
|
1569
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
2119
1570
|
}
|
|
2120
1571
|
|
|
2121
|
-
.overtype-
|
|
2122
|
-
|
|
2123
|
-
margin: 0 !important;
|
|
2124
|
-
padding: 0 !important;
|
|
2125
|
-
/* Don't set list-style here - let ul/ol control it */
|
|
1572
|
+
.overtype-dropdown-item:hover {
|
|
1573
|
+
background: var(--hover-bg, #f0f0f0);
|
|
2126
1574
|
}
|
|
2127
1575
|
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
1576
|
+
.overtype-dropdown-item.active {
|
|
1577
|
+
font-weight: 600;
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
.overtype-dropdown-check {
|
|
1581
|
+
width: 16px;
|
|
1582
|
+
margin-right: 8px;
|
|
1583
|
+
color: var(--h1, #007bff);
|
|
2132
1584
|
}
|
|
2133
1585
|
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
text-
|
|
2138
|
-
text-decoration-thickness: 1px !important;
|
|
2139
|
-
font-style: italic !important;
|
|
1586
|
+
.overtype-dropdown-icon {
|
|
1587
|
+
width: 20px;
|
|
1588
|
+
margin-right: 8px;
|
|
1589
|
+
text-align: center;
|
|
2140
1590
|
}
|
|
2141
1591
|
|
|
2142
|
-
/*
|
|
2143
|
-
.overtype-
|
|
2144
|
-
|
|
2145
|
-
text-decoration: line-through !important;
|
|
2146
|
-
text-decoration-color: var(--del, #ee964b) !important;
|
|
2147
|
-
text-decoration-thickness: 1px !important;
|
|
1592
|
+
/* Preview mode styles */
|
|
1593
|
+
.overtype-container[data-mode="preview"] .overtype-input {
|
|
1594
|
+
display: none !important;
|
|
2148
1595
|
}
|
|
2149
1596
|
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
padding: 0 !important;
|
|
2155
|
-
border-radius: 2px !important;
|
|
2156
|
-
font-family: inherit !important;
|
|
2157
|
-
font-size: inherit !important;
|
|
2158
|
-
line-height: inherit !important;
|
|
2159
|
-
font-weight: normal !important;
|
|
1597
|
+
.overtype-container[data-mode="preview"] .overtype-preview {
|
|
1598
|
+
pointer-events: auto !important;
|
|
1599
|
+
user-select: text !important;
|
|
1600
|
+
cursor: text !important;
|
|
2160
1601
|
}
|
|
2161
1602
|
|
|
2162
|
-
/*
|
|
2163
|
-
.overtype-
|
|
2164
|
-
|
|
2165
|
-
margin: 0 !important;
|
|
2166
|
-
border-radius: 4px !important;
|
|
2167
|
-
overflow-x: auto !important;
|
|
1603
|
+
/* Hide syntax markers in preview mode */
|
|
1604
|
+
.overtype-container[data-mode="preview"] .syntax-marker {
|
|
1605
|
+
display: none !important;
|
|
2168
1606
|
}
|
|
2169
1607
|
|
|
2170
|
-
/*
|
|
2171
|
-
.overtype-
|
|
2172
|
-
|
|
2173
|
-
|
|
1608
|
+
/* Hide URL part of links in preview mode - extra specificity */
|
|
1609
|
+
.overtype-container[data-mode="preview"] .syntax-marker.url-part,
|
|
1610
|
+
.overtype-container[data-mode="preview"] .url-part {
|
|
1611
|
+
display: none !important;
|
|
2174
1612
|
}
|
|
2175
|
-
|
|
2176
|
-
/*
|
|
2177
|
-
.overtype-
|
|
2178
|
-
|
|
2179
|
-
color: var(--code, #0d3b66) !important;
|
|
2180
|
-
font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */
|
|
1613
|
+
|
|
1614
|
+
/* Hide all syntax markers inside links too */
|
|
1615
|
+
.overtype-container[data-mode="preview"] a .syntax-marker {
|
|
1616
|
+
display: none !important;
|
|
2181
1617
|
}
|
|
2182
1618
|
|
|
2183
|
-
/*
|
|
2184
|
-
.overtype-wrapper .overtype-preview
|
|
2185
|
-
|
|
2186
|
-
|
|
1619
|
+
/* Headers - restore proper sizing in preview mode */
|
|
1620
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h1,
|
|
1621
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h2,
|
|
1622
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h3 {
|
|
1623
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
|
|
1624
|
+
font-weight: 600 !important;
|
|
2187
1625
|
margin: 0 !important;
|
|
2188
|
-
|
|
1626
|
+
display: block !important;
|
|
1627
|
+
color: inherit !important; /* Use parent text color */
|
|
1628
|
+
line-height: 1 !important; /* Tight line height for headings */
|
|
2189
1629
|
}
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
color: var(--link, #0d3b66) !important;
|
|
2194
|
-
text-decoration: underline !important;
|
|
2195
|
-
font-weight: normal !important;
|
|
1630
|
+
|
|
1631
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h1 {
|
|
1632
|
+
font-size: 2em !important;
|
|
2196
1633
|
}
|
|
2197
|
-
|
|
2198
|
-
.overtype-wrapper .overtype-preview
|
|
2199
|
-
|
|
2200
|
-
color: var(--link, #0d3b66) !important;
|
|
1634
|
+
|
|
1635
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h2 {
|
|
1636
|
+
font-size: 1.5em !important;
|
|
2201
1637
|
}
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
.overtype-wrapper .overtype-preview ol {
|
|
2206
|
-
list-style: none !important;
|
|
2207
|
-
margin: 0 !important;
|
|
2208
|
-
padding: 0 !important;
|
|
1638
|
+
|
|
1639
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h3 {
|
|
1640
|
+
font-size: 1.17em !important;
|
|
2209
1641
|
}
|
|
2210
1642
|
|
|
1643
|
+
/* Lists - restore list styling in preview mode */
|
|
1644
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview ul {
|
|
1645
|
+
display: block !important;
|
|
1646
|
+
list-style: disc !important;
|
|
1647
|
+
padding-left: 2em !important;
|
|
1648
|
+
margin: 1em 0 !important;
|
|
1649
|
+
}
|
|
2211
1650
|
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
1651
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview ol {
|
|
1652
|
+
display: block !important;
|
|
1653
|
+
list-style: decimal !important;
|
|
1654
|
+
padding-left: 2em !important;
|
|
1655
|
+
margin: 1em 0 !important;
|
|
1656
|
+
}
|
|
1657
|
+
|
|
1658
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview li {
|
|
1659
|
+
display: list-item !important;
|
|
2216
1660
|
margin: 0 !important;
|
|
2217
1661
|
padding: 0 !important;
|
|
2218
1662
|
}
|
|
2219
1663
|
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
1664
|
+
/* Task list checkboxes - only in preview mode */
|
|
1665
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview li.task-list {
|
|
1666
|
+
list-style: none !important;
|
|
1667
|
+
position: relative !important;
|
|
2223
1668
|
}
|
|
2224
1669
|
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
}
|
|
2230
|
-
|
|
2231
|
-
/* Code block lines - background for entire code block */
|
|
2232
|
-
.overtype-wrapper .overtype-preview .code-block-line {
|
|
2233
|
-
background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;
|
|
2234
|
-
}
|
|
2235
|
-
|
|
2236
|
-
/* Remove background from code fence when inside code block line */
|
|
2237
|
-
.overtype-wrapper .overtype-preview .code-block-line .code-fence {
|
|
2238
|
-
background: transparent !important;
|
|
1670
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview li.task-list input[type="checkbox"] {
|
|
1671
|
+
margin-right: 0.5em !important;
|
|
1672
|
+
cursor: default !important;
|
|
1673
|
+
vertical-align: middle !important;
|
|
2239
1674
|
}
|
|
2240
1675
|
|
|
2241
|
-
/*
|
|
2242
|
-
.overtype-wrapper .overtype-preview .
|
|
2243
|
-
|
|
2244
|
-
font-style: normal !important;
|
|
2245
|
-
font-weight: normal !important;
|
|
1676
|
+
/* Task list in normal mode - keep syntax visible */
|
|
1677
|
+
.overtype-container:not([data-mode="preview"]) .overtype-wrapper .overtype-preview li.task-list {
|
|
1678
|
+
list-style: none !important;
|
|
2246
1679
|
}
|
|
2247
1680
|
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
opacity: 0.7 !important;
|
|
1681
|
+
.overtype-container:not([data-mode="preview"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {
|
|
1682
|
+
color: var(--syntax, #999999) !important;
|
|
1683
|
+
font-weight: normal !important;
|
|
2252
1684
|
}
|
|
2253
1685
|
|
|
2254
|
-
/*
|
|
2255
|
-
.overtype-
|
|
2256
|
-
|
|
1686
|
+
/* Links - make clickable in preview mode */
|
|
1687
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview a {
|
|
1688
|
+
pointer-events: auto !important;
|
|
1689
|
+
cursor: pointer !important;
|
|
1690
|
+
color: var(--link, #0066cc) !important;
|
|
1691
|
+
text-decoration: underline !important;
|
|
2257
1692
|
}
|
|
2258
1693
|
|
|
2259
|
-
/*
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
display:
|
|
2268
|
-
justify-content: space-between !important;
|
|
2269
|
-
align-items: center !important;
|
|
2270
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
|
|
2271
|
-
font-size: 0.85rem !important;
|
|
2272
|
-
color: #666 !important;
|
|
2273
|
-
flex-shrink: 0 !important; /* Don't shrink */
|
|
2274
|
-
z-index: 10001 !important; /* Above link tooltip */
|
|
2275
|
-
position: relative !important; /* Enable z-index */
|
|
1694
|
+
/* Code blocks - proper pre/code styling in preview mode */
|
|
1695
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview pre.code-block {
|
|
1696
|
+
background: #2d2d2d !important;
|
|
1697
|
+
color: #f8f8f2 !important;
|
|
1698
|
+
padding: 1.2em !important;
|
|
1699
|
+
border-radius: 3px !important;
|
|
1700
|
+
overflow-x: auto !important;
|
|
1701
|
+
margin: 0 !important;
|
|
1702
|
+
display: block !important;
|
|
2276
1703
|
}
|
|
2277
1704
|
|
|
2278
|
-
/*
|
|
2279
|
-
.overtype-container[data-theme="cave"] .overtype-
|
|
2280
|
-
background:
|
|
2281
|
-
border-top: 1px solid rgba(197, 221, 232, 0.1) !important;
|
|
2282
|
-
color: var(--text, #c5dde8) !important;
|
|
1705
|
+
/* Cave theme code block background in preview mode */
|
|
1706
|
+
.overtype-container[data-theme="cave"][data-mode="preview"] .overtype-wrapper .overtype-preview pre.code-block {
|
|
1707
|
+
background: #11171F !important;
|
|
2283
1708
|
}
|
|
2284
|
-
|
|
2285
|
-
.overtype-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
1709
|
+
|
|
1710
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview pre.code-block code {
|
|
1711
|
+
background: transparent !important;
|
|
1712
|
+
color: inherit !important;
|
|
1713
|
+
padding: 0 !important;
|
|
1714
|
+
font-family: ${fontFamily} !important;
|
|
1715
|
+
font-size: 0.9em !important;
|
|
1716
|
+
line-height: 1.4 !important;
|
|
2290
1717
|
}
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
background: #4caf50 !important;
|
|
2296
|
-
border-radius: 50% !important;
|
|
2297
|
-
animation: overtype-pulse 2s infinite !important;
|
|
1718
|
+
|
|
1719
|
+
/* Hide old code block lines and fences in preview mode */
|
|
1720
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview .code-block-line {
|
|
1721
|
+
display: none !important;
|
|
2298
1722
|
}
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
50% { opacity: 0.6; transform: scale(1.2); }
|
|
1723
|
+
|
|
1724
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview .code-fence {
|
|
1725
|
+
display: none !important;
|
|
2303
1726
|
}
|
|
2304
|
-
|
|
2305
1727
|
|
|
2306
|
-
/*
|
|
2307
|
-
.overtype-
|
|
2308
|
-
display:
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */
|
|
2314
|
-
overflow-x: auto !important; /* Allow horizontal scrolling */
|
|
2315
|
-
overflow-y: hidden !important; /* Hide vertical overflow */
|
|
2316
|
-
-webkit-overflow-scrolling: touch !important;
|
|
2317
|
-
flex-shrink: 0 !important;
|
|
2318
|
-
height: auto !important;
|
|
2319
|
-
position: relative !important; /* Override reset */
|
|
2320
|
-
z-index: 100 !important; /* Ensure toolbar is above wrapper */
|
|
2321
|
-
scrollbar-width: thin; /* Thin scrollbar on Firefox */
|
|
1728
|
+
/* Blockquotes - enhanced styling in preview mode */
|
|
1729
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview .blockquote {
|
|
1730
|
+
display: block !important;
|
|
1731
|
+
border-left: 4px solid var(--blockquote, #ddd) !important;
|
|
1732
|
+
padding-left: 1em !important;
|
|
1733
|
+
margin: 1em 0 !important;
|
|
1734
|
+
font-style: italic !important;
|
|
2322
1735
|
}
|
|
2323
|
-
|
|
2324
|
-
/*
|
|
2325
|
-
.overtype-
|
|
2326
|
-
|
|
1736
|
+
|
|
1737
|
+
/* Typography improvements in preview mode */
|
|
1738
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview {
|
|
1739
|
+
font-family: Georgia, 'Times New Roman', serif !important;
|
|
1740
|
+
font-size: 16px !important;
|
|
1741
|
+
line-height: 1.8 !important;
|
|
1742
|
+
color: var(--text, #333) !important; /* Consistent text color */
|
|
2327
1743
|
}
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
1744
|
+
|
|
1745
|
+
/* Inline code in preview mode - keep monospace */
|
|
1746
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview code {
|
|
1747
|
+
font-family: ${fontFamily} !important;
|
|
1748
|
+
font-size: 0.9em !important;
|
|
1749
|
+
background: rgba(135, 131, 120, 0.15) !important;
|
|
1750
|
+
padding: 0.2em 0.4em !important;
|
|
1751
|
+
border-radius: 3px !important;
|
|
2331
1752
|
}
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
1753
|
+
|
|
1754
|
+
/* Strong and em elements in preview mode */
|
|
1755
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview strong {
|
|
1756
|
+
font-weight: 700 !important;
|
|
1757
|
+
color: inherit !important; /* Use parent text color */
|
|
2336
1758
|
}
|
|
2337
1759
|
|
|
2338
|
-
.overtype-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
justify-content: center;
|
|
2342
|
-
width: 32px;
|
|
2343
|
-
height: 32px;
|
|
2344
|
-
padding: 0;
|
|
2345
|
-
border: none;
|
|
2346
|
-
border-radius: 6px;
|
|
2347
|
-
background: transparent;
|
|
2348
|
-
color: var(--toolbar-icon, var(--text-secondary, #666));
|
|
2349
|
-
cursor: pointer;
|
|
2350
|
-
transition: all 0.2s ease;
|
|
2351
|
-
flex-shrink: 0;
|
|
1760
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview em {
|
|
1761
|
+
font-style: italic !important;
|
|
1762
|
+
color: inherit !important; /* Use parent text color */
|
|
2352
1763
|
}
|
|
2353
1764
|
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
1765
|
+
/* HR in preview mode */
|
|
1766
|
+
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview .hr-marker {
|
|
1767
|
+
display: block !important;
|
|
1768
|
+
border-top: 2px solid var(--hr, #ddd) !important;
|
|
1769
|
+
text-indent: -9999px !important;
|
|
1770
|
+
height: 2px !important;
|
|
2358
1771
|
}
|
|
2359
1772
|
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
1773
|
+
/* Link Tooltip - Base styles (all browsers) */
|
|
1774
|
+
.overtype-link-tooltip {
|
|
1775
|
+
/* Visual styles that work for both positioning methods */
|
|
1776
|
+
background: #333 !important;
|
|
1777
|
+
color: white !important;
|
|
1778
|
+
padding: 6px 10px !important;
|
|
1779
|
+
border-radius: 16px !important;
|
|
1780
|
+
font-size: 12px !important;
|
|
1781
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
|
|
1782
|
+
display: none !important;
|
|
1783
|
+
z-index: 10000 !important;
|
|
1784
|
+
cursor: pointer !important;
|
|
1785
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;
|
|
1786
|
+
max-width: 300px !important;
|
|
1787
|
+
white-space: nowrap !important;
|
|
1788
|
+
overflow: hidden !important;
|
|
1789
|
+
text-overflow: ellipsis !important;
|
|
1790
|
+
|
|
1791
|
+
/* Base positioning for Floating UI fallback */
|
|
1792
|
+
position: absolute;
|
|
2363
1793
|
}
|
|
2364
1794
|
|
|
2365
|
-
.overtype-
|
|
2366
|
-
|
|
1795
|
+
.overtype-link-tooltip.visible {
|
|
1796
|
+
display: flex !important;
|
|
2367
1797
|
}
|
|
2368
1798
|
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
1799
|
+
/* CSS Anchor Positioning (modern browsers only) */
|
|
1800
|
+
@supports (position-anchor: --x) and (position-area: center) {
|
|
1801
|
+
.overtype-link-tooltip {
|
|
1802
|
+
/* Only anchor positioning specific properties */
|
|
1803
|
+
position-anchor: var(--target-anchor, --link-0);
|
|
1804
|
+
position-area: block-end center;
|
|
1805
|
+
margin-top: 8px !important;
|
|
1806
|
+
position-try: most-width block-end inline-end, flip-inline, block-start center;
|
|
1807
|
+
position-visibility: anchors-visible;
|
|
1808
|
+
}
|
|
2372
1809
|
}
|
|
2373
1810
|
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
1811
|
+
${mobileStyles}
|
|
1812
|
+
`;
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1815
|
+
// node_modules/markdown-actions/dist/markdown-actions.esm.js
|
|
1816
|
+
var __defProp2 = Object.defineProperty;
|
|
1817
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
1818
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
1819
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
1820
|
+
var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1821
|
+
var __spreadValues = (a, b) => {
|
|
1822
|
+
for (var prop in b || (b = {}))
|
|
1823
|
+
if (__hasOwnProp.call(b, prop))
|
|
1824
|
+
__defNormalProp2(a, prop, b[prop]);
|
|
1825
|
+
if (__getOwnPropSymbols)
|
|
1826
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
1827
|
+
if (__propIsEnum.call(b, prop))
|
|
1828
|
+
__defNormalProp2(a, prop, b[prop]);
|
|
1829
|
+
}
|
|
1830
|
+
return a;
|
|
1831
|
+
};
|
|
1832
|
+
var FORMATS = {
|
|
1833
|
+
bold: {
|
|
1834
|
+
prefix: "**",
|
|
1835
|
+
suffix: "**",
|
|
1836
|
+
trimFirst: true
|
|
1837
|
+
},
|
|
1838
|
+
italic: {
|
|
1839
|
+
prefix: "_",
|
|
1840
|
+
suffix: "_",
|
|
1841
|
+
trimFirst: true
|
|
1842
|
+
},
|
|
1843
|
+
code: {
|
|
1844
|
+
prefix: "`",
|
|
1845
|
+
suffix: "`",
|
|
1846
|
+
blockPrefix: "```",
|
|
1847
|
+
blockSuffix: "```"
|
|
1848
|
+
},
|
|
1849
|
+
link: {
|
|
1850
|
+
prefix: "[",
|
|
1851
|
+
suffix: "](url)",
|
|
1852
|
+
replaceNext: "url",
|
|
1853
|
+
scanFor: "https?://"
|
|
1854
|
+
},
|
|
1855
|
+
bulletList: {
|
|
1856
|
+
prefix: "- ",
|
|
1857
|
+
multiline: true,
|
|
1858
|
+
unorderedList: true
|
|
1859
|
+
},
|
|
1860
|
+
numberedList: {
|
|
1861
|
+
prefix: "1. ",
|
|
1862
|
+
multiline: true,
|
|
1863
|
+
orderedList: true
|
|
1864
|
+
},
|
|
1865
|
+
quote: {
|
|
1866
|
+
prefix: "> ",
|
|
1867
|
+
multiline: true,
|
|
1868
|
+
surroundWithNewlines: true
|
|
1869
|
+
},
|
|
1870
|
+
taskList: {
|
|
1871
|
+
prefix: "- [ ] ",
|
|
1872
|
+
multiline: true,
|
|
1873
|
+
surroundWithNewlines: true
|
|
1874
|
+
},
|
|
1875
|
+
header1: { prefix: "# " },
|
|
1876
|
+
header2: { prefix: "## " },
|
|
1877
|
+
header3: { prefix: "### " },
|
|
1878
|
+
header4: { prefix: "#### " },
|
|
1879
|
+
header5: { prefix: "##### " },
|
|
1880
|
+
header6: { prefix: "###### " }
|
|
1881
|
+
};
|
|
1882
|
+
function getDefaultStyle() {
|
|
1883
|
+
return {
|
|
1884
|
+
prefix: "",
|
|
1885
|
+
suffix: "",
|
|
1886
|
+
blockPrefix: "",
|
|
1887
|
+
blockSuffix: "",
|
|
1888
|
+
multiline: false,
|
|
1889
|
+
replaceNext: "",
|
|
1890
|
+
prefixSpace: false,
|
|
1891
|
+
scanFor: "",
|
|
1892
|
+
surroundWithNewlines: false,
|
|
1893
|
+
orderedList: false,
|
|
1894
|
+
unorderedList: false,
|
|
1895
|
+
trimFirst: false
|
|
1896
|
+
};
|
|
1897
|
+
}
|
|
1898
|
+
function mergeWithDefaults(format) {
|
|
1899
|
+
return __spreadValues(__spreadValues({}, getDefaultStyle()), format);
|
|
1900
|
+
}
|
|
1901
|
+
var debugMode = false;
|
|
1902
|
+
function getDebugMode() {
|
|
1903
|
+
return debugMode;
|
|
1904
|
+
}
|
|
1905
|
+
function debugLog(funcName, message, data) {
|
|
1906
|
+
if (!debugMode)
|
|
1907
|
+
return;
|
|
1908
|
+
console.group(`\u{1F50D} ${funcName}`);
|
|
1909
|
+
console.log(message);
|
|
1910
|
+
if (data) {
|
|
1911
|
+
console.log("Data:", data);
|
|
1912
|
+
}
|
|
1913
|
+
console.groupEnd();
|
|
1914
|
+
}
|
|
1915
|
+
function debugSelection(textarea, label) {
|
|
1916
|
+
if (!debugMode)
|
|
1917
|
+
return;
|
|
1918
|
+
const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
1919
|
+
console.group(`\u{1F4CD} Selection: ${label}`);
|
|
1920
|
+
console.log("Position:", `${textarea.selectionStart}-${textarea.selectionEnd}`);
|
|
1921
|
+
console.log("Selected text:", JSON.stringify(selected));
|
|
1922
|
+
console.log("Length:", selected.length);
|
|
1923
|
+
const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);
|
|
1924
|
+
const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));
|
|
1925
|
+
console.log("Context:", JSON.stringify(before) + "[SELECTION]" + JSON.stringify(after));
|
|
1926
|
+
console.groupEnd();
|
|
1927
|
+
}
|
|
1928
|
+
function debugResult(result) {
|
|
1929
|
+
if (!debugMode)
|
|
1930
|
+
return;
|
|
1931
|
+
console.group("\u{1F4DD} Result");
|
|
1932
|
+
console.log("Text to insert:", JSON.stringify(result.text));
|
|
1933
|
+
console.log("New selection:", `${result.selectionStart}-${result.selectionEnd}`);
|
|
1934
|
+
console.groupEnd();
|
|
1935
|
+
}
|
|
1936
|
+
var canInsertText = null;
|
|
1937
|
+
function insertText(textarea, { text, selectionStart, selectionEnd }) {
|
|
1938
|
+
const debugMode2 = getDebugMode();
|
|
1939
|
+
if (debugMode2) {
|
|
1940
|
+
console.group("\u{1F527} insertText");
|
|
1941
|
+
console.log("Current selection:", `${textarea.selectionStart}-${textarea.selectionEnd}`);
|
|
1942
|
+
console.log("Text to insert:", JSON.stringify(text));
|
|
1943
|
+
console.log("New selection to set:", selectionStart, "-", selectionEnd);
|
|
1944
|
+
}
|
|
1945
|
+
textarea.focus();
|
|
1946
|
+
const originalSelectionStart = textarea.selectionStart;
|
|
1947
|
+
const originalSelectionEnd = textarea.selectionEnd;
|
|
1948
|
+
const before = textarea.value.slice(0, originalSelectionStart);
|
|
1949
|
+
const after = textarea.value.slice(originalSelectionEnd);
|
|
1950
|
+
if (debugMode2) {
|
|
1951
|
+
console.log("Before text (last 20):", JSON.stringify(before.slice(-20)));
|
|
1952
|
+
console.log("After text (first 20):", JSON.stringify(after.slice(0, 20)));
|
|
1953
|
+
console.log("Selected text being replaced:", JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));
|
|
1954
|
+
}
|
|
1955
|
+
const originalValue = textarea.value;
|
|
1956
|
+
const hasSelection = originalSelectionStart !== originalSelectionEnd;
|
|
1957
|
+
if (canInsertText === null || canInsertText === true) {
|
|
1958
|
+
textarea.contentEditable = "true";
|
|
1959
|
+
try {
|
|
1960
|
+
canInsertText = document.execCommand("insertText", false, text);
|
|
1961
|
+
if (debugMode2)
|
|
1962
|
+
console.log("execCommand returned:", canInsertText, "for text with", text.split("\n").length, "lines");
|
|
1963
|
+
} catch (error) {
|
|
1964
|
+
canInsertText = false;
|
|
1965
|
+
if (debugMode2)
|
|
1966
|
+
console.log("execCommand threw error:", error);
|
|
2377
1967
|
}
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
1968
|
+
textarea.contentEditable = "false";
|
|
1969
|
+
}
|
|
1970
|
+
if (debugMode2) {
|
|
1971
|
+
console.log("canInsertText before:", canInsertText);
|
|
1972
|
+
console.log("execCommand result:", canInsertText);
|
|
1973
|
+
}
|
|
1974
|
+
if (canInsertText) {
|
|
1975
|
+
const expectedValue = before + text + after;
|
|
1976
|
+
const actualValue = textarea.value;
|
|
1977
|
+
if (debugMode2) {
|
|
1978
|
+
console.log("Expected length:", expectedValue.length);
|
|
1979
|
+
console.log("Actual length:", actualValue.length);
|
|
2385
1980
|
}
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
padding: 6px;
|
|
2392
|
-
gap: 2px;
|
|
1981
|
+
if (actualValue !== expectedValue) {
|
|
1982
|
+
if (debugMode2) {
|
|
1983
|
+
console.log("execCommand changed the value but not as expected");
|
|
1984
|
+
console.log("Expected:", JSON.stringify(expectedValue.slice(0, 100)));
|
|
1985
|
+
console.log("Actual:", JSON.stringify(actualValue.slice(0, 100)));
|
|
2393
1986
|
}
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
if (!canInsertText) {
|
|
1990
|
+
if (debugMode2)
|
|
1991
|
+
console.log("Using manual insertion");
|
|
1992
|
+
if (textarea.value === originalValue) {
|
|
1993
|
+
if (debugMode2)
|
|
1994
|
+
console.log("Value unchanged, doing manual replacement");
|
|
1995
|
+
try {
|
|
1996
|
+
document.execCommand("ms-beginUndoUnit");
|
|
1997
|
+
} catch (e) {
|
|
2398
1998
|
}
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
1999
|
+
textarea.value = before + text + after;
|
|
2000
|
+
try {
|
|
2001
|
+
document.execCommand("ms-endUndoUnit");
|
|
2002
|
+
} catch (e) {
|
|
2402
2003
|
}
|
|
2004
|
+
textarea.dispatchEvent(new CustomEvent("input", { bubbles: true, cancelable: true }));
|
|
2005
|
+
} else {
|
|
2006
|
+
if (debugMode2)
|
|
2007
|
+
console.log("Value was changed by execCommand, skipping manual insertion");
|
|
2403
2008
|
}
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
.
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
.
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
.overtype-dropdown-item {
|
|
2444
|
-
display: flex;
|
|
2445
|
-
align-items: center;
|
|
2446
|
-
width: 100%;
|
|
2447
|
-
padding: 8px 12px;
|
|
2448
|
-
border: none;
|
|
2449
|
-
background: none;
|
|
2450
|
-
text-align: left;
|
|
2451
|
-
cursor: pointer;
|
|
2452
|
-
font-size: 14px;
|
|
2453
|
-
color: var(--text, #333);
|
|
2454
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
2455
|
-
}
|
|
2456
|
-
|
|
2457
|
-
.overtype-dropdown-item:hover {
|
|
2458
|
-
background: var(--hover-bg, #f0f0f0);
|
|
2459
|
-
}
|
|
2460
|
-
|
|
2461
|
-
.overtype-dropdown-item.active {
|
|
2462
|
-
font-weight: 600;
|
|
2463
|
-
}
|
|
2464
|
-
|
|
2465
|
-
.overtype-dropdown-check {
|
|
2466
|
-
width: 16px;
|
|
2467
|
-
margin-right: 8px;
|
|
2468
|
-
color: var(--h1, #007bff);
|
|
2469
|
-
}
|
|
2470
|
-
|
|
2471
|
-
.overtype-dropdown-icon {
|
|
2472
|
-
width: 20px;
|
|
2473
|
-
margin-right: 8px;
|
|
2474
|
-
text-align: center;
|
|
2475
|
-
}
|
|
2476
|
-
|
|
2477
|
-
/* Preview mode styles */
|
|
2478
|
-
.overtype-container[data-mode="preview"] .overtype-input {
|
|
2479
|
-
display: none !important;
|
|
2480
|
-
}
|
|
2481
|
-
|
|
2482
|
-
.overtype-container[data-mode="preview"] .overtype-preview {
|
|
2483
|
-
pointer-events: auto !important;
|
|
2484
|
-
user-select: text !important;
|
|
2485
|
-
cursor: text !important;
|
|
2486
|
-
}
|
|
2487
|
-
|
|
2488
|
-
/* Hide syntax markers in preview mode */
|
|
2489
|
-
.overtype-container[data-mode="preview"] .syntax-marker {
|
|
2490
|
-
display: none !important;
|
|
2491
|
-
}
|
|
2492
|
-
|
|
2493
|
-
/* Hide URL part of links in preview mode - extra specificity */
|
|
2494
|
-
.overtype-container[data-mode="preview"] .syntax-marker.url-part,
|
|
2495
|
-
.overtype-container[data-mode="preview"] .url-part {
|
|
2496
|
-
display: none !important;
|
|
2497
|
-
}
|
|
2498
|
-
|
|
2499
|
-
/* Hide all syntax markers inside links too */
|
|
2500
|
-
.overtype-container[data-mode="preview"] a .syntax-marker {
|
|
2501
|
-
display: none !important;
|
|
2502
|
-
}
|
|
2503
|
-
|
|
2504
|
-
/* Headers - restore proper sizing in preview mode */
|
|
2505
|
-
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h1,
|
|
2506
|
-
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h2,
|
|
2507
|
-
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h3 {
|
|
2508
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
|
|
2509
|
-
font-weight: 600 !important;
|
|
2510
|
-
margin: 0 !important;
|
|
2511
|
-
display: block !important;
|
|
2512
|
-
color: inherit !important; /* Use parent text color */
|
|
2513
|
-
line-height: 1 !important; /* Tight line height for headings */
|
|
2514
|
-
}
|
|
2515
|
-
|
|
2516
|
-
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h1 {
|
|
2517
|
-
font-size: 2em !important;
|
|
2518
|
-
}
|
|
2519
|
-
|
|
2520
|
-
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h2 {
|
|
2521
|
-
font-size: 1.5em !important;
|
|
2522
|
-
}
|
|
2523
|
-
|
|
2524
|
-
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h3 {
|
|
2525
|
-
font-size: 1.17em !important;
|
|
2526
|
-
}
|
|
2527
|
-
|
|
2528
|
-
/* Lists - restore list styling in preview mode */
|
|
2529
|
-
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview ul {
|
|
2530
|
-
display: block !important;
|
|
2531
|
-
list-style: disc !important;
|
|
2532
|
-
padding-left: 2em !important;
|
|
2533
|
-
margin: 1em 0 !important;
|
|
2534
|
-
}
|
|
2535
|
-
|
|
2536
|
-
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview ol {
|
|
2537
|
-
display: block !important;
|
|
2538
|
-
list-style: decimal !important;
|
|
2539
|
-
padding-left: 2em !important;
|
|
2540
|
-
margin: 1em 0 !important;
|
|
2541
|
-
}
|
|
2542
|
-
|
|
2543
|
-
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview li {
|
|
2544
|
-
display: list-item !important;
|
|
2545
|
-
margin: 0 !important;
|
|
2546
|
-
padding: 0 !important;
|
|
2547
|
-
}
|
|
2548
|
-
|
|
2549
|
-
/* Task list checkboxes - only in preview mode */
|
|
2550
|
-
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview li.task-list {
|
|
2551
|
-
list-style: none !important;
|
|
2552
|
-
position: relative !important;
|
|
2009
|
+
}
|
|
2010
|
+
if (debugMode2)
|
|
2011
|
+
console.log("Setting selection range:", selectionStart, selectionEnd);
|
|
2012
|
+
if (selectionStart != null && selectionEnd != null) {
|
|
2013
|
+
textarea.setSelectionRange(selectionStart, selectionEnd);
|
|
2014
|
+
} else {
|
|
2015
|
+
textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd);
|
|
2016
|
+
}
|
|
2017
|
+
if (debugMode2) {
|
|
2018
|
+
console.log("Final value length:", textarea.value.length);
|
|
2019
|
+
console.groupEnd();
|
|
2020
|
+
}
|
|
2021
|
+
}
|
|
2022
|
+
function isMultipleLines(string) {
|
|
2023
|
+
return string.trim().split("\n").length > 1;
|
|
2024
|
+
}
|
|
2025
|
+
function wordSelectionStart(text, i) {
|
|
2026
|
+
let index = i;
|
|
2027
|
+
while (text[index] && text[index - 1] != null && !text[index - 1].match(/\s/)) {
|
|
2028
|
+
index--;
|
|
2029
|
+
}
|
|
2030
|
+
return index;
|
|
2031
|
+
}
|
|
2032
|
+
function wordSelectionEnd(text, i, multiline) {
|
|
2033
|
+
let index = i;
|
|
2034
|
+
const breakpoint = multiline ? /\n/ : /\s/;
|
|
2035
|
+
while (text[index] && !text[index].match(breakpoint)) {
|
|
2036
|
+
index++;
|
|
2037
|
+
}
|
|
2038
|
+
return index;
|
|
2039
|
+
}
|
|
2040
|
+
function expandSelectionToLine(textarea) {
|
|
2041
|
+
const lines = textarea.value.split("\n");
|
|
2042
|
+
let counter = 0;
|
|
2043
|
+
for (let index = 0; index < lines.length; index++) {
|
|
2044
|
+
const lineLength = lines[index].length + 1;
|
|
2045
|
+
if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {
|
|
2046
|
+
textarea.selectionStart = counter;
|
|
2553
2047
|
}
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2048
|
+
if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {
|
|
2049
|
+
if (index === lines.length - 1) {
|
|
2050
|
+
textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length);
|
|
2051
|
+
} else {
|
|
2052
|
+
textarea.selectionEnd = counter + lineLength - 1;
|
|
2053
|
+
}
|
|
2559
2054
|
}
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2055
|
+
counter += lineLength;
|
|
2056
|
+
}
|
|
2057
|
+
}
|
|
2058
|
+
function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {
|
|
2059
|
+
if (textarea.selectionStart === textarea.selectionEnd) {
|
|
2060
|
+
textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart);
|
|
2061
|
+
textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline);
|
|
2062
|
+
} else {
|
|
2063
|
+
const expandedSelectionStart = textarea.selectionStart - prefixToUse.length;
|
|
2064
|
+
const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length;
|
|
2065
|
+
const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse;
|
|
2066
|
+
const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse;
|
|
2067
|
+
if (beginsWithPrefix && endsWithSuffix) {
|
|
2068
|
+
textarea.selectionStart = expandedSelectionStart;
|
|
2069
|
+
textarea.selectionEnd = expandedSelectionEnd;
|
|
2564
2070
|
}
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2071
|
+
}
|
|
2072
|
+
return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
2073
|
+
}
|
|
2074
|
+
function newlinesToSurroundSelectedText(textarea) {
|
|
2075
|
+
const beforeSelection = textarea.value.slice(0, textarea.selectionStart);
|
|
2076
|
+
const afterSelection = textarea.value.slice(textarea.selectionEnd);
|
|
2077
|
+
const breaksBefore = beforeSelection.match(/\n*$/);
|
|
2078
|
+
const breaksAfter = afterSelection.match(/^\n*/);
|
|
2079
|
+
const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0;
|
|
2080
|
+
const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0;
|
|
2081
|
+
let newlinesToAppend = "";
|
|
2082
|
+
let newlinesToPrepend = "";
|
|
2083
|
+
if (beforeSelection.match(/\S/) && newlinesBeforeSelection < 2) {
|
|
2084
|
+
newlinesToAppend = "\n".repeat(2 - newlinesBeforeSelection);
|
|
2085
|
+
}
|
|
2086
|
+
if (afterSelection.match(/\S/) && newlinesAfterSelection < 2) {
|
|
2087
|
+
newlinesToPrepend = "\n".repeat(2 - newlinesAfterSelection);
|
|
2088
|
+
}
|
|
2089
|
+
return { newlinesToAppend, newlinesToPrepend };
|
|
2090
|
+
}
|
|
2091
|
+
function applyLineOperation(textarea, operation, options = {}) {
|
|
2092
|
+
const originalStart = textarea.selectionStart;
|
|
2093
|
+
const originalEnd = textarea.selectionEnd;
|
|
2094
|
+
const noInitialSelection = originalStart === originalEnd;
|
|
2095
|
+
const value = textarea.value;
|
|
2096
|
+
let lineStart = originalStart;
|
|
2097
|
+
while (lineStart > 0 && value[lineStart - 1] !== "\n") {
|
|
2098
|
+
lineStart--;
|
|
2099
|
+
}
|
|
2100
|
+
if (noInitialSelection) {
|
|
2101
|
+
let lineEnd = originalStart;
|
|
2102
|
+
while (lineEnd < value.length && value[lineEnd] !== "\n") {
|
|
2103
|
+
lineEnd++;
|
|
2569
2104
|
}
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2105
|
+
textarea.selectionStart = lineStart;
|
|
2106
|
+
textarea.selectionEnd = lineEnd;
|
|
2107
|
+
} else {
|
|
2108
|
+
expandSelectionToLine(textarea);
|
|
2109
|
+
}
|
|
2110
|
+
const result = operation(textarea);
|
|
2111
|
+
if (options.adjustSelection) {
|
|
2112
|
+
const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
2113
|
+
const isRemoving = selectedText.startsWith(options.prefix);
|
|
2114
|
+
const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart);
|
|
2115
|
+
result.selectionStart = adjusted.start;
|
|
2116
|
+
result.selectionEnd = adjusted.end;
|
|
2117
|
+
} else if (options.prefix) {
|
|
2118
|
+
const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
2119
|
+
const isRemoving = selectedText.startsWith(options.prefix);
|
|
2120
|
+
if (noInitialSelection) {
|
|
2121
|
+
if (isRemoving) {
|
|
2122
|
+
result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart);
|
|
2123
|
+
result.selectionEnd = result.selectionStart;
|
|
2124
|
+
} else {
|
|
2125
|
+
result.selectionStart = originalStart + options.prefix.length;
|
|
2126
|
+
result.selectionEnd = result.selectionStart;
|
|
2127
|
+
}
|
|
2128
|
+
} else {
|
|
2129
|
+
if (isRemoving) {
|
|
2130
|
+
result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart);
|
|
2131
|
+
result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart);
|
|
2132
|
+
} else {
|
|
2133
|
+
result.selectionStart = originalStart + options.prefix.length;
|
|
2134
|
+
result.selectionEnd = originalEnd + options.prefix.length;
|
|
2135
|
+
}
|
|
2577
2136
|
}
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2137
|
+
}
|
|
2138
|
+
return result;
|
|
2139
|
+
}
|
|
2140
|
+
function blockStyle(textarea, style) {
|
|
2141
|
+
let newlinesToAppend;
|
|
2142
|
+
let newlinesToPrepend;
|
|
2143
|
+
const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style;
|
|
2144
|
+
const originalSelectionStart = textarea.selectionStart;
|
|
2145
|
+
const originalSelectionEnd = textarea.selectionEnd;
|
|
2146
|
+
let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
2147
|
+
let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}
|
|
2148
|
+
` : prefix;
|
|
2149
|
+
let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `
|
|
2150
|
+
${blockSuffix}` : suffix;
|
|
2151
|
+
if (prefixSpace) {
|
|
2152
|
+
const beforeSelection = textarea.value[textarea.selectionStart - 1];
|
|
2153
|
+
if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\s/)) {
|
|
2154
|
+
prefixToUse = ` ${prefixToUse}`;
|
|
2588
2155
|
}
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2156
|
+
}
|
|
2157
|
+
selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline);
|
|
2158
|
+
let selectionStart = textarea.selectionStart;
|
|
2159
|
+
let selectionEnd = textarea.selectionEnd;
|
|
2160
|
+
const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0;
|
|
2161
|
+
if (surroundWithNewlines) {
|
|
2162
|
+
const ref = newlinesToSurroundSelectedText(textarea);
|
|
2163
|
+
newlinesToAppend = ref.newlinesToAppend;
|
|
2164
|
+
newlinesToPrepend = ref.newlinesToPrepend;
|
|
2165
|
+
prefixToUse = newlinesToAppend + prefix;
|
|
2166
|
+
suffixToUse += newlinesToPrepend;
|
|
2167
|
+
}
|
|
2168
|
+
if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {
|
|
2169
|
+
const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length);
|
|
2170
|
+
if (originalSelectionStart === originalSelectionEnd) {
|
|
2171
|
+
let position = originalSelectionStart - prefixToUse.length;
|
|
2172
|
+
position = Math.max(position, selectionStart);
|
|
2173
|
+
position = Math.min(position, selectionStart + replacementText.length);
|
|
2174
|
+
selectionStart = selectionEnd = position;
|
|
2175
|
+
} else {
|
|
2176
|
+
selectionEnd = selectionStart + replacementText.length;
|
|
2593
2177
|
}
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2178
|
+
return { text: replacementText, selectionStart, selectionEnd };
|
|
2179
|
+
} else if (!hasReplaceNext) {
|
|
2180
|
+
let replacementText = prefixToUse + selectedText + suffixToUse;
|
|
2181
|
+
selectionStart = originalSelectionStart + prefixToUse.length;
|
|
2182
|
+
selectionEnd = originalSelectionEnd + prefixToUse.length;
|
|
2183
|
+
const whitespaceEdges = selectedText.match(/^\s*|\s*$/g);
|
|
2184
|
+
if (trimFirst && whitespaceEdges) {
|
|
2185
|
+
const leadingWhitespace = whitespaceEdges[0] || "";
|
|
2186
|
+
const trailingWhitespace = whitespaceEdges[1] || "";
|
|
2187
|
+
replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace;
|
|
2188
|
+
selectionStart += leadingWhitespace.length;
|
|
2189
|
+
selectionEnd -= trailingWhitespace.length;
|
|
2602
2190
|
}
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2191
|
+
return { text: replacementText, selectionStart, selectionEnd };
|
|
2192
|
+
} else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {
|
|
2193
|
+
suffixToUse = suffixToUse.replace(replaceNext, selectedText);
|
|
2194
|
+
const replacementText = prefixToUse + suffixToUse;
|
|
2195
|
+
selectionStart = selectionEnd = selectionStart + prefixToUse.length;
|
|
2196
|
+
return { text: replacementText, selectionStart, selectionEnd };
|
|
2197
|
+
} else {
|
|
2198
|
+
const replacementText = prefixToUse + selectedText + suffixToUse;
|
|
2199
|
+
selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext);
|
|
2200
|
+
selectionEnd = selectionStart + replaceNext.length;
|
|
2201
|
+
return { text: replacementText, selectionStart, selectionEnd };
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
function multilineStyle(textarea, style) {
|
|
2205
|
+
const { prefix, suffix, surroundWithNewlines } = style;
|
|
2206
|
+
let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
2207
|
+
let selectionStart = textarea.selectionStart;
|
|
2208
|
+
let selectionEnd = textarea.selectionEnd;
|
|
2209
|
+
const lines = text.split("\n");
|
|
2210
|
+
const undoStyle = lines.every((line) => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)));
|
|
2211
|
+
if (undoStyle) {
|
|
2212
|
+
text = lines.map((line) => {
|
|
2213
|
+
let result = line.slice(prefix.length);
|
|
2214
|
+
if (suffix) {
|
|
2215
|
+
result = result.slice(0, result.length - suffix.length);
|
|
2216
|
+
}
|
|
2217
|
+
return result;
|
|
2218
|
+
}).join("\n");
|
|
2219
|
+
selectionEnd = selectionStart + text.length;
|
|
2220
|
+
} else {
|
|
2221
|
+
text = lines.map((line) => prefix + line + (suffix || "")).join("\n");
|
|
2222
|
+
if (surroundWithNewlines) {
|
|
2223
|
+
const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea);
|
|
2224
|
+
selectionStart += newlinesToAppend.length;
|
|
2225
|
+
selectionEnd = selectionStart + text.length;
|
|
2226
|
+
text = newlinesToAppend + text + newlinesToPrepend;
|
|
2607
2227
|
}
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2228
|
+
}
|
|
2229
|
+
return { text, selectionStart, selectionEnd };
|
|
2230
|
+
}
|
|
2231
|
+
function undoOrderedListStyle(text) {
|
|
2232
|
+
const lines = text.split("\n");
|
|
2233
|
+
const orderedListRegex = /^\d+\.\s+/;
|
|
2234
|
+
const shouldUndoOrderedList = lines.every((line) => orderedListRegex.test(line));
|
|
2235
|
+
let result = lines;
|
|
2236
|
+
if (shouldUndoOrderedList) {
|
|
2237
|
+
result = lines.map((line) => line.replace(orderedListRegex, ""));
|
|
2238
|
+
}
|
|
2239
|
+
return {
|
|
2240
|
+
text: result.join("\n"),
|
|
2241
|
+
processed: shouldUndoOrderedList
|
|
2242
|
+
};
|
|
2243
|
+
}
|
|
2244
|
+
function undoUnorderedListStyle(text) {
|
|
2245
|
+
const lines = text.split("\n");
|
|
2246
|
+
const unorderedListPrefix = "- ";
|
|
2247
|
+
const shouldUndoUnorderedList = lines.every((line) => line.startsWith(unorderedListPrefix));
|
|
2248
|
+
let result = lines;
|
|
2249
|
+
if (shouldUndoUnorderedList) {
|
|
2250
|
+
result = lines.map((line) => line.slice(unorderedListPrefix.length));
|
|
2251
|
+
}
|
|
2252
|
+
return {
|
|
2253
|
+
text: result.join("\n"),
|
|
2254
|
+
processed: shouldUndoUnorderedList
|
|
2255
|
+
};
|
|
2256
|
+
}
|
|
2257
|
+
function makePrefix(index, unorderedList) {
|
|
2258
|
+
if (unorderedList) {
|
|
2259
|
+
return "- ";
|
|
2260
|
+
} else {
|
|
2261
|
+
return `${index + 1}. `;
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
function clearExistingListStyle(style, selectedText) {
|
|
2265
|
+
let undoResult;
|
|
2266
|
+
let undoResultOppositeList;
|
|
2267
|
+
let pristineText;
|
|
2268
|
+
if (style.orderedList) {
|
|
2269
|
+
undoResult = undoOrderedListStyle(selectedText);
|
|
2270
|
+
undoResultOppositeList = undoUnorderedListStyle(undoResult.text);
|
|
2271
|
+
pristineText = undoResultOppositeList.text;
|
|
2272
|
+
} else {
|
|
2273
|
+
undoResult = undoUnorderedListStyle(selectedText);
|
|
2274
|
+
undoResultOppositeList = undoOrderedListStyle(undoResult.text);
|
|
2275
|
+
pristineText = undoResultOppositeList.text;
|
|
2276
|
+
}
|
|
2277
|
+
return [undoResult, undoResultOppositeList, pristineText];
|
|
2278
|
+
}
|
|
2279
|
+
function listStyle(textarea, style) {
|
|
2280
|
+
const noInitialSelection = textarea.selectionStart === textarea.selectionEnd;
|
|
2281
|
+
let selectionStart = textarea.selectionStart;
|
|
2282
|
+
let selectionEnd = textarea.selectionEnd;
|
|
2283
|
+
expandSelectionToLine(textarea);
|
|
2284
|
+
const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
2285
|
+
const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText);
|
|
2286
|
+
const prefixedLines = pristineText.split("\n").map((value, index) => {
|
|
2287
|
+
return `${makePrefix(index, style.unorderedList)}${value}`;
|
|
2288
|
+
});
|
|
2289
|
+
const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {
|
|
2290
|
+
return previousValue + makePrefix(currentIndex, style.unorderedList).length;
|
|
2291
|
+
}, 0);
|
|
2292
|
+
const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {
|
|
2293
|
+
return previousValue + makePrefix(currentIndex, !style.unorderedList).length;
|
|
2294
|
+
}, 0);
|
|
2295
|
+
if (undoResult.processed) {
|
|
2296
|
+
if (noInitialSelection) {
|
|
2297
|
+
selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0);
|
|
2298
|
+
selectionEnd = selectionStart;
|
|
2299
|
+
} else {
|
|
2300
|
+
selectionStart = textarea.selectionStart;
|
|
2301
|
+
selectionEnd = textarea.selectionEnd - totalPrefixLength;
|
|
2611
2302
|
}
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2303
|
+
return { text: pristineText, selectionStart, selectionEnd };
|
|
2304
|
+
}
|
|
2305
|
+
const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea);
|
|
2306
|
+
const text = newlinesToAppend + prefixedLines.join("\n") + newlinesToPrepend;
|
|
2307
|
+
if (noInitialSelection) {
|
|
2308
|
+
selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0);
|
|
2309
|
+
selectionEnd = selectionStart;
|
|
2310
|
+
} else {
|
|
2311
|
+
if (undoResultOppositeList.processed) {
|
|
2312
|
+
selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0);
|
|
2313
|
+
selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList;
|
|
2314
|
+
} else {
|
|
2315
|
+
selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0);
|
|
2316
|
+
selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength;
|
|
2620
2317
|
}
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2318
|
+
}
|
|
2319
|
+
return { text, selectionStart, selectionEnd };
|
|
2320
|
+
}
|
|
2321
|
+
function applyListStyle(textarea, style) {
|
|
2322
|
+
const result = applyLineOperation(
|
|
2323
|
+
textarea,
|
|
2324
|
+
(ta) => listStyle(ta, style),
|
|
2325
|
+
{
|
|
2326
|
+
// Custom selection adjustment for lists
|
|
2327
|
+
adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {
|
|
2328
|
+
const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd);
|
|
2329
|
+
const orderedListRegex = /^\d+\.\s+/;
|
|
2330
|
+
const unorderedListRegex = /^- /;
|
|
2331
|
+
const hasOrderedList = orderedListRegex.test(currentLine);
|
|
2332
|
+
const hasUnorderedList = unorderedListRegex.test(currentLine);
|
|
2333
|
+
const isRemovingCurrent = style.orderedList && hasOrderedList || style.unorderedList && hasUnorderedList;
|
|
2334
|
+
if (selStart === selEnd) {
|
|
2335
|
+
if (isRemovingCurrent) {
|
|
2336
|
+
const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex);
|
|
2337
|
+
const prefixLength = prefixMatch ? prefixMatch[0].length : 0;
|
|
2338
|
+
return {
|
|
2339
|
+
start: Math.max(selStart - prefixLength, lineStart),
|
|
2340
|
+
end: Math.max(selStart - prefixLength, lineStart)
|
|
2341
|
+
};
|
|
2342
|
+
} else if (hasOrderedList || hasUnorderedList) {
|
|
2343
|
+
const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex);
|
|
2344
|
+
const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0;
|
|
2345
|
+
const newPrefixLength = style.unorderedList ? 2 : 3;
|
|
2346
|
+
const adjustment = newPrefixLength - oldPrefixLength;
|
|
2347
|
+
return {
|
|
2348
|
+
start: selStart + adjustment,
|
|
2349
|
+
end: selStart + adjustment
|
|
2350
|
+
};
|
|
2351
|
+
} else {
|
|
2352
|
+
const prefixLength = style.unorderedList ? 2 : 3;
|
|
2353
|
+
return {
|
|
2354
|
+
start: selStart + prefixLength,
|
|
2355
|
+
end: selStart + prefixLength
|
|
2356
|
+
};
|
|
2357
|
+
}
|
|
2358
|
+
} else {
|
|
2359
|
+
if (isRemovingCurrent) {
|
|
2360
|
+
const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex);
|
|
2361
|
+
const prefixLength = prefixMatch ? prefixMatch[0].length : 0;
|
|
2362
|
+
return {
|
|
2363
|
+
start: Math.max(selStart - prefixLength, lineStart),
|
|
2364
|
+
end: Math.max(selEnd - prefixLength, lineStart)
|
|
2365
|
+
};
|
|
2366
|
+
} else if (hasOrderedList || hasUnorderedList) {
|
|
2367
|
+
const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex);
|
|
2368
|
+
const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0;
|
|
2369
|
+
const newPrefixLength = style.unorderedList ? 2 : 3;
|
|
2370
|
+
const adjustment = newPrefixLength - oldPrefixLength;
|
|
2371
|
+
return {
|
|
2372
|
+
start: selStart + adjustment,
|
|
2373
|
+
end: selEnd + adjustment
|
|
2374
|
+
};
|
|
2375
|
+
} else {
|
|
2376
|
+
const prefixLength = style.unorderedList ? 2 : 3;
|
|
2377
|
+
return {
|
|
2378
|
+
start: selStart + prefixLength,
|
|
2379
|
+
end: selEnd + prefixLength
|
|
2380
|
+
};
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
2628
2384
|
}
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2385
|
+
);
|
|
2386
|
+
insertText(textarea, result);
|
|
2387
|
+
}
|
|
2388
|
+
function getActiveFormats(textarea) {
|
|
2389
|
+
if (!textarea)
|
|
2390
|
+
return [];
|
|
2391
|
+
const formats = [];
|
|
2392
|
+
const { selectionStart, selectionEnd, value } = textarea;
|
|
2393
|
+
const lines = value.split("\n");
|
|
2394
|
+
let lineStart = 0;
|
|
2395
|
+
let currentLine = "";
|
|
2396
|
+
for (const line of lines) {
|
|
2397
|
+
if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {
|
|
2398
|
+
currentLine = line;
|
|
2399
|
+
break;
|
|
2637
2400
|
}
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2401
|
+
lineStart += line.length + 1;
|
|
2402
|
+
}
|
|
2403
|
+
if (currentLine.startsWith("- ")) {
|
|
2404
|
+
if (currentLine.startsWith("- [ ] ") || currentLine.startsWith("- [x] ")) {
|
|
2405
|
+
formats.push("task-list");
|
|
2406
|
+
} else {
|
|
2407
|
+
formats.push("bullet-list");
|
|
2643
2408
|
}
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2409
|
+
}
|
|
2410
|
+
if (/^\d+\.\s/.test(currentLine)) {
|
|
2411
|
+
formats.push("numbered-list");
|
|
2412
|
+
}
|
|
2413
|
+
if (currentLine.startsWith("> ")) {
|
|
2414
|
+
formats.push("quote");
|
|
2415
|
+
}
|
|
2416
|
+
if (currentLine.startsWith("# "))
|
|
2417
|
+
formats.push("header");
|
|
2418
|
+
if (currentLine.startsWith("## "))
|
|
2419
|
+
formats.push("header-2");
|
|
2420
|
+
if (currentLine.startsWith("### "))
|
|
2421
|
+
formats.push("header-3");
|
|
2422
|
+
const lookBehind = Math.max(0, selectionStart - 10);
|
|
2423
|
+
const lookAhead = Math.min(value.length, selectionEnd + 10);
|
|
2424
|
+
const surrounding = value.slice(lookBehind, lookAhead);
|
|
2425
|
+
if (surrounding.includes("**")) {
|
|
2426
|
+
const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
|
|
2427
|
+
const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
|
|
2428
|
+
const lastOpenBold = beforeCursor.lastIndexOf("**");
|
|
2429
|
+
const nextCloseBold = afterCursor.indexOf("**");
|
|
2430
|
+
if (lastOpenBold !== -1 && nextCloseBold !== -1) {
|
|
2431
|
+
formats.push("bold");
|
|
2648
2432
|
}
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2433
|
+
}
|
|
2434
|
+
if (surrounding.includes("_")) {
|
|
2435
|
+
const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
|
|
2436
|
+
const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
|
|
2437
|
+
const lastOpenItalic = beforeCursor.lastIndexOf("_");
|
|
2438
|
+
const nextCloseItalic = afterCursor.indexOf("_");
|
|
2439
|
+
if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {
|
|
2440
|
+
formats.push("italic");
|
|
2656
2441
|
}
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
.
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
padding: 6px 10px !important;
|
|
2664
|
-
border-radius: 16px !important;
|
|
2665
|
-
font-size: 12px !important;
|
|
2666
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
|
|
2667
|
-
display: none !important;
|
|
2668
|
-
z-index: 10000 !important;
|
|
2669
|
-
cursor: pointer !important;
|
|
2670
|
-
box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;
|
|
2671
|
-
max-width: 300px !important;
|
|
2672
|
-
white-space: nowrap !important;
|
|
2673
|
-
overflow: hidden !important;
|
|
2674
|
-
text-overflow: ellipsis !important;
|
|
2675
|
-
|
|
2676
|
-
/* Base positioning for Floating UI fallback */
|
|
2677
|
-
position: absolute;
|
|
2442
|
+
}
|
|
2443
|
+
if (surrounding.includes("`")) {
|
|
2444
|
+
const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
|
|
2445
|
+
const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
|
|
2446
|
+
if (beforeCursor.includes("`") && afterCursor.includes("`")) {
|
|
2447
|
+
formats.push("code");
|
|
2678
2448
|
}
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2449
|
+
}
|
|
2450
|
+
if (surrounding.includes("[") && surrounding.includes("]")) {
|
|
2451
|
+
const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart);
|
|
2452
|
+
const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100));
|
|
2453
|
+
const lastOpenBracket = beforeCursor.lastIndexOf("[");
|
|
2454
|
+
const nextCloseBracket = afterCursor.indexOf("]");
|
|
2455
|
+
if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {
|
|
2456
|
+
const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10);
|
|
2457
|
+
if (afterBracket.startsWith("(")) {
|
|
2458
|
+
formats.push("link");
|
|
2459
|
+
}
|
|
2682
2460
|
}
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2461
|
+
}
|
|
2462
|
+
return formats;
|
|
2463
|
+
}
|
|
2464
|
+
function toggleBold(textarea) {
|
|
2465
|
+
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
2466
|
+
return;
|
|
2467
|
+
debugLog("toggleBold", "Starting");
|
|
2468
|
+
debugSelection(textarea, "Before");
|
|
2469
|
+
const style = mergeWithDefaults(FORMATS.bold);
|
|
2470
|
+
const result = blockStyle(textarea, style);
|
|
2471
|
+
debugResult(result);
|
|
2472
|
+
insertText(textarea, result);
|
|
2473
|
+
debugSelection(textarea, "After");
|
|
2474
|
+
}
|
|
2475
|
+
function toggleItalic(textarea) {
|
|
2476
|
+
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
2477
|
+
return;
|
|
2478
|
+
const style = mergeWithDefaults(FORMATS.italic);
|
|
2479
|
+
const result = blockStyle(textarea, style);
|
|
2480
|
+
insertText(textarea, result);
|
|
2481
|
+
}
|
|
2482
|
+
function toggleCode(textarea) {
|
|
2483
|
+
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
2484
|
+
return;
|
|
2485
|
+
const style = mergeWithDefaults(FORMATS.code);
|
|
2486
|
+
const result = blockStyle(textarea, style);
|
|
2487
|
+
insertText(textarea, result);
|
|
2488
|
+
}
|
|
2489
|
+
function insertLink(textarea, options = {}) {
|
|
2490
|
+
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
2491
|
+
return;
|
|
2492
|
+
const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
2493
|
+
let style = mergeWithDefaults(FORMATS.link);
|
|
2494
|
+
const isURL = selectedText && selectedText.match(/^https?:\/\//);
|
|
2495
|
+
if (isURL && !options.url) {
|
|
2496
|
+
style.suffix = `](${selectedText})`;
|
|
2497
|
+
style.replaceNext = "";
|
|
2498
|
+
} else if (options.url) {
|
|
2499
|
+
style.suffix = `](${options.url})`;
|
|
2500
|
+
style.replaceNext = "";
|
|
2501
|
+
}
|
|
2502
|
+
if (options.text && !selectedText) {
|
|
2503
|
+
const pos = textarea.selectionStart;
|
|
2504
|
+
textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos);
|
|
2505
|
+
textarea.selectionStart = pos;
|
|
2506
|
+
textarea.selectionEnd = pos + options.text.length;
|
|
2507
|
+
}
|
|
2508
|
+
const result = blockStyle(textarea, style);
|
|
2509
|
+
insertText(textarea, result);
|
|
2510
|
+
}
|
|
2511
|
+
function toggleBulletList(textarea) {
|
|
2512
|
+
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
2513
|
+
return;
|
|
2514
|
+
const style = mergeWithDefaults(FORMATS.bulletList);
|
|
2515
|
+
applyListStyle(textarea, style);
|
|
2516
|
+
}
|
|
2517
|
+
function toggleNumberedList(textarea) {
|
|
2518
|
+
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
2519
|
+
return;
|
|
2520
|
+
const style = mergeWithDefaults(FORMATS.numberedList);
|
|
2521
|
+
applyListStyle(textarea, style);
|
|
2522
|
+
}
|
|
2523
|
+
function toggleQuote(textarea) {
|
|
2524
|
+
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
2525
|
+
return;
|
|
2526
|
+
debugLog("toggleQuote", "Starting");
|
|
2527
|
+
debugSelection(textarea, "Initial");
|
|
2528
|
+
const style = mergeWithDefaults(FORMATS.quote);
|
|
2529
|
+
const result = applyLineOperation(
|
|
2530
|
+
textarea,
|
|
2531
|
+
(ta) => multilineStyle(ta, style),
|
|
2532
|
+
{ prefix: style.prefix }
|
|
2533
|
+
);
|
|
2534
|
+
debugResult(result);
|
|
2535
|
+
insertText(textarea, result);
|
|
2536
|
+
debugSelection(textarea, "Final");
|
|
2537
|
+
}
|
|
2538
|
+
function toggleTaskList(textarea) {
|
|
2539
|
+
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
2540
|
+
return;
|
|
2541
|
+
const style = mergeWithDefaults(FORMATS.taskList);
|
|
2542
|
+
const result = applyLineOperation(
|
|
2543
|
+
textarea,
|
|
2544
|
+
(ta) => multilineStyle(ta, style),
|
|
2545
|
+
{ prefix: style.prefix }
|
|
2546
|
+
);
|
|
2547
|
+
insertText(textarea, result);
|
|
2548
|
+
}
|
|
2549
|
+
function insertHeader(textarea, level = 1, toggle = false) {
|
|
2550
|
+
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
2551
|
+
return;
|
|
2552
|
+
if (level < 1 || level > 6)
|
|
2553
|
+
level = 1;
|
|
2554
|
+
debugLog("insertHeader", `============ START ============`);
|
|
2555
|
+
debugLog("insertHeader", `Level: ${level}, Toggle: ${toggle}`);
|
|
2556
|
+
debugLog("insertHeader", `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);
|
|
2557
|
+
const headerKey = `header${level === 1 ? "1" : level}`;
|
|
2558
|
+
const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1);
|
|
2559
|
+
debugLog("insertHeader", `Style prefix: "${style.prefix}"`);
|
|
2560
|
+
const value = textarea.value;
|
|
2561
|
+
const originalStart = textarea.selectionStart;
|
|
2562
|
+
const originalEnd = textarea.selectionEnd;
|
|
2563
|
+
let lineStart = originalStart;
|
|
2564
|
+
while (lineStart > 0 && value[lineStart - 1] !== "\n") {
|
|
2565
|
+
lineStart--;
|
|
2566
|
+
}
|
|
2567
|
+
let lineEnd = originalEnd;
|
|
2568
|
+
while (lineEnd < value.length && value[lineEnd] !== "\n") {
|
|
2569
|
+
lineEnd++;
|
|
2570
|
+
}
|
|
2571
|
+
const currentLineContent = value.slice(lineStart, lineEnd);
|
|
2572
|
+
debugLog("insertHeader", `Current line (before): "${currentLineContent}"`);
|
|
2573
|
+
const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\s*/);
|
|
2574
|
+
const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0;
|
|
2575
|
+
const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0;
|
|
2576
|
+
debugLog("insertHeader", `Existing header check:`);
|
|
2577
|
+
debugLog("insertHeader", ` - Match: ${existingHeaderMatch ? `"${existingHeaderMatch[0]}"` : "none"}`);
|
|
2578
|
+
debugLog("insertHeader", ` - Existing level: ${existingLevel}`);
|
|
2579
|
+
debugLog("insertHeader", ` - Existing prefix length: ${existingPrefixLength}`);
|
|
2580
|
+
debugLog("insertHeader", ` - Target level: ${level}`);
|
|
2581
|
+
const shouldToggleOff = toggle && existingLevel === level;
|
|
2582
|
+
debugLog("insertHeader", `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);
|
|
2583
|
+
const result = applyLineOperation(
|
|
2584
|
+
textarea,
|
|
2585
|
+
(ta) => {
|
|
2586
|
+
const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd);
|
|
2587
|
+
debugLog("insertHeader", `Line in operation: "${currentLine}"`);
|
|
2588
|
+
const cleanedLine = currentLine.replace(/^#{1,6}\s*/, "");
|
|
2589
|
+
debugLog("insertHeader", `Cleaned line: "${cleanedLine}"`);
|
|
2590
|
+
let newLine;
|
|
2591
|
+
if (shouldToggleOff) {
|
|
2592
|
+
debugLog("insertHeader", "ACTION: Toggling OFF - removing header");
|
|
2593
|
+
newLine = cleanedLine;
|
|
2594
|
+
} else if (existingLevel > 0) {
|
|
2595
|
+
debugLog("insertHeader", `ACTION: Replacing H${existingLevel} with H${level}`);
|
|
2596
|
+
newLine = style.prefix + cleanedLine;
|
|
2597
|
+
} else {
|
|
2598
|
+
debugLog("insertHeader", "ACTION: Adding new header");
|
|
2599
|
+
newLine = style.prefix + cleanedLine;
|
|
2600
|
+
}
|
|
2601
|
+
debugLog("insertHeader", `New line: "${newLine}"`);
|
|
2602
|
+
return {
|
|
2603
|
+
text: newLine,
|
|
2604
|
+
selectionStart: ta.selectionStart,
|
|
2605
|
+
selectionEnd: ta.selectionEnd
|
|
2606
|
+
};
|
|
2607
|
+
},
|
|
2608
|
+
{
|
|
2609
|
+
prefix: style.prefix,
|
|
2610
|
+
// Custom selection adjustment for headers
|
|
2611
|
+
adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {
|
|
2612
|
+
debugLog("insertHeader", `Adjusting selection:`);
|
|
2613
|
+
debugLog("insertHeader", ` - isRemoving param: ${isRemoving}`);
|
|
2614
|
+
debugLog("insertHeader", ` - shouldToggleOff: ${shouldToggleOff}`);
|
|
2615
|
+
debugLog("insertHeader", ` - selStart: ${selStart}, selEnd: ${selEnd}`);
|
|
2616
|
+
debugLog("insertHeader", ` - lineStartPos: ${lineStartPos}`);
|
|
2617
|
+
if (shouldToggleOff) {
|
|
2618
|
+
const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos);
|
|
2619
|
+
debugLog("insertHeader", ` - Removing header, adjusting by -${existingPrefixLength}`);
|
|
2620
|
+
return {
|
|
2621
|
+
start: adjustment,
|
|
2622
|
+
end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)
|
|
2623
|
+
};
|
|
2624
|
+
} else if (existingPrefixLength > 0) {
|
|
2625
|
+
const prefixDiff = style.prefix.length - existingPrefixLength;
|
|
2626
|
+
debugLog("insertHeader", ` - Replacing header, adjusting by ${prefixDiff}`);
|
|
2627
|
+
return {
|
|
2628
|
+
start: selStart + prefixDiff,
|
|
2629
|
+
end: selEnd + prefixDiff
|
|
2630
|
+
};
|
|
2631
|
+
} else {
|
|
2632
|
+
debugLog("insertHeader", ` - Adding header, adjusting by +${style.prefix.length}`);
|
|
2633
|
+
return {
|
|
2634
|
+
start: selStart + style.prefix.length,
|
|
2635
|
+
end: selEnd + style.prefix.length
|
|
2636
|
+
};
|
|
2637
|
+
}
|
|
2693
2638
|
}
|
|
2694
2639
|
}
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2640
|
+
);
|
|
2641
|
+
debugLog("insertHeader", `Final result: text="${result.text}", cursor=${result.selectionStart}-${result.selectionEnd}`);
|
|
2642
|
+
debugLog("insertHeader", `============ END ============`);
|
|
2643
|
+
insertText(textarea, result);
|
|
2644
|
+
}
|
|
2645
|
+
function toggleH1(textarea) {
|
|
2646
|
+
insertHeader(textarea, 1, true);
|
|
2647
|
+
}
|
|
2648
|
+
function toggleH2(textarea) {
|
|
2649
|
+
insertHeader(textarea, 2, true);
|
|
2650
|
+
}
|
|
2651
|
+
function toggleH3(textarea) {
|
|
2652
|
+
insertHeader(textarea, 3, true);
|
|
2653
|
+
}
|
|
2654
|
+
function getActiveFormats2(textarea) {
|
|
2655
|
+
return getActiveFormats(textarea);
|
|
2698
2656
|
}
|
|
2699
2657
|
|
|
2700
2658
|
// src/toolbar.js
|
|
@@ -2754,55 +2712,43 @@ var Toolbar = class {
|
|
|
2754
2712
|
});
|
|
2755
2713
|
return button;
|
|
2756
2714
|
}
|
|
2757
|
-
button._clickHandler =
|
|
2715
|
+
button._clickHandler = (e) => {
|
|
2758
2716
|
e.preventDefault();
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
if (buttonConfig.action) {
|
|
2762
|
-
await buttonConfig.action({
|
|
2763
|
-
editor: this.editor,
|
|
2764
|
-
getValue: () => this.editor.getValue(),
|
|
2765
|
-
setValue: (value) => this.editor.setValue(value),
|
|
2766
|
-
event: e
|
|
2767
|
-
});
|
|
2768
|
-
}
|
|
2769
|
-
} catch (error) {
|
|
2770
|
-
console.error(`Button "${buttonConfig.name}" error:`, error);
|
|
2771
|
-
this.editor.wrapper.dispatchEvent(new CustomEvent("button-error", {
|
|
2772
|
-
detail: { buttonName: buttonConfig.name, error }
|
|
2773
|
-
}));
|
|
2774
|
-
button.classList.add("button-error");
|
|
2775
|
-
button.style.animation = "buttonError 0.3s";
|
|
2776
|
-
setTimeout(() => {
|
|
2777
|
-
button.classList.remove("button-error");
|
|
2778
|
-
button.style.animation = "";
|
|
2779
|
-
}, 300);
|
|
2780
|
-
}
|
|
2717
|
+
const actionId = buttonConfig.actionId || buttonConfig.name;
|
|
2718
|
+
this.editor.performAction(actionId, e);
|
|
2781
2719
|
};
|
|
2782
2720
|
button.addEventListener("click", button._clickHandler);
|
|
2783
2721
|
return button;
|
|
2784
2722
|
}
|
|
2785
2723
|
/**
|
|
2786
|
-
* Handle button action programmatically
|
|
2787
|
-
*
|
|
2724
|
+
* Handle button action programmatically
|
|
2725
|
+
* Accepts either an actionId string or a buttonConfig object (backwards compatible)
|
|
2726
|
+
* @param {string|Object} actionIdOrConfig - Action identifier string or button config object
|
|
2727
|
+
* @returns {Promise<boolean>} Whether the action was executed
|
|
2788
2728
|
*/
|
|
2789
|
-
async handleAction(
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
await
|
|
2729
|
+
async handleAction(actionIdOrConfig) {
|
|
2730
|
+
if (actionIdOrConfig && typeof actionIdOrConfig === "object" && typeof actionIdOrConfig.action === "function") {
|
|
2731
|
+
this.editor.textarea.focus();
|
|
2732
|
+
try {
|
|
2733
|
+
await actionIdOrConfig.action({
|
|
2794
2734
|
editor: this.editor,
|
|
2795
2735
|
getValue: () => this.editor.getValue(),
|
|
2796
2736
|
setValue: (value) => this.editor.setValue(value),
|
|
2797
2737
|
event: null
|
|
2798
2738
|
});
|
|
2739
|
+
return true;
|
|
2740
|
+
} catch (error) {
|
|
2741
|
+
console.error(`Action "${actionIdOrConfig.name}" error:`, error);
|
|
2742
|
+
this.editor.wrapper.dispatchEvent(new CustomEvent("button-error", {
|
|
2743
|
+
detail: { buttonName: actionIdOrConfig.name, error }
|
|
2744
|
+
}));
|
|
2745
|
+
return false;
|
|
2799
2746
|
}
|
|
2800
|
-
} catch (error) {
|
|
2801
|
-
console.error(`Action "${buttonConfig.name}" error:`, error);
|
|
2802
|
-
this.editor.wrapper.dispatchEvent(new CustomEvent("button-error", {
|
|
2803
|
-
detail: { buttonName: buttonConfig.name, error }
|
|
2804
|
-
}));
|
|
2805
2747
|
}
|
|
2748
|
+
if (typeof actionIdOrConfig === "string") {
|
|
2749
|
+
return this.editor.performAction(actionIdOrConfig, null);
|
|
2750
|
+
}
|
|
2751
|
+
return false;
|
|
2806
2752
|
}
|
|
2807
2753
|
/**
|
|
2808
2754
|
* Sanitize SVG to prevent XSS
|
|
@@ -2972,6 +2918,7 @@ var LinkTooltip = class {
|
|
|
2972
2918
|
this.visibilityChangeHandler = null;
|
|
2973
2919
|
this.useFloatingUI = false;
|
|
2974
2920
|
this.floatingUI = null;
|
|
2921
|
+
this.isTooltipHovered = false;
|
|
2975
2922
|
this.init();
|
|
2976
2923
|
}
|
|
2977
2924
|
async init() {
|
|
@@ -3005,14 +2952,25 @@ var LinkTooltip = class {
|
|
|
3005
2952
|
this.hide();
|
|
3006
2953
|
}
|
|
3007
2954
|
});
|
|
3008
|
-
this.editor.textarea.addEventListener("blur", () =>
|
|
2955
|
+
this.editor.textarea.addEventListener("blur", () => {
|
|
2956
|
+
if (!this.isTooltipHovered) {
|
|
2957
|
+
this.hide();
|
|
2958
|
+
}
|
|
2959
|
+
});
|
|
3009
2960
|
this.visibilityChangeHandler = () => {
|
|
3010
2961
|
if (document.hidden) {
|
|
3011
2962
|
this.hide();
|
|
3012
2963
|
}
|
|
3013
2964
|
};
|
|
3014
2965
|
document.addEventListener("visibilitychange", this.visibilityChangeHandler);
|
|
3015
|
-
this.tooltip.addEventListener("mouseenter", () =>
|
|
2966
|
+
this.tooltip.addEventListener("mouseenter", () => {
|
|
2967
|
+
this.isTooltipHovered = true;
|
|
2968
|
+
this.cancelHide();
|
|
2969
|
+
});
|
|
2970
|
+
this.tooltip.addEventListener("mouseleave", () => {
|
|
2971
|
+
this.isTooltipHovered = false;
|
|
2972
|
+
this.scheduleHide();
|
|
2973
|
+
});
|
|
3016
2974
|
}
|
|
3017
2975
|
createTooltip() {
|
|
3018
2976
|
this.tooltip = document.createElement("div");
|
|
@@ -3122,6 +3080,7 @@ var LinkTooltip = class {
|
|
|
3122
3080
|
hide() {
|
|
3123
3081
|
this.tooltip.classList.remove("visible");
|
|
3124
3082
|
this.currentLink = null;
|
|
3083
|
+
this.isTooltipHovered = false;
|
|
3125
3084
|
}
|
|
3126
3085
|
scheduleHide() {
|
|
3127
3086
|
this.cancelHide();
|
|
@@ -3146,6 +3105,7 @@ var LinkTooltip = class {
|
|
|
3146
3105
|
this.currentLink = null;
|
|
3147
3106
|
this.floatingUI = null;
|
|
3148
3107
|
this.useFloatingUI = false;
|
|
3108
|
+
this.isTooltipHovered = false;
|
|
3149
3109
|
}
|
|
3150
3110
|
};
|
|
3151
3111
|
|
|
@@ -3216,27 +3176,30 @@ var eyeIcon = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke
|
|
|
3216
3176
|
var toolbarButtons = {
|
|
3217
3177
|
bold: {
|
|
3218
3178
|
name: "bold",
|
|
3179
|
+
actionId: "toggleBold",
|
|
3219
3180
|
icon: boldIcon,
|
|
3220
3181
|
title: "Bold (Ctrl+B)",
|
|
3221
|
-
action: ({ editor
|
|
3182
|
+
action: ({ editor }) => {
|
|
3222
3183
|
toggleBold(editor.textarea);
|
|
3223
3184
|
editor.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
3224
3185
|
}
|
|
3225
3186
|
},
|
|
3226
3187
|
italic: {
|
|
3227
3188
|
name: "italic",
|
|
3189
|
+
actionId: "toggleItalic",
|
|
3228
3190
|
icon: italicIcon,
|
|
3229
3191
|
title: "Italic (Ctrl+I)",
|
|
3230
|
-
action: ({ editor
|
|
3192
|
+
action: ({ editor }) => {
|
|
3231
3193
|
toggleItalic(editor.textarea);
|
|
3232
3194
|
editor.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
3233
3195
|
}
|
|
3234
3196
|
},
|
|
3235
3197
|
code: {
|
|
3236
3198
|
name: "code",
|
|
3199
|
+
actionId: "toggleCode",
|
|
3237
3200
|
icon: codeIcon,
|
|
3238
3201
|
title: "Inline Code",
|
|
3239
|
-
action: ({ editor
|
|
3202
|
+
action: ({ editor }) => {
|
|
3240
3203
|
toggleCode(editor.textarea);
|
|
3241
3204
|
editor.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
3242
3205
|
}
|
|
@@ -3247,63 +3210,70 @@ var toolbarButtons = {
|
|
|
3247
3210
|
},
|
|
3248
3211
|
link: {
|
|
3249
3212
|
name: "link",
|
|
3213
|
+
actionId: "insertLink",
|
|
3250
3214
|
icon: linkIcon,
|
|
3251
3215
|
title: "Insert Link",
|
|
3252
|
-
action: ({ editor
|
|
3216
|
+
action: ({ editor }) => {
|
|
3253
3217
|
insertLink(editor.textarea);
|
|
3254
3218
|
editor.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
3255
3219
|
}
|
|
3256
3220
|
},
|
|
3257
3221
|
h1: {
|
|
3258
3222
|
name: "h1",
|
|
3223
|
+
actionId: "toggleH1",
|
|
3259
3224
|
icon: h1Icon,
|
|
3260
3225
|
title: "Heading 1",
|
|
3261
|
-
action: ({ editor
|
|
3226
|
+
action: ({ editor }) => {
|
|
3262
3227
|
toggleH1(editor.textarea);
|
|
3263
3228
|
editor.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
3264
3229
|
}
|
|
3265
3230
|
},
|
|
3266
3231
|
h2: {
|
|
3267
3232
|
name: "h2",
|
|
3233
|
+
actionId: "toggleH2",
|
|
3268
3234
|
icon: h2Icon,
|
|
3269
3235
|
title: "Heading 2",
|
|
3270
|
-
action: ({ editor
|
|
3236
|
+
action: ({ editor }) => {
|
|
3271
3237
|
toggleH2(editor.textarea);
|
|
3272
3238
|
editor.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
3273
3239
|
}
|
|
3274
3240
|
},
|
|
3275
3241
|
h3: {
|
|
3276
3242
|
name: "h3",
|
|
3243
|
+
actionId: "toggleH3",
|
|
3277
3244
|
icon: h3Icon,
|
|
3278
3245
|
title: "Heading 3",
|
|
3279
|
-
action: ({ editor
|
|
3246
|
+
action: ({ editor }) => {
|
|
3280
3247
|
toggleH3(editor.textarea);
|
|
3281
3248
|
editor.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
3282
3249
|
}
|
|
3283
3250
|
},
|
|
3284
3251
|
bulletList: {
|
|
3285
3252
|
name: "bulletList",
|
|
3253
|
+
actionId: "toggleBulletList",
|
|
3286
3254
|
icon: bulletListIcon,
|
|
3287
3255
|
title: "Bullet List",
|
|
3288
|
-
action: ({ editor
|
|
3256
|
+
action: ({ editor }) => {
|
|
3289
3257
|
toggleBulletList(editor.textarea);
|
|
3290
3258
|
editor.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
3291
3259
|
}
|
|
3292
3260
|
},
|
|
3293
3261
|
orderedList: {
|
|
3294
3262
|
name: "orderedList",
|
|
3263
|
+
actionId: "toggleNumberedList",
|
|
3295
3264
|
icon: orderedListIcon,
|
|
3296
3265
|
title: "Numbered List",
|
|
3297
|
-
action: ({ editor
|
|
3266
|
+
action: ({ editor }) => {
|
|
3298
3267
|
toggleNumberedList(editor.textarea);
|
|
3299
3268
|
editor.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
3300
3269
|
}
|
|
3301
3270
|
},
|
|
3302
3271
|
taskList: {
|
|
3303
3272
|
name: "taskList",
|
|
3273
|
+
actionId: "toggleTaskList",
|
|
3304
3274
|
icon: taskListIcon,
|
|
3305
3275
|
title: "Task List",
|
|
3306
|
-
action: ({ editor
|
|
3276
|
+
action: ({ editor }) => {
|
|
3307
3277
|
if (toggleTaskList) {
|
|
3308
3278
|
toggleTaskList(editor.textarea);
|
|
3309
3279
|
editor.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
@@ -3312,9 +3282,10 @@ var toolbarButtons = {
|
|
|
3312
3282
|
},
|
|
3313
3283
|
quote: {
|
|
3314
3284
|
name: "quote",
|
|
3285
|
+
actionId: "toggleQuote",
|
|
3315
3286
|
icon: quoteIcon,
|
|
3316
3287
|
title: "Quote",
|
|
3317
|
-
action: ({ editor
|
|
3288
|
+
action: ({ editor }) => {
|
|
3318
3289
|
toggleQuote(editor.textarea);
|
|
3319
3290
|
editor.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
3320
3291
|
}
|
|
@@ -3348,6 +3319,45 @@ var defaultToolbarButtons = [
|
|
|
3348
3319
|
];
|
|
3349
3320
|
|
|
3350
3321
|
// src/overtype.js
|
|
3322
|
+
function buildActionsMap(buttons) {
|
|
3323
|
+
const map = {};
|
|
3324
|
+
(buttons || []).forEach((btn) => {
|
|
3325
|
+
if (!btn || btn.name === "separator")
|
|
3326
|
+
return;
|
|
3327
|
+
const id = btn.actionId || btn.name;
|
|
3328
|
+
if (btn.action) {
|
|
3329
|
+
map[id] = btn.action;
|
|
3330
|
+
}
|
|
3331
|
+
});
|
|
3332
|
+
return map;
|
|
3333
|
+
}
|
|
3334
|
+
function normalizeButtons(buttons) {
|
|
3335
|
+
const list = buttons || defaultToolbarButtons;
|
|
3336
|
+
if (!Array.isArray(list))
|
|
3337
|
+
return null;
|
|
3338
|
+
return list.map((btn) => ({
|
|
3339
|
+
name: (btn == null ? void 0 : btn.name) || null,
|
|
3340
|
+
actionId: (btn == null ? void 0 : btn.actionId) || (btn == null ? void 0 : btn.name) || null,
|
|
3341
|
+
icon: (btn == null ? void 0 : btn.icon) || null,
|
|
3342
|
+
title: (btn == null ? void 0 : btn.title) || null
|
|
3343
|
+
}));
|
|
3344
|
+
}
|
|
3345
|
+
function toolbarButtonsChanged(prevButtons, nextButtons) {
|
|
3346
|
+
const prev = normalizeButtons(prevButtons);
|
|
3347
|
+
const next = normalizeButtons(nextButtons);
|
|
3348
|
+
if (prev === null || next === null)
|
|
3349
|
+
return prev !== next;
|
|
3350
|
+
if (prev.length !== next.length)
|
|
3351
|
+
return true;
|
|
3352
|
+
for (let i = 0; i < prev.length; i++) {
|
|
3353
|
+
const a = prev[i];
|
|
3354
|
+
const b = next[i];
|
|
3355
|
+
if (a.name !== b.name || a.actionId !== b.actionId || a.icon !== b.icon || a.title !== b.title) {
|
|
3356
|
+
return true;
|
|
3357
|
+
}
|
|
3358
|
+
}
|
|
3359
|
+
return false;
|
|
3360
|
+
}
|
|
3351
3361
|
var _OverType = class _OverType {
|
|
3352
3362
|
/**
|
|
3353
3363
|
* Constructor - Always returns an array of instances
|
|
@@ -3405,6 +3415,7 @@ var _OverType = class _OverType {
|
|
|
3405
3415
|
this._buildFromScratch();
|
|
3406
3416
|
}
|
|
3407
3417
|
this.shortcuts = new ShortcutsManager(this);
|
|
3418
|
+
this._rebuildActionsMap();
|
|
3408
3419
|
this.linkTooltip = new LinkTooltip(this);
|
|
3409
3420
|
requestAnimationFrame(() => {
|
|
3410
3421
|
requestAnimationFrame(() => {
|
|
@@ -3660,6 +3671,17 @@ var _OverType = class _OverType {
|
|
|
3660
3671
|
this._toolbarInputListener = null;
|
|
3661
3672
|
}
|
|
3662
3673
|
}
|
|
3674
|
+
/**
|
|
3675
|
+
* Rebuild the action map from current toolbar button configuration
|
|
3676
|
+
* Called during init and reinit to keep shortcuts in sync with toolbar buttons
|
|
3677
|
+
* @private
|
|
3678
|
+
*/
|
|
3679
|
+
_rebuildActionsMap() {
|
|
3680
|
+
this.actionsById = buildActionsMap(defaultToolbarButtons);
|
|
3681
|
+
if (this.options.toolbarButtons) {
|
|
3682
|
+
Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));
|
|
3683
|
+
}
|
|
3684
|
+
}
|
|
3663
3685
|
/**
|
|
3664
3686
|
* Apply options to the editor
|
|
3665
3687
|
* @private
|
|
@@ -3921,6 +3943,40 @@ var _OverType = class _OverType {
|
|
|
3921
3943
|
this._updateAutoHeight();
|
|
3922
3944
|
}
|
|
3923
3945
|
}
|
|
3946
|
+
/**
|
|
3947
|
+
* Execute an action by ID
|
|
3948
|
+
* Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls
|
|
3949
|
+
* @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')
|
|
3950
|
+
* @param {Event|null} event - Optional event that triggered the action
|
|
3951
|
+
* @returns {Promise<boolean>} Whether the action was executed successfully
|
|
3952
|
+
*/
|
|
3953
|
+
async performAction(actionId, event = null) {
|
|
3954
|
+
var _a;
|
|
3955
|
+
const textarea = this.textarea;
|
|
3956
|
+
if (!textarea)
|
|
3957
|
+
return false;
|
|
3958
|
+
const action = (_a = this.actionsById) == null ? void 0 : _a[actionId];
|
|
3959
|
+
if (!action) {
|
|
3960
|
+
console.warn(`OverType: Unknown action "${actionId}"`);
|
|
3961
|
+
return false;
|
|
3962
|
+
}
|
|
3963
|
+
textarea.focus();
|
|
3964
|
+
try {
|
|
3965
|
+
await action({
|
|
3966
|
+
editor: this,
|
|
3967
|
+
getValue: () => this.getValue(),
|
|
3968
|
+
setValue: (value) => this.setValue(value),
|
|
3969
|
+
event
|
|
3970
|
+
});
|
|
3971
|
+
return true;
|
|
3972
|
+
} catch (error) {
|
|
3973
|
+
console.error(`OverType: Action "${actionId}" error:`, error);
|
|
3974
|
+
this.wrapper.dispatchEvent(new CustomEvent("button-error", {
|
|
3975
|
+
detail: { actionId, error }
|
|
3976
|
+
}));
|
|
3977
|
+
return false;
|
|
3978
|
+
}
|
|
3979
|
+
}
|
|
3924
3980
|
/**
|
|
3925
3981
|
* Get the rendered HTML of the current content
|
|
3926
3982
|
* @param {Object} options - Rendering options
|
|
@@ -3977,7 +4033,17 @@ var _OverType = class _OverType {
|
|
|
3977
4033
|
* @param {Object} options - New options to apply
|
|
3978
4034
|
*/
|
|
3979
4035
|
reinit(options = {}) {
|
|
4036
|
+
var _a;
|
|
4037
|
+
const prevToolbarButtons = (_a = this.options) == null ? void 0 : _a.toolbarButtons;
|
|
3980
4038
|
this.options = this._mergeOptions({ ...this.options, ...options });
|
|
4039
|
+
const toolbarNeedsRebuild = this.toolbar && this.options.toolbar && toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);
|
|
4040
|
+
this._rebuildActionsMap();
|
|
4041
|
+
if (toolbarNeedsRebuild) {
|
|
4042
|
+
this._cleanupToolbarListeners();
|
|
4043
|
+
this.toolbar.destroy();
|
|
4044
|
+
this.toolbar = null;
|
|
4045
|
+
this._createToolbar();
|
|
4046
|
+
}
|
|
3981
4047
|
this._applyOptions();
|
|
3982
4048
|
this.updatePreview();
|
|
3983
4049
|
}
|