Skip to content

Commit

Permalink
Fix paste multiline text issue(T1130660) (#84)
Browse files Browse the repository at this point in the history
Fix paste multiline text issue(T1130660)
  • Loading branch information
alexanderPolosatov authored Mar 14, 2023
1 parent 3c294c7 commit 18139a2
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 11 deletions.
3 changes: 2 additions & 1 deletion core/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ class Editor {

getHTML(index, length) {
const [line, lineOffset] = this.scroll.line(index);
if (line.length() >= lineOffset + length) {

if (line.length() > lineOffset + length) {
return convertHTML(line, lineOffset, length, true);
}
return convertHTML(this.scroll, index, length, true);
Expand Down
25 changes: 15 additions & 10 deletions modules/clipboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,15 @@ class Clipboard extends Module {
this.tableBlots.push(blotName);
}

convert({ html, text }, formats = {}) {
convert({ html, text, keepLastNewLine }, formats = {}) {
if (formats[CodeBlock.blotName]) {
return new Delta().insert(text, {
[CodeBlock.blotName]: formats[CodeBlock.blotName],
});
}

return html
? this.applyMatchers(html, formats)
? this.applyMatchers(html, keepLastNewLine, formats)
: this.applyTextMatchers(text);
}

Expand All @@ -115,7 +115,7 @@ class Clipboard extends Module {
}, new Delta());
}

applyMatchers(html, formats = {}) {
applyMatchers(html, keepLastNewLine, formats = {}) {
const doc = new DOMParser().parseFromString(html, 'text/html');
const container = doc.body;
const nodeMatches = new WeakMap();
Expand All @@ -132,7 +132,8 @@ class Clipboard extends Module {
);
// Remove trailing newline
if (
deltaEndsWith(delta, '\n')
!keepLastNewLine
&& deltaEndsWith(delta, '\n')
&& (delta.ops[delta.ops.length - 1].attributes == null
|| Object.values(formats).some((blotName) => this.tableBlots.includes(blotName)))
) {
Expand Down Expand Up @@ -212,7 +213,11 @@ class Clipboard extends Module {
}

const text = e.clipboardData.getData('text/plain');
this.onPaste(range, { html, text });
this.onPaste(range, {
html,
text,
keepLastNewLine: true,
});
}

raiseCallback(name, event) {
Expand All @@ -223,15 +228,15 @@ class Clipboard extends Module {
}
}

onCopy(range) {
const text = this.quill.getText(range);
const html = this.quill.getSemanticHTML(range);
onCopy({ index, length }) {
const text = this.quill.getText(index, length);
const html = this.quill.getSemanticHTML(index, length);
return { html, text };
}

onPaste(range, { text, html }) {
onPaste(range, { text, html, keepLastNewLine }) {
const formats = this.quill.getFormat(range.index);
const pastedDelta = this.convert({ text, html }, formats);
const pastedDelta = this.convert({ text, html, keepLastNewLine }, formats);
debug.log('onPaste', pastedDelta, { text, html });
const delta = new Delta()
.retain(range.index)
Expand Down
8 changes: 8 additions & 0 deletions test/unit/core/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,14 @@ describe('Editor', function () {
expect(editor.getHTML(0, 11)).toEqual('<b>Test</b>');
});

it('text should be wrapped to P tag when get part of initial text with new line on end', function () {
const editor = this.initialize(Editor, '<p>1</p><br><p>2</p>');

const html = editor.getHTML(0, 2);

expect(html).toEqual('<p>1</p>');
});

it('multiline code', function () {
const editor = this.initialize(
Editor,
Expand Down
20 changes: 20 additions & 0 deletions test/unit/modules/clipboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,26 @@ describe('Clipboard', function () {
}, 2);
});

it('last line break should not be cut on a multiline text paste', function (done) {
this.quill.setSelection(0, 8);

const captureData = {
...this.clipboardEvent,
clipboardData: {
...this.clipboardData,
getData: (type) => (type === 'text/html' ? '1<br>' : '1\n'),
},
};

this.quill.clipboard.onCapturePaste(captureData);
setTimeout(() => {
expect(this.quill.root).toEqualHTML(
'<p>1</p><p>8</p>',
);
done();
}, 2);
});

// Copying from Word includes both html and files
it('pastes html data if present with file', function (done) {
const upload = spyOn(this.quill.uploader, 'upload');
Expand Down

0 comments on commit 18139a2

Please sign in to comment.