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 editors = document.querySelectorAll(
|
||||
'[data-behavior="markdown-editor-widget"]'
|
||||
@ -42,6 +75,39 @@ const initializeMarkdownEditors = () => {
|
||||
const content = toastEditor.getMarkdown();
|
||||
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