UNPKG

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