From 9bcad33012b6deb7d3dadf37e3aebc6d12e9bbfa Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Mon, 14 Jul 2025 13:53:38 +0300 Subject: [PATCH] markdown shortcuts --- client/src/views/fields/text.js | 70 ++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/client/src/views/fields/text.js b/client/src/views/fields/text.js index 572d8b5aaf..3f5e67eb43 100644 --- a/client/src/views/fields/text.js +++ b/client/src/views/fields/text.js @@ -622,9 +622,13 @@ class TextFieldView extends BaseFieldView { * @param {KeyboardEvent} event */ onKeyDownMarkdown(event) { - if (Espo.Utils.getKeyFromKeyEvent(event) !== 'Enter') { + const key = Espo.Utils.getKeyFromKeyEvent(event); + + if (key !== 'Enter') { this._lastEnteredKeyIsEnter = false; + this.handleKeyDownMarkdown(event, key); + return; } @@ -686,6 +690,70 @@ class TextFieldView extends BaseFieldView { this.controlTextareaHeight(); } + + /** + * @private + * @param {KeyboardEvent} event + * @param {string} key + */ + handleKeyDownMarkdown(event, key) { + const target = event.target; + + if (!(target instanceof HTMLTextAreaElement)) { + return; + } + + /** + * @param {string} wrapper + */ + const toggleWrap = (wrapper) => { + const {selectionStart, selectionEnd} = target; + + let text = target.value.substring(selectionStart, selectionEnd); + + if (text === '') { + return; + } + + let textPrevious = text; + + text = text.trimStart(); + + const startPart = textPrevious.substring(0, textPrevious.length - text.length); + + textPrevious = text; + + text = text.trimEnd(); + + const endPart = textPrevious.substring(text.length); + + if (text.startsWith(wrapper) && text.endsWith(wrapper)) { + text = text.slice(wrapper.length, - wrapper.length); + } else { + text = wrapper + text + wrapper; + } + + const newText = startPart + text + endPart; + + // noinspection JSDeprecatedSymbols + document.execCommand('insertText', false, newText); + + const newStart = selectionStart + startPart.length; + + target.setSelectionRange(newStart, newStart + text.length); + + event.preventDefault(); + event.stopPropagation(); + }; + + if (key === 'Control+KeyB') { + toggleWrap('**'); + } + + if (key === 'Control+KeyI') { + toggleWrap('_'); + } + } } export default TextFieldView;