JiHong88 / suneditor

Pure javascript based WYSIWYG html editor, with no dependencies.
http://suneditor.com
MIT License
1.72k stars 308 forks source link

copying styled text does not copy whitespace between spans (with workaround) #1433

Open rozek opened 1 month ago

rozek commented 1 month ago

Describe the bug look at the screen shot: the first paragraph was written and styled using the tool bar. Then, the whole text was selected, copied into the clipboard and pasted underneath

To Reproduce Steps to reproduce the behavior:

  1. enter some text and style parts of it
  2. copy that text into the clipboard
  3. paste it somewhere else

Expected behavior The pasted text should look like the original

Screenshots SunEditor-Bug

Desktop (please complete the following information):

Nota bene: even worse: "cutting" the text into the clipboard also removes whitespace between spans - as a consequence, you can't move paragraphs

Amendment: I've experimented with the onCut, onCopy and onPaste callbacks. While I cannot see anything in the arguments of onCut and onCopy, thecleanDataprovided inonPasteclearly shows the "loss" of whitespace betweenelements... `s are kept, of course, but these badly affect selectabilty (sigh)

rozek commented 1 month ago

my problem seems to be old: there was a fix (https://github.com/JiHong88/suneditor/issues/189) which uses   instead of spaces - but that affects formatting and selectability

rozek commented 1 month ago

there seems to be a function in util.js which explicitly removes whitespace between some tags when cleaning HTML: htmlRemoveWhiteSpace

As a complete newbie to the SunEditor code I cannot predict the side effects - but I would guess that removing this function would be a good idea...

Amendment: I tried to intercept the invocation of htmlRemoveWhiteSpace and found, that whitespace was already removed before!

rozek commented 4 weeks ago

latest findings: I used the following code to inspect and experiment with the contents of the clipboard after Cut or Copy. The following code seems to create the proper HTML:

  my.SunEditor.onCopy = async (Event, ClipboardData, Core) => {
    const ClipboardContents = await navigator.clipboard.read()
    for (const ClipboardItem of ClipboardContents) {
      if (ClipboardItem.types.includes('text/html')) {
        const ItemAsBlob = await ClipboardItem.getType('text/html')
        const ItemAsHTML = (await ItemAsBlob.text())
          .replaceAll('<span>&nbsp;</span>',' ')
        console.log('ItemAsHTML',Core.cleanHTML(ItemAsHTML))
      }
    }
  }

Now I only have to find out how to "convince" the SunEditor to prefer my code...

Nota bene: for those who wonder about the "strange code": the following does not work:

  my.SunEditor.onCopy = (Event, ClipboardData, Core) => {
    console.log('Copy', Event, Core)
    const copiedHTML = Event.clipboardData.getData('text/html')
      .replaceAll('<span>&nbsp;</span>',' ')
    console.log('copiedHTML',Core.cleanHTML(copiedHTML))
  }

but returns an empty string - for whatever reason

rozek commented 4 weeks ago

ok, here is my workaround - it's a horrible hack, but it works for me until the problem gets "officially" solved:

  my.SunEditor.onCopy = async (Event, ClipboardData, Core) => {
    let copiedHTML
      const ClipboardContents = await navigator.clipboard.read()
      for (const ClipboardItem of ClipboardContents) {
        if (ClipboardItem.types.includes('text/html')) {
          const ItemAsBlob = await ClipboardItem.getType('text/html')
          const ItemAsHTML = (await ItemAsBlob.text())
            .replaceAll('<span>&nbsp;</span>',' ')
          copiedHTML = Core.cleanHTML(ItemAsHTML)
          break
        }
      }
    if (copiedHTML != null) {
      const HTMLasBlob = new Blob([copiedHTML], { type:'text/html' })
      const HTMLItem   = new ClipboardItem({ 'text/html':HTMLasBlob })
      navigator.clipboard.write([HTMLItem])
    }
  }

The same applies to onCut

Bakhtawarshahid1 commented 3 weeks ago

I have the same issue with the suneditor while pasting the text from vscode or word it removes spaces within the words and strangely joins them.

Tarpsvo commented 2 weeks ago

I encountered the exact same issue. Copying HTML from where-ever with tags (usually in my case), the spaces before and after the tag are removed. I will be using @rozek's workaround as well, thanks a ton for the debugging work and providing a solution for others. :)

EDIT: Misread, this issue is related to copying. My issue is related to pasting, same as #1291 and #1350. No workaround yet. I tried overriding onPaste, but the cleanData received there is already cleaned of those whitespaces.

EDIT EDIT: My workaround:

pasteTagsBlacklist: "span|div",

and:

this.editor.onPaste = (e, cleanData, maxCharCount, core) => {
  // Add padding before and after tags
  return this.addSpacesAroundTags(cleanData);
};

addSpacesAroundTags(html) {
  // Add space before opening <a> and <span> tags
  html = html.replace(/(?<! )(<(a|span)[^>]*>)/g, " $1");

  // Add space after closing </a> and </span> tags
  html = html.replace(/(<\/(a|span)>)(?! )/g, "$1 ");

  return html;
},