From bf721e6e307a8efd6351f32be79f0ed3fb3e427f Mon Sep 17 00:00:00 2001 From: luin Date: Wed, 3 Feb 2021 00:54:23 +0800 Subject: [PATCH] Cut across lines shouldn't affect the formatting of the line above To test: 1. Open http://localhost:9000/standalone/full/ 2. Create two lines: ``` Hea|der Normal |paragraph ``` 3. Cut text between two |. Expected: The first line is a header. Actually: The first line is a normal paragraph. --- modules/clipboard.js | 3 ++- modules/keyboard.js | 30 +++++++++++++++++------------- test/unit/modules/clipboard.js | 27 +++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/modules/clipboard.js b/modules/clipboard.js index f8d409fe62..6045fa31c5 100644 --- a/modules/clipboard.js +++ b/modules/clipboard.js @@ -19,6 +19,7 @@ import { ColorStyle } from '../formats/color'; import { DirectionAttribute, DirectionStyle } from '../formats/direction'; import { FontStyle } from '../formats/font'; import { SizeStyle } from '../formats/size'; +import { deleteRange } from './keyboard'; const debug = logger('quill:clipboard'); @@ -135,7 +136,7 @@ class Clipboard extends Module { e.clipboardData.setData('text/plain', text); e.clipboardData.setData('text/html', html); if (isCut) { - this.quill.deleteText(range, Quill.sources.USER); + deleteRange({ range, quill: this.quill }); } } diff --git a/modules/keyboard.js b/modules/keyboard.js index 1a4bd004ee..d3d4d6e55e 100644 --- a/modules/keyboard.js +++ b/modules/keyboard.js @@ -244,18 +244,7 @@ class Keyboard extends Module { } handleDeleteRange(range) { - const lines = this.quill.getLines(range); - let formats = {}; - if (lines.length > 1) { - const firstFormats = lines[0].formats(); - const lastFormats = lines[lines.length - 1].formats(); - formats = AttributeMap.diff(lastFormats, firstFormats) || {}; - } - this.quill.deleteText(range, Quill.sources.USER); - if (Object.keys(formats).length > 0) { - this.quill.formatLine(range.index, 1, formats, Quill.sources.USER); - } - this.quill.setSelection(range.index, Quill.sources.SILENT); + deleteRange({ range, quill: this.quill }); this.quill.focus(); } @@ -709,6 +698,21 @@ function normalize(binding) { return binding; } +function deleteRange({ quill, range }) { + const lines = quill.getLines(range); + let formats = {}; + if (lines.length > 1) { + const firstFormats = lines[0].formats(); + const lastFormats = lines[lines.length - 1].formats(); + formats = AttributeMap.diff(lastFormats, firstFormats) || {}; + } + quill.deleteText(range, Quill.sources.USER); + if (Object.keys(formats).length > 0) { + quill.formatLine(range.index, 1, formats, Quill.sources.USER); + } + quill.setSelection(range.index, Quill.sources.SILENT); +} + function tableSide(table, row, cell, offset) { if (row.prev == null && row.next == null) { if (cell.prev == null && cell.next == null) { @@ -725,4 +729,4 @@ function tableSide(table, row, cell, offset) { return null; } -export { Keyboard as default, SHORTKEY, normalize }; +export { Keyboard as default, SHORTKEY, normalize, deleteRange }; diff --git a/test/unit/modules/clipboard.js b/test/unit/modules/clipboard.js index d542fc9fcd..b7b804c605 100644 --- a/test/unit/modules/clipboard.js +++ b/test/unit/modules/clipboard.js @@ -58,6 +58,33 @@ describe('Clipboard', function() { }); }); + describe('cut', () => { + beforeEach(function() { + this.clipboardData = {}; + this.clipboardEvent = { + clipboardData: { + setData: (type, data) => { + this.clipboardData[type] = data; + }, + }, + preventDefault: () => {}, + }; + }); + + it('keeps formats of first line', function(done) { + this.quill.clipboard.onCaptureCopy(this.clipboardEvent, true); + setTimeout(() => { + expect(this.quill.root).toEqualHTML('

0178

'); + expect(this.quill.getSelection()).toEqual(new Range(2)); + expect(this.clipboardData['text/plain']).toEqual('23\n56'); + expect(this.clipboardData['text/html']).toEqual( + '

23

56

', + ); + done(); + }, 2); + }); + }); + it('dangerouslyPasteHTML(html)', function() { this.quill.clipboard.dangerouslyPasteHTML('abcd'); expect(this.quill.root).toEqualHTML(