diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js index 34e9e4a1e6..c14b9ebf23 100644 --- a/src/components/views/rooms/MessageComposerInput.js +++ b/src/components/views/rooms/MessageComposerInput.js @@ -502,12 +502,18 @@ export default class MessageComposerInput extends React.Component { // These are block types, not handled by RichUtils by default. const blockCommands = ['code-block', 'blockquote', 'unordered-list-item', 'ordered-list-item']; const currentBlockType = RichUtils.getCurrentBlockType(this.state.editorState); + + const shouldToggleBlockFormat = ( + command === 'backspace' || + command === 'split-block' + ) && currentBlockType !== 'unstyled'; + if (blockCommands.includes(command)) { newState = RichUtils.toggleBlockType(this.state.editorState, command); } else if (command === 'strike') { // this is the only inline style not handled by Draft by default newState = RichUtils.toggleInlineStyle(this.state.editorState, 'STRIKETHROUGH'); - } else if (command === 'backspace' && currentBlockType !== 'unstyled') { + } else if (shouldToggleBlockFormat) { const currentStartOffset = this.state.editorState.getSelection().getStartOffset(); if (currentStartOffset === 0) { // Toggle current block type (setting it to 'unstyled') @@ -718,9 +724,31 @@ export default class MessageComposerInput extends React.Component { ); } } else { - // Use the original plaintext because `contextText` has had mentions stripped - // and these need to end up in contentHTML - const md = new Markdown(contentState.getPlainText()); + // Use the original contentState because `contentText` has had mentions + // stripped and these need to end up in contentHTML. + + // Replace all Entities of type `LINK` with markdown link equivalents. + // TODO: move this into `Markdown` and do the same conversion in the other + // two places (toggling from MD->RT mode and loading MD history into RT mode) + // but this can only be done when history includes Entities. + const pt = contentState.getBlocksAsArray().map((block) => { + let blockText = block.getText(); + let offset = 0; + this.findLinkEntities(block, (start, end) => { + const entity = Entity.get(block.getEntityAt(start)); + if (entity.getType() !== 'LINK') { + return; + } + const text = blockText.slice(offset + start, offset + end); + const url = entity.getData().url; + const mdLink = `[${text}](${url})`; + blockText = blockText.slice(0, offset + start) + mdLink + blockText.slice(offset + end); + offset += mdLink.length - text.length; + }); + return blockText; + }).join('\n'); + + const md = new Markdown(pt); if (md.isPlainText()) { contentText = md.toPlaintext(); } else { @@ -916,9 +944,6 @@ export default class MessageComposerInput extends React.Component { url: href, isCompletion: true, }); - if (!this.state.isRichtextEnabled) { - mdCompletion = `[${completion}](${href})`; - } } let selection;