diff --git a/src/utils/normalizeclipboarddata.js b/src/utils/normalizeclipboarddata.js index 9f451f1..c45cff0 100644 --- a/src/utils/normalizeclipboarddata.js +++ b/src/utils/normalizeclipboarddata.js @@ -15,7 +15,7 @@ */ export default function normalizeClipboardData( data ) { return data - .replace( /(\s+)<\/span>/g, ( fullMatch, spaces ) => { + .replace( /(\s+)<\/span>/g, ( fullMatch, spaces ) => { // Handle the most popular and problematic case when even a single space becomes an nbsp;. // Decode those to normal spaces. Read more in https://github.com/ckeditor/ckeditor5-clipboard/issues/2. if ( spaces.length == 1 ) { diff --git a/tests/manual/pasting.html b/tests/manual/pasting.html index 6bc4805..4583c8a 100644 --- a/tests/manual/pasting.html +++ b/tests/manual/pasting.html @@ -17,3 +17,23 @@

Notes

It has bugs that we are aware of – and that we will be working on in the next few iterations of the project. Stay tuned for some updates soon!

+ +

Some rich content to copy

+ +

Copy also this content to check how pasting from outside of the editor works. Feel free to also use content from other websites.

+ +

This is the third developer preview of CKEditor 5.

+ +

After 2 years of work, building the next generation editor from scratch and closing over 670 tickets, we created a highly extensible and flexible architecture which consists of an amazing editing framework and editing solutions that will be built on top of it.

+ +

Notes

+ +

CKEditor 5 is under heavy development and this demo is not production-ready software. For example:

+ + + +

It has bugs that we are aware of – and that we will be working on in the next few iterations of the project. Stay tuned for some updates soon!

diff --git a/tests/pasting-integration.js b/tests/pasting-integration.js index 17e3de9..dd66351 100644 --- a/tests/pasting-integration.js +++ b/tests/pasting-integration.js @@ -115,6 +115,89 @@ describe( 'Pasting – integration', () => { } ); } ); } ); + + describe( 'white spaces', () => { + // See https://github.com/ckeditor/ckeditor5-clipboard/issues/2#issuecomment-310417731. + it( 'keeps spaces around inline styles (Chrome)', () => { + return ClassicTestEditor + .create( element, { plugins: [ Clipboard, Paragraph, Bold, Italic, Link ] } ) + .then( editor => { + setData( editor.document, 'x[]y' ); + + pasteHtml( editor, + '' + + 'This is the\u00a0' + + 'third developer preview' + + '\u00a0of\u00a0' + + 'CKEditor\u00a05' + + '.' + ); + + expect( getData( editor.document ) ).to.equal( + '' + + 'xThis is the ' + + '<$text linkHref="url">third developer preview of <$text bold="true">CKEditor\u00a05' + + '.[]y' + + '' + ); + + return editor.destroy(); + } ); + } ); + + // See https://github.com/ckeditor/ckeditor5-clipboard/issues/2#issuecomment-310417731. + it( 'keeps spaces around inline styles (Safari)', () => { + return ClassicTestEditor + .create( element, { plugins: [ Clipboard, Paragraph, Bold, Italic, Link ] } ) + .then( editor => { + setData( editor.document, 'x[]y' ); + + /* eslint-disable max-len */ + pasteHtml( editor, + 'This is the\u00a0' + + 'third developer preview' + + '\u00a0of\u00a0' + + 'CKEditor\u00a05' + + '.' + ); + /* eslint-enable max-len */ + + expect( getData( editor.document ) ).to.equal( + '' + + 'xThis is the ' + + '<$text linkHref="url">third developer preview of <$text bold="true">CKEditor\u00a05' + + '.[]y' + + '' + ); + + return editor.destroy(); + } ); + } ); + + it( 'keeps spaces around inline styles (Firefox)', () => { + return ClassicTestEditor + .create( element, { plugins: [ Clipboard, Paragraph, Bold, Italic, Link ] } ) + .then( editor => { + setData( editor.document, 'x[]y' ); + + // Note, when copying the HTML from Firefox's console you'll see only normal spaces, + // but when you check it later in the model it's still an nbsp. + pasteHtml( editor, + 'This is the third developer preview of CKEditor\u00a05.' + ); + + expect( getData( editor.document ) ).to.equal( + '' + + 'xThis is the ' + + '<$text linkHref="url">third developer preview of <$text bold="true">CKEditor\u00a05' + + '.[]y' + + '' + ); + + return editor.destroy(); + } ); + } ); + } ); } ); function pasteHtml( editor, html ) { diff --git a/tests/utils/normalizeclipboarddata.js b/tests/utils/normalizeclipboarddata.js index 19bcfab..1a6b949 100644 --- a/tests/utils/normalizeclipboarddata.js +++ b/tests/utils/normalizeclipboarddata.js @@ -5,7 +5,7 @@ import normalizeClipboardData from '../../src/utils/normalizeclipboarddata'; -describe( 'normalizeClipboardData', () => { +describe( 'normalizeClipboardData()', () => { it( 'should strip all span.Apple-converted-space', () => { expect( normalizeClipboardData( ' \t\nx\u00a0\u00a0' @@ -17,4 +17,44 @@ describe( 'normalizeClipboardData', () => { normalizeClipboardData( ' x\u00a0' ) ).to.equal( ' x ' ); } ); + + it( 'should strip all spans with no attributes', () => { + expect( normalizeClipboardData( + ' \t\nx\u00a0\u00a0' + ) ).to.equal( ' \t\nx\u00a0\u00a0' ); + } ); + + it( 'should replace spans with no attributes with a normal space', () => { + expect( + normalizeClipboardData( ' x\u00a0' ) + ).to.equal( ' x ' ); + } ); + + it( 'should not strip spans with no attributes if they contain anything but spaces', () => { + expect( + normalizeClipboardData( ' axb\u00a0xc' ) + ).to.equal( ' axb\u00a0xc' ); + } ); + + it( 'should not replace spans of length 1+ with normal space', () => { + expect( + normalizeClipboardData( ' x\u00a0 x\u00a0\u00a0x \u00a0' ) + ).to.equal( ' x\u00a0 x\u00a0\u00a0x \u00a0' ); + } ); + + it( 'should not strip spans with any attribute (except span.Apple-converted-space)', () => { + const input = + ' x' + + '\u00a0x' + + ' x' + + '\u00a0'; + + expect( normalizeClipboardData( input ) ).to.equal( input ); + } ); + + it( 'should not be greedy', () => { + expect( + normalizeClipboardData( ' a' ) + ).to.equal( ' a' ); + } ); } ); diff --git a/tests/utils/plaintexttohtml.js b/tests/utils/plaintexttohtml.js index ab266c7..7a7b1ca 100644 --- a/tests/utils/plaintexttohtml.js +++ b/tests/utils/plaintexttohtml.js @@ -5,7 +5,7 @@ import plainTextToHtml from '../../src/utils/plaintexttohtml'; -describe( 'plainTextToHtml', () => { +describe( 'plainTextToHtml()', () => { it( 'encodes < and >', () => { expect( plainTextToHtml( 'x y ' ) ).to.equal( 'x y <z>' ); } ); diff --git a/tests/utils/viewtoplaintext.js b/tests/utils/viewtoplaintext.js index 8a8d3e9..f57af7d 100644 --- a/tests/utils/viewtoplaintext.js +++ b/tests/utils/viewtoplaintext.js @@ -7,7 +7,7 @@ import viewToPlainText from '../../src/utils/viewtoplaintext'; import { parse as parseView } from '@ckeditor/ckeditor5-engine/src/dev-utils/view'; -describe( 'viewToPlainText', () => { +describe( 'viewToPlainText()', () => { function test( viewString, expectedText ) { const view = parseView( viewString ); const text = viewToPlainText( view );