|
3 | 3 | * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options |
4 | 4 | */ |
5 | 5 |
|
| 6 | +/* globals document */ |
| 7 | + |
6 | 8 | import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor.js'; |
7 | 9 | import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph.js'; |
8 | 10 | import ImageInlineEditing from '@ckeditor/ckeditor5-image/src/image/imageinlineediting.js'; |
9 | 11 | import ShiftEnter from '@ckeditor/ckeditor5-enter/src/shiftenter.js'; |
| 12 | +import createElement from '@ckeditor/ckeditor5-utils/src/dom/createelement.js'; |
10 | 13 |
|
11 | 14 | import { getData } from '../../../src/dev-utils/model.js'; |
| 15 | +import { getFillerOffset } from '../../../src/index.js'; |
12 | 16 |
|
13 | 17 | // NOTE: |
14 | 18 | // dev utils' setData() loses white spaces so don't use it for tests here!!! |
@@ -193,13 +197,60 @@ describe( 'DomConverter – whitespace handling – integration', () => { |
193 | 197 | expect( editor.getData() ).to.equal( '<p> foo </p>' ); |
194 | 198 | } ); |
195 | 199 |
|
196 | | - it( 'single nbsp inside blocks are ignored', () => { |
| 200 | + it( 'single nbsp inside blocks is ignored (NBSP block filler)', () => { |
197 | 201 | editor.setData( '<p> </p>' ); |
198 | 202 |
|
199 | 203 | expect( getData( editor.model, { withoutSelection: true } ) ) |
200 | 204 | .to.equal( '<paragraph></paragraph>' ); |
201 | 205 |
|
202 | 206 | expect( editor.getData() ).to.equal( '' ); // trimmed |
| 207 | + expect( editor.getData( { trim: false } ) ).to.equal( '<p> </p>' ); |
| 208 | + } ); |
| 209 | + |
| 210 | + it( 'nbsp with spaces inside blocks is ignored (NBSP block filler)', () => { |
| 211 | + editor.setData( '<p>\n \n </p>' ); |
| 212 | + |
| 213 | + expect( getData( editor.model, { withoutSelection: true } ) ) |
| 214 | + .to.equal( '<paragraph></paragraph>' ); |
| 215 | + |
| 216 | + expect( editor.getData() ).to.equal( '' ); // trimmed |
| 217 | + expect( editor.getData( { trim: false } ) ).to.equal( '<p> </p>' ); |
| 218 | + } ); |
| 219 | + |
| 220 | + it( 'single nbsp inside blocks is ignored (marked NBSP block filler)', () => { |
| 221 | + editor.data.processor.useFillerType( 'marked' ); |
| 222 | + |
| 223 | + editor.conversion.for( 'upcast' ).add( dispatcher => { |
| 224 | + dispatcher.on( 'element', ( evt, data ) => { |
| 225 | + expect( data.viewItem.name ).to.not.equal( 'span' ); |
| 226 | + } ); |
| 227 | + } ); |
| 228 | + |
| 229 | + editor.setData( '<p><span data-cke-filler="true"> </span></p>' ); |
| 230 | + |
| 231 | + expect( getData( editor.model, { withoutSelection: true } ) ) |
| 232 | + .to.equal( '<paragraph></paragraph>' ); |
| 233 | + |
| 234 | + expect( editor.getData() ).to.equal( '' ); // trimmed |
| 235 | + expect( editor.getData( { trim: false } ) ).to.equal( '<p><span data-cke-filler="true"> </span></p>' ); |
| 236 | + } ); |
| 237 | + |
| 238 | + it( 'nbsp with spaces inside blocks are ignored (marked NBSP block filler)', () => { |
| 239 | + editor.data.processor.useFillerType( 'marked' ); |
| 240 | + |
| 241 | + editor.conversion.for( 'upcast' ).add( dispatcher => { |
| 242 | + dispatcher.on( 'element', ( evt, data ) => { |
| 243 | + expect( data.viewItem.name ).to.not.equal( 'span' ); |
| 244 | + } ); |
| 245 | + } ); |
| 246 | + |
| 247 | + editor.setData( '<p>\n <span data-cke-filler="true"> </span>\n </p>' ); |
| 248 | + |
| 249 | + expect( getData( editor.model, { withoutSelection: true } ) ) |
| 250 | + .to.equal( '<paragraph></paragraph>' ); |
| 251 | + |
| 252 | + expect( editor.getData() ).to.equal( '' ); // trimmed |
| 253 | + expect( editor.getData( { trim: false } ) ).to.equal( '<p><span data-cke-filler="true"> </span></p>' ); |
203 | 254 | } ); |
204 | 255 |
|
205 | 256 | it( 'all whitespaces together are ignored', () => { |
@@ -878,6 +929,114 @@ describe( 'DomConverter – whitespace handling – integration', () => { |
878 | 929 | '</ul>' |
879 | 930 | ); |
880 | 931 | } ); |
| 932 | + |
| 933 | + describe( 'text nodes parse and stringify', () => { |
| 934 | + function testTexts( inputTexts, processedText, outputText ) { |
| 935 | + if ( typeof inputTexts == 'string' ) { |
| 936 | + inputTexts = [ inputTexts ]; |
| 937 | + } |
| 938 | + |
| 939 | + outputText = outputText !== undefined ? outputText : inputTexts.join( '' ); |
| 940 | + |
| 941 | + it( `spaces in a text node: "${ inputTexts.join( '|' ) }" -> "${ processedText }" -> "${ outputText }"`, () => { |
| 942 | + const domElement = createElement( document, 'p', {}, [] ); |
| 943 | + |
| 944 | + for ( const text of inputTexts ) { |
| 945 | + domElement.appendChild( document.createTextNode( text.replace( /_/g, '\u00A0' ) ) ); |
| 946 | + } |
| 947 | + |
| 948 | + const viewElement = editor.data.processor.domConverter.domToView( domElement ); |
| 949 | + let viewData = ''; |
| 950 | + |
| 951 | + viewElement.getFillerOffset = getFillerOffset; |
| 952 | + |
| 953 | + for ( const child of viewElement.getChildren() ) { |
| 954 | + viewData += child.data.replace( /\u00A0/g, '_' ); |
| 955 | + } |
| 956 | + |
| 957 | + expect( viewData, 'processed' ).to.equal( processedText ); |
| 958 | + |
| 959 | + const outputDomElement = editor.data.processor.domConverter.viewToDom( viewElement ); |
| 960 | + |
| 961 | + expect( outputDomElement.innerHTML.replace( / /g, '_' ), 'output' ).to.equal( outputText ); |
| 962 | + } ); |
| 963 | + } |
| 964 | + |
| 965 | + // Block filler. |
| 966 | + testTexts( '_', '', '_' ); |
| 967 | + testTexts( ' _ ', '', '_' ); |
| 968 | + testTexts( ' _ ', '', '_' ); |
| 969 | + |
| 970 | + // At the beginning. |
| 971 | + testTexts( '_x', ' x' ); |
| 972 | + testTexts( '_ x', ' x' ); |
| 973 | + testTexts( '_ _x', ' x' ); |
| 974 | + testTexts( '_ _ x', ' x' ); |
| 975 | + |
| 976 | + // At the end. |
| 977 | + testTexts( 'x_', 'x ' ); |
| 978 | + testTexts( 'x _', 'x ' ); |
| 979 | + testTexts( 'x __', 'x ' ); |
| 980 | + testTexts( 'x _ _', 'x ' ); |
| 981 | + |
| 982 | + // In the middle. |
| 983 | + testTexts( 'x x', 'x x' ); |
| 984 | + testTexts( 'x _x', 'x x' ); |
| 985 | + testTexts( 'x _ x', 'x x' ); |
| 986 | + testTexts( 'x _ _x', 'x x' ); |
| 987 | + |
| 988 | + // Complex. |
| 989 | + testTexts( '_x_', ' x ' ); |
| 990 | + testTexts( '_ x _x _', ' x x ' ); |
| 991 | + testTexts( '_ _x x _', ' x x ' ); |
| 992 | + testTexts( '_ _x x __', ' x x ' ); |
| 993 | + testTexts( '_ _x _ _x_', ' x x ' ); |
| 994 | + |
| 995 | + // With hard |
| 996 | + testTexts( '_x', ' x' ); |
| 997 | + testTexts( '__x', ' _x' ); |
| 998 | + testTexts( '___x', ' __x' ); |
| 999 | + testTexts( '__ x', ' _ x' ); |
| 1000 | + |
| 1001 | + testTexts( 'x_', 'x ' ); |
| 1002 | + testTexts( 'x__', 'x_ ' ); |
| 1003 | + testTexts( 'x___', 'x__ ' ); |
| 1004 | + |
| 1005 | + testTexts( 'x_x', 'x_x' ); |
| 1006 | + testTexts( 'x___x', 'x___x' ); |
| 1007 | + testTexts( 'x____x', 'x____x' ); |
| 1008 | + testTexts( 'x__ x', 'x__ x' ); |
| 1009 | + testTexts( 'x___ x', 'x___ x' ); |
| 1010 | + testTexts( 'x_ _x', 'x_ x' ); |
| 1011 | + testTexts( 'x __x', 'x _x' ); |
| 1012 | + testTexts( 'x _ x', 'x x' ); |
| 1013 | + testTexts( 'x __ _x', 'x _ x' ); |
| 1014 | + |
| 1015 | + // Two text nodes. |
| 1016 | + testTexts( [ 'x', 'y' ], 'xy' ); |
| 1017 | + testTexts( [ 'x ', 'y' ], 'x y' ); |
| 1018 | + testTexts( [ 'x _', 'y' ], 'x y' ); |
| 1019 | + testTexts( [ 'x __', 'y' ], 'x y' ); |
| 1020 | + testTexts( [ 'x _ _', 'y' ], 'x y', 'x _ _y' ); |
| 1021 | + |
| 1022 | + testTexts( [ 'x', ' y' ], 'x y' ); |
| 1023 | + testTexts( [ 'x_', ' y' ], 'x y' ); |
| 1024 | + testTexts( [ 'x _', ' y' ], 'x y' ); |
| 1025 | + testTexts( [ 'x __', ' y' ], 'x y' ); |
| 1026 | + testTexts( [ 'x _ _', ' y' ], 'x y' ); |
| 1027 | + |
| 1028 | + testTexts( [ 'x', ' _y' ], 'x y' ); |
| 1029 | + testTexts( [ 'x_', ' _y' ], 'x y' ); |
| 1030 | + testTexts( [ 'x _', ' _y' ], 'x y' ); |
| 1031 | + testTexts( [ 'x __', ' _y' ], 'x y' ); |
| 1032 | + testTexts( [ 'x _ _', ' _y' ], 'x y' ); |
| 1033 | + |
| 1034 | + // Some tests with hard |
| 1035 | + testTexts( [ 'x', '_y' ], 'x_y' ); |
| 1036 | + testTexts( [ 'x_', 'y' ], 'x_y' ); |
| 1037 | + testTexts( [ 'x__', ' y' ], 'x_ y' ); |
| 1038 | + testTexts( [ 'x_ _', ' y' ], 'x_ y' ); |
| 1039 | + } ); |
881 | 1040 | } ); |
882 | 1041 |
|
883 | 1042 | // https://github.com/ckeditor/ckeditor5/issues/1024 |
|
0 commit comments