UNPKG

3.32 kBJavaScriptView Raw
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 */
19export 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 &nbsp;.
28 .replace( /<o:p>(&nbsp;|\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 `&nbsp; ` 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 */
40export 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 `&nbsp; ` 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 / &nbsp; sequence for replacement.
54//
55// @param {String} htmlString HTML string in which spacing should be normalized
56// @returns {String} Input HTML with spaces normalized.
57function 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}