From ef59a7438053b6f2d5fb475dba5234fdcc6defdb Mon Sep 17 00:00:00 2001 From: Ran Luo Date: Thu, 11 Apr 2019 09:28:04 +0800 Subject: [PATCH] feat: support copy rich text (#904) * feat: support copy rich text * update changelog --- .github/CHANGELOG.md | 2 + src/muya/lib/contentState/copyCutCtrl.js | 5 +- src/muya/lib/contentState/pasteCtrl.js | 71 ++++++++++++++++++------ 3 files changed, 59 insertions(+), 19 deletions(-) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 5545d787..8d0f2ef6 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -61,6 +61,7 @@ foo
bar
zar - Hide titlebar control buttons in custom titlebar style - Corrected hamburger menu offset - Optimization of inline html displa, now you can nest other inline syntax in inline html(#849) +- Use CmdOrCtrl + C/V to copy rich text to `word`(Windows) or `page`(macOS) (#885) **:beetle:Bug fix** @@ -115,6 +116,7 @@ foo
bar
zar - Fixed source code mode to preview switching - Mark Text didn't remove highlight when I delete the markdown symbol like * or `. (#893) - After delete ``` at the beginning to paragraph by backspace, then type other text foo, the color will be strange, if you type 1. bar. error happened. (#892) +- Fix highlight error in code block (#545 #890) ### 0.13.65 diff --git a/src/muya/lib/contentState/copyCutCtrl.js b/src/muya/lib/contentState/copyCutCtrl.js index d96b54a5..e22b05ee 100644 --- a/src/muya/lib/contentState/copyCutCtrl.js +++ b/src/muya/lib/contentState/copyCutCtrl.js @@ -2,6 +2,7 @@ import selection from '../selection' import { CLASS_OR_ID } from '../config' import { getSanitizeHtml } from '../utils/exportHtml' import ExportMarkdown from '../utils/exportMarkdown' +import marked from '../parser/marked' const copyCutCtrl = ContentState => { ContentState.prototype.cutHandler = function () { @@ -125,9 +126,9 @@ const copyCutCtrl = ContentState => { } } - const htmlData = wrapper.innerHTML + let htmlData = wrapper.innerHTML const textData = this.htmlToMarkdown(htmlData) - + htmlData = marked(textData) return { html: htmlData, text: textData } } diff --git a/src/muya/lib/contentState/pasteCtrl.js b/src/muya/lib/contentState/pasteCtrl.js index 7c04ffcc..0aa59770 100644 --- a/src/muya/lib/contentState/pasteCtrl.js +++ b/src/muya/lib/contentState/pasteCtrl.js @@ -82,7 +82,7 @@ const pasteCtrl = ContentState => { return this.pasteHandler(event, type) } - const appendHtml = () => { + const appendHtml = (text) => { startBlock.text = startBlock.text.substring(0, start.offset) + text + startBlock.text.substring(start.offset) const { key } = start const offset = start.offset + text.length @@ -179,30 +179,67 @@ const pasteCtrl = ContentState => { // handle copyAsHtml if (copyType === 'copyAsHtml') { + // already handle code block above + if (startBlock.type === 'span' && startBlock.nextSibling) { + const afterParagraph = this.createBlock('p') + let temp = startBlock + const removeCache = [] + while (temp.nextSibling) { + temp = this.getBlock(temp.nextSibling) + this.appendChild(afterParagraph, temp) + removeCache.push(temp) + } + removeCache.forEach(b => this.removeBlock(b)) + this.insertAfter(afterParagraph, parent) + startBlock.nextSibling = null + } switch (type) { case 'normal': { - if (startBlock.type === 'span' && this.isOnlyChild(startBlock) && !startBlock.text) { - this.codeBlockUpdate(startBlock, text.trim(), 'html') - } else { - appendHtml() + const htmlBlock = this.createBlock('p') + const lines = text.trim().split(LINE_BREAKS_REG).map(line => this.createBlock('span', line)) + for (const line of lines) { + this.appendChild(htmlBlock, line) } + if (startBlock.type === 'span') { + this.insertAfter(htmlBlock, parent) + } else { + this.insertAfter(htmlBlock, startBlock) + } + if ( + startBlock.type === 'span' && startBlock.text.length === 0 && this.isOnlyChild(startBlock) + ) { + this.removeBlock(parent) + } + // handler heading + if (startBlock.text.length === 0 && startBlock.type !== 'span') { + this.removeBlock(startBlock) + } + this.insertHtmlBlock(htmlBlock) break } case 'pasteAsPlainText': { - if (startBlock.type === 'span') { - const lines = text.trim().split(LINE_BREAKS_REG).map(line => this.createBlock('span', line)) - for (const line of lines) { - this.appendChild(parent, line) - } - const lastLine = lines[lines.length - 1] - const { key } = lastLine - const offset = lastLine.text.length - this.cursor = { - start: { key, offset }, - end: { key, offset } + const lines = text.trim().split(LINE_BREAKS_REG) + let htmlBlock = null + + if (!startBlock.text || lines.length > 1) { + htmlBlock = this.createBlock('p') + ;(startBlock.text ? lines.slice(1) : lines).map(line => this.createBlock('span', line)) + .forEach(l => { + this.appendChild(htmlBlock, l) + }) + } + if (htmlBlock) { + if (startBlock.type === 'span') { + this.insertAfter(htmlBlock, parent) + } else { + this.insertAfter(htmlBlock, startBlock) } + this.insertHtmlBlock(htmlBlock) + } + if (startBlock.text) { + appendHtml(lines[0]) } else { - appendHtml() + this.removeBlock(startBlock.type === 'span' ? parent : startBlock) } break }