1 | /**
|
2 | * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
3 | * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4 | */
|
5 |
|
6 | /**
|
7 | * @module paste-from-office/filters/space
|
8 | */
|
9 |
|
10 | /**
|
11 | * Replaces last space preceding elements closing tag with ` `. Such operation prevents spaces from being removed
|
12 | * during further DOM/View processing (see especially {@link module:engine/view/domconverter~DomConverter#_processDataFromDomText}).
|
13 | * This method also takes into account Word specific `<o:p></o:p>` empty tags.
|
14 | * Additionally multiline sequences of spaces and new lines between tags are removed (see #39 and #40).
|
15 | *
|
16 | * @param {String} htmlString HTML string in which spacing should be normalized.
|
17 | * @returns {String} Input HTML with spaces normalized.
|
18 | */
|
19 | export function normalizeSpacing( htmlString ) {
|
20 | // Run normalizeSafariSpaceSpans() two times to cover nested spans.
|
21 | return normalizeSafariSpaceSpans( normalizeSafariSpaceSpans( htmlString ) )
|
22 | // Remove all \r\n from "spacerun spans" so the last replace line doesn't strip all whitespaces.
|
23 | .replace( /(<span\s+style=['"]mso-spacerun:yes['"]>[^\S\r\n]*?)[\r\n]+([^\S\r\n]*<\/span>)/g, '$1$2' )
|
24 | .replace( /<span\s+style=['"]mso-spacerun:yes['"]><\/span>/g, '' )
|
25 | .replace( / <\//g, '\u00A0</' )
|
26 | .replace( / <o:p><\/o:p>/g, '\u00A0<o:p></o:p>' )
|
27 | // Remove <o:p> block filler from empty paragraph. Safari uses \u00A0 instead of .
|
28 | .replace( /<o:p>( |\u00A0)<\/o:p>/g, '' )
|
29 | // Remove all whitespaces when they contain any \r or \n.
|
30 | .replace( />([^\S\r\n]*[\r\n]\s*)</g, '><' );
|
31 | }
|
32 |
|
33 | /**
|
34 | * Normalizes spacing in special Word `spacerun spans` (`<span style='mso-spacerun:yes'>\s+</span>`) by replacing
|
35 | * all spaces with ` ` pairs. This prevents spaces from being removed during further DOM/View processing
|
36 | * (see especially {@link module:engine/view/domconverter~DomConverter#_processDataFromDomText}).
|
37 | *
|
38 | * @param {Document} htmlDocument Native `Document` object in which spacing should be normalized.
|
39 | */
|
40 | export function normalizeSpacerunSpans( htmlDocument ) {
|
41 | htmlDocument.querySelectorAll( 'span[style*=spacerun]' ).forEach( el => {
|
42 | const innerTextLength = el.innerText.length || 0;
|
43 |
|
44 | el.innerHTML = Array( innerTextLength + 1 ).join( '\u00A0 ' ).substr( 0, innerTextLength );
|
45 | } );
|
46 | }
|
47 |
|
48 | // Normalizes specific spacing generated by Safari when content pasted from Word (`<span class="Apple-converted-space"> </span>`)
|
49 | // by replacing all spaces sequences longer than 1 space with ` ` pairs. This prevents spaces from being removed during
|
50 | // further DOM/View processing (see especially {@link module:engine/view/domconverter~DomConverter#_processDataFromDomText}).
|
51 | //
|
52 | // This function is similar to {@link module:clipboard/utils/normalizeclipboarddata normalizeClipboardData util} but uses
|
53 | // regular spaces / sequence for replacement.
|
54 | //
|
55 | // @param {String} htmlString HTML string in which spacing should be normalized
|
56 | // @returns {String} Input HTML with spaces normalized.
|
57 | function normalizeSafariSpaceSpans( htmlString ) {
|
58 | return htmlString.replace( /<span(?: class="Apple-converted-space"|)>(\s+)<\/span>/g, ( fullMatch, spaces ) => {
|
59 | return spaces.length === 1 ? ' ' : Array( spaces.length + 1 ).join( '\u00A0 ' ).substr( 0, spaces.length );
|
60 | } );
|
61 | }
|