soccerloway / quill-better-table

Module for better table in Quill, more useful features are supported.
MIT License
313 stars 120 forks source link

[Bug]Table broken when paste wrapping text #43

Closed kagol closed 4 years ago

kagol commented 4 years ago

Insert wrapping text into the table and the table is broken.

image

soccerloway commented 4 years ago

Thanks for your report. I will fix it later.

soccerloway commented 4 years ago

Since quill's official table module doesn't support wrapping text in table cells, so pasting wrapping text in table cells will cause the table broken. To fix it, we must deal with pasting wrapping text in table cells specially. One way is:Modifying onCapturePaste method of quilljs built-in clipboard module. Add these code in onCapturePaste method:

const [thisLeaf] = this.quill.getLine(range.index)
    if (thisLeaf && thisLeaf.constructor.name === 'TableCellLine') {
      e.preventDefault();
      const html = e.clipboardData.getData('text/html');
      const text = e.clipboardData.getData('text/plain');
      const files = Array.from(e.clipboardData.files || []);
      if (!html && files.length > 0) {
        this.quill.uploader.upload(range, files);
      } else {
        this.onTableCellPaste(range, { html, text });
      }
      return;
    }

Add onTableCellPaste method to clipboard class:

onTableCellPaste (range, {text, html}) {
    const [line] = this.quill.getLine(range.index)
    const lineFormats = line.formats()
    const formats = this.quill.getFormat(range.index);
    let pastedDelta = this.convert({ text, html }, formats);

    pastedDelta = pastedDelta.reduce((newDelta, op) => {
      if (op.insert && typeof op.insert === 'string') {
        const lines = []
        let insertStr = op.insert
        let start = 0
        for (let i = 0; i < op.insert.length; i++) {
          if (insertStr.charAt(i) === '\n') {
            if (i === 0) {
              lines.push('\n')
            } else {
              lines.push(insertStr.substring(start, i))
              lines.push('\n')
            }
            start = i + 1
          }
        }

        const tailStr = insertStr.substring(start)
        if (tailStr) lines.push(tailStr)

        lines.forEach(text => {
          text === '\n'
          ? newDelta.insert('\n', extend(
              {},
              op.attributes,
              lineFormats
            ))
          : newDelta.insert(text, op.attributes)
        })
      } else {
        newDelta.insert(op.insert, op.attributes)
      }

      return newDelta
    }, new Delta())

    debug.log('onTableCellPaste', pastedDelta, { text, html });
    const delta = new Delta()
      .retain(range.index)
      .delete(range.length)
      .concat(pastedDelta);
    this.quill.updateContents(delta, Quill.sources.USER);
    this.quill.setSelection(
      delta.length() - range.length,
      Quill.sources.SILENT,
    );
    this.quill.scrollIntoView();
  }
soccerloway commented 4 years ago

But I haven't found a suitable way to do this. The clipboard module of quilljs does not provide a interface to modify the onCapturePaste method. Now the question is how to add the special logics to onCapturePaste method of Clipboard.

soccerloway commented 4 years ago

This issue is discussed in #33 Pasting multiple lines breaks the table.