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