Fix ToastUI editor bug preventing manual codeblock insertion
Manually inserting a codeblock adding three backticks and hitting enter is not functioning in the ToastUI editor due to an existing bug in the library. This commit implements a workaround to address the issue.
This commit is contained in:

committed by
Dominic Sauer

parent
749074fec0
commit
da9add4a10
@ -6,6 +6,39 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const BACKTICK = 192;
|
||||||
|
// These counters can be global. Scoping them to each editor becomes redundant
|
||||||
|
// since they are reset to this state when switching editors.
|
||||||
|
// Read more: https://github.com/openHPI/codeocean/pull/2242#discussion_r1576617432
|
||||||
|
let backtickPressedCount = 0;
|
||||||
|
let justInsertedCodeBlock = false;
|
||||||
|
|
||||||
|
const deleteSelection = (editor, count) => {
|
||||||
|
// The backtick is a so-called dead key, which is waiting for further input to be combined with.
|
||||||
|
// For example a backtick and the letter a are combined to à.
|
||||||
|
// When we remove a selection ending with a backtick, we want to clear the keyboard buffer, too.
|
||||||
|
// This ensures that typing a regular character a after this operation is not combined into à, but just inserted as a.
|
||||||
|
// This solution is taken from https://stackoverflow.com/a/72634132.
|
||||||
|
editor.blur();
|
||||||
|
setTimeout(() => editor.focus());
|
||||||
|
// Get current position
|
||||||
|
const selectionRange = editor.getSelection();
|
||||||
|
// Replace the previous `count` characters with an empty string.
|
||||||
|
// We use a replace function (rather than delete) to avoid issues with line breaks in ToastUi.
|
||||||
|
// Otherwise, a line break following the cursor position might still be displayed normally,
|
||||||
|
// but could be removed erroneously from the internal editor state.
|
||||||
|
// If this happens, code blocks ending with \n``` are not recognized correctly.
|
||||||
|
editor.replaceSelection(
|
||||||
|
"",
|
||||||
|
[selectionRange[0][0], selectionRange[0][1] - count],
|
||||||
|
[selectionRange[1][0], selectionRange[1][1]]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const resetCount = (withBlock = false) => {
|
||||||
|
backtickPressedCount = 0;
|
||||||
|
justInsertedCodeBlock = withBlock;
|
||||||
|
};
|
||||||
|
|
||||||
const initializeMarkdownEditors = () => {
|
const initializeMarkdownEditors = () => {
|
||||||
const editors = document.querySelectorAll(
|
const editors = document.querySelectorAll(
|
||||||
'[data-behavior="markdown-editor-widget"]'
|
'[data-behavior="markdown-editor-widget"]'
|
||||||
@ -42,6 +75,39 @@ const initializeMarkdownEditors = () => {
|
|||||||
const content = toastEditor.getMarkdown();
|
const content = toastEditor.getMarkdown();
|
||||||
formInput.value = content;
|
formInput.value = content;
|
||||||
},
|
},
|
||||||
|
// Fix ToastUI editor bug preventing manual codeblock insertion:
|
||||||
|
// Manually inserting a codeblock adding three backticks and hitting enter
|
||||||
|
// is not functioning in the ToastUI editor due to an existing bug in the library.
|
||||||
|
// Therefore, this `keyup` handler implements a workaround to address the issue.
|
||||||
|
keyup: (_, event) => {
|
||||||
|
// Although the use of keyCode seems to be deprecated, the suggested alternatives (key or code)
|
||||||
|
// work inconsistently across browsers. Using keyCode works flawless for now.
|
||||||
|
// Read more: https://github.com/openHPI/codeocean/pull/2242#discussion_r1576675620
|
||||||
|
if (event.keyCode === BACKTICK) {
|
||||||
|
backtickPressedCount++;
|
||||||
|
if (backtickPressedCount === 2) {
|
||||||
|
// Remove the last two backticks and insert a code block
|
||||||
|
// The order of operations is important here: Inserting the code block first and then removing
|
||||||
|
// some backticks won't work, since this would infer with the internal ToastUi editor state.
|
||||||
|
// With the current solution, we don't mingle with the code block inserted by ToastUi at all.
|
||||||
|
deleteSelection(toastEditor, 2);
|
||||||
|
toastEditor.exec("codeBlock");
|
||||||
|
resetCount(true);
|
||||||
|
}
|
||||||
|
} else if (backtickPressedCount === 1 && justInsertedCodeBlock) {
|
||||||
|
// We want to improve the usage of our code block fix with the following mechanism.
|
||||||
|
// Usually, three backticks are required to start a code block.
|
||||||
|
// However, with our workaround only two backticks are required.
|
||||||
|
// Out of habit, however, users might still enter three backticks at once,
|
||||||
|
// not noticing that the code block was already inserted after the second one.
|
||||||
|
// Thus, we remove one additional backtick entered after starting a code block through our fix.
|
||||||
|
deleteSelection(toastEditor, 1);
|
||||||
|
resetCount();
|
||||||
|
} else {
|
||||||
|
// If any other key is pressed, reset the count
|
||||||
|
resetCount();
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user