Spaces:
Paused
Paused
| import { power_user } from './power-user.js'; | |
| export function initInputMarkdown() { | |
| $(document).on('keydown', 'textarea.mdHotkeys', function (e) { | |
| if (!power_user.enable_md_hotkeys) { return; } | |
| // Ensure that the element is a textarea | |
| let textarea = this; | |
| if (!(textarea instanceof HTMLTextAreaElement)) { | |
| return; | |
| } | |
| // Early return on only control or no control, alt key, and win/cmd key | |
| if (e.key === 'Control' || !e.ctrlKey || e.altKey || e.metaKey || (e.shiftKey && !(e.ctrlKey && e.shiftKey && e.code === 'Backquote'))) { | |
| return; | |
| } | |
| let charsToAdd = ''; | |
| let possiblePreviousFormattingMargin = 1; | |
| switch (true) { | |
| case e.ctrlKey && e.shiftKey && e.code === 'Backquote': | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| charsToAdd = '~~'; | |
| possiblePreviousFormattingMargin = 2; | |
| break; | |
| case e.ctrlKey && e.code === 'KeyB': | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| charsToAdd = '**'; | |
| possiblePreviousFormattingMargin = 2; | |
| break; | |
| case e.ctrlKey && e.code === 'KeyI': | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| charsToAdd = '*'; | |
| break; | |
| case e.ctrlKey && e.code === 'KeyU': | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| charsToAdd = '__'; | |
| possiblePreviousFormattingMargin = 2; | |
| break; | |
| case e.ctrlKey && e.code === 'KeyK': | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| charsToAdd = '`'; | |
| break; | |
| default: | |
| return; // Early return if no key matches | |
| } | |
| let selectedText = ''; | |
| let start = textarea.selectionStart; | |
| let end = textarea.selectionEnd; | |
| let beforeCaret = textarea.value.substring(start - 1, start); | |
| let afterCaret = textarea.value.substring(end, end + 1); | |
| let isTextSelected = (start !== end); | |
| let cursorShift = charsToAdd.length; | |
| let selectedTextandPossibleFormatting = textarea.value.substring(start - possiblePreviousFormattingMargin, end + possiblePreviousFormattingMargin).trim(); | |
| if (isTextSelected) { //if text is selected | |
| selectedText = textarea.value.substring(start, end); | |
| if (selectedTextandPossibleFormatting === charsToAdd + selectedText + charsToAdd) { | |
| // If the selected text is already formatted, remove the formatting | |
| let expandedStart = start - charsToAdd.length; | |
| let expandedEnd = end + charsToAdd.length; | |
| // Ensure expanded range is within the bounds of the text | |
| if (expandedStart < 0) expandedStart = 0; | |
| if (expandedEnd > textarea.value.length) expandedEnd = textarea.value.length; | |
| // Select the expanded range | |
| textarea.setSelectionRange(expandedStart, expandedEnd); | |
| // Replace the expanded selection with the original selected text | |
| document.execCommand('insertText', false, selectedText); | |
| // Adjust cursor position | |
| cursorShift = -charsToAdd.length; | |
| } else { | |
| // Add formatting to the selected text | |
| let possibleAddedSpace = ''; | |
| if (selectedText.endsWith(' ')) { | |
| possibleAddedSpace = ' '; | |
| selectedText = selectedText.substring(0, selectedText.length - 1); | |
| end--; // Adjust the end index since we removed the space | |
| } | |
| // To add the formatting, we need to select the text first | |
| textarea.focus(); | |
| document.execCommand('insertText', false, charsToAdd + selectedText + charsToAdd + possibleAddedSpace); | |
| } | |
| } else {// No text is selected | |
| //check 1 character before and after the cursor for non-space characters | |
| if (beforeCaret !== ' ' && afterCaret !== ' ' && afterCaret !== '' && beforeCaret !== '') { //look for caret in the middle of a word | |
| //expand the selection range until the next space on both sides | |
| let midCaretExpandedStart = start - 1; | |
| let midCaretExpandedEnd = end + 1; | |
| while (midCaretExpandedStart > 0 && textarea.value.substring(midCaretExpandedStart - 1, midCaretExpandedStart) !== ' ') { | |
| midCaretExpandedStart--; | |
| } | |
| while (midCaretExpandedEnd < textarea.value.length && textarea.value.substring(midCaretExpandedEnd, midCaretExpandedEnd + 1) !== ' ') { | |
| midCaretExpandedEnd++; | |
| } | |
| //make a selection of the discovered word | |
| textarea.setSelectionRange(midCaretExpandedStart, midCaretExpandedEnd); | |
| //set variables for comparison | |
| let discoveredWordWithPossibleFormatting = textarea.value.substring(midCaretExpandedStart, midCaretExpandedEnd).trim(); | |
| let discoveredWord = ''; | |
| if (discoveredWordWithPossibleFormatting.endsWith(charsToAdd) && discoveredWordWithPossibleFormatting.startsWith(charsToAdd)) { | |
| discoveredWord = textarea.value.substring(midCaretExpandedStart + charsToAdd.length, midCaretExpandedEnd - charsToAdd.length).trim(); | |
| } else { | |
| discoveredWord = textarea.value.substring(midCaretExpandedStart, midCaretExpandedEnd).trim(); | |
| } | |
| if (charsToAdd + discoveredWord + charsToAdd === discoveredWordWithPossibleFormatting) { | |
| // Replace the expanded selection with the original discovered word | |
| textarea.focus(); | |
| document.execCommand('insertText', false, discoveredWord); | |
| // Adjust cursor position | |
| cursorShift = -charsToAdd.length; | |
| } else { //format did not previously exist, so add it | |
| textarea.focus(); | |
| document.execCommand('insertText', false, charsToAdd + discoveredWord + charsToAdd); | |
| } | |
| } else { //caret is not inside a word, so just add the formatting | |
| textarea.focus(); | |
| textarea.setSelectionRange(start, end); | |
| selectedText = textarea.value.substring(start, end); | |
| document.execCommand('insertText', false, charsToAdd + selectedText + charsToAdd); | |
| } | |
| } | |
| // Manually trigger the 'input' event to make undo/redo work | |
| let event = new Event('input', { bubbles: true }); | |
| textarea.dispatchEvent(event); // This notifies the browser of a change, allowing undo/redo to function. | |
| // Update the cursor position | |
| if (isTextSelected) { | |
| textarea.selectionStart = start + cursorShift; | |
| textarea.selectionEnd = start + cursorShift + selectedText.length; | |
| } else { | |
| textarea.selectionStart = start + cursorShift; | |
| textarea.selectionEnd = start + cursorShift; | |
| } | |
| }); | |
| } | |