From 28c98d93d1d6237595d22420f4174e17f5f5007e Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 19 Jul 2017 15:00:25 +0100 Subject: [PATCH] Mimic ctrl+j of RT mode in MD mode by inspecting whether multiple lines are selected or the selection is empty. If either of these are true, insert a code block surrounding the selection, otherwise insert single backticks around the selection for inline code formatting. --- src/RichText.js | 11 +++++++++++ .../views/rooms/MessageComposerInput.js | 19 +++++++++++++++---- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/RichText.js b/src/RichText.js index f2f2d533a8..16e16c5b81 100644 --- a/src/RichText.js +++ b/src/RichText.js @@ -304,3 +304,14 @@ export function attachImmutableEntitiesToEmoji(editorState: EditorState): Editor return editorState; } + +export function hasMultiLineSelection(editorState: EditorState): boolean { + const selectionState = editorState.getSelection(); + const anchorKey = selectionState.getAnchorKey(); + const currentContent = editorState.getCurrentContent(); + const currentContentBlock = currentContent.getBlockForKey(anchorKey); + const start = selectionState.getStartOffset(); + const end = selectionState.getEndOffset(); + const selectedText = currentContentBlock.getText().slice(start, end); + return selectedText.includes('\n'); +} diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js index d4ae55f03a..6704998c05 100644 --- a/src/components/views/rooms/MessageComposerInput.js +++ b/src/components/views/rooms/MessageComposerInput.js @@ -521,14 +521,12 @@ export default class MessageComposerInput extends React.Component { this.enableRichtext(!this.state.isRichtextEnabled); return true; } - let newState: ?EditorState = null; // Draft handles rich text mode commands by default but we need to do it ourselves for Markdown. if (this.state.isRichtextEnabled) { // These are block types, not handled by RichUtils by default. const blockCommands = ['code-block', 'blockquote', 'unordered-list-item', 'ordered-list-item']; - if (blockCommands.includes(command)) { this.setState({ editorState: RichUtils.toggleBlockType(this.state.editorState, command), @@ -540,14 +538,26 @@ export default class MessageComposerInput extends React.Component { }); } } else { - let contentState = this.state.editorState.getCurrentContent(); + const contentState = this.state.editorState.getCurrentContent(); + const multipleLinesSelected = RichText.hasMultiLineSelection(this.state.editorState); + const selectionState = this.state.editorState.getSelection(); + const start = selectionState.getStartOffset(); + const end = selectionState.getEndOffset(); + + // If multiple lines are selected or nothing is selected, insert a code block + // instead of applying inline code formatting. This is an attempt to mimic what + // happens in non-MD mode. + const treatInlineCodeAsBlock = multipleLinesSelected || start === end; + const textMdCodeBlock = (text) => `\`\`\`\n${text}\n\`\`\`\n`; const modifyFn = { 'bold': (text) => `**${text}**`, 'italic': (text) => `*${text}*`, 'underline': (text) => `${text}`, 'strike': (text) => `${text}`, - 'code-block': (text) => `\`\`\`\n${text}\n\`\`\`\n`, + // ("code" is triggered by ctrl+j by draft-js by default) + 'code': (text) => treatInlineCodeAsBlock ? textMdCodeBlock(text) : `\`${text}\``, + 'code-block': textMdCodeBlock, 'blockquote': (text) => text.split('\n').map((line) => `> ${line}\n`).join('') + '\n', 'unordered-list-item': (text) => text.split('\n').map((line) => `\n- ${line}`).join(''), 'ordered-list-item': (text) => text.split('\n').map((line, i) => `\n${i + 1}. ${line}`).join(''), @@ -558,6 +568,7 @@ export default class MessageComposerInput extends React.Component { 'italic': -1, 'underline': -4, 'strike': -6, + 'code': treatInlineCodeAsBlock ? -5 : -1, 'code-block': -5, 'blockquote': -2, }[command];