8
0
Просмотр исходного кода

Internal: Moved parsing and spacing normalization functions to separate files.

Krzysztof Krztoń 7 лет назад
Родитель
Сommit
29b9d42337

+ 3 - 28
packages/ckeditor5-paste-from-office/src/filters/utils.js → packages/ckeditor5-paste-from-office/src/filters/parse.js

@@ -4,7 +4,7 @@
  */
 
 /**
- * @module paste-from-office/filters/utils
+ * @module paste-from-office/filters/parse
  */
 
 /* globals DOMParser */
@@ -12,6 +12,8 @@
 import DomConverter from '@ckeditor/ckeditor5-engine/src/view/domconverter';
 import { NBSP_FILLER } from '@ckeditor/ckeditor5-engine/src/view/filler';
 
+import { normalizeEndTagsPrecedingSpace, normalizeSpacerunSpans } from './space';
+
 /**
  * Parses provided HTML extracting contents of `<body>` and `<style>` tags.
  *
@@ -89,30 +91,3 @@ function extractStyles( htmlDocument ) {
 		stylesString: stylesString.join( ' ' )
 	};
 }
-
-// Replaces last space preceding elements closing tag with `&nbsp;`. Such operation prevents spaces from being removed
-// during further DOM/View processing (see especially {@link module:engine/view/domconverter~DomConverter#_processDataFromDomText}).
-// This method also takes into account Word specific `<o:p></o:p>` empty tags.
-//
-// @param {String} htmlString HTML string in which spacing should be normalized.
-// @returns {String} Input HTML with spaces normalized.
-function normalizeEndTagsPrecedingSpace( htmlString ) {
-	return htmlString
-		.replace( / <\//g, '\u00A0</' )
-		.replace( / <o:p><\/o:p>/g, '\u00A0<o:p></o:p>' );
-}
-
-// Normalizes spacing in special Word `spacerun spans` (`<span style='mso-spacerun:yes'>\s+</span>`) by replacing
-// all spaces with `&nbsp; ` pairs. This prevents spaces from being removed during further DOM/View processing
-// (see especially {@link module:engine/view/domconverter~DomConverter#_processDataFromDomText}).
-//
-// @param {Document} htmlDocument Native `Document` object in which spacing should be normalized.
-function normalizeSpacerunSpans( htmlDocument ) {
-	htmlDocument.querySelectorAll( 'span[style*=spacerun]' ).forEach( el => {
-		// Use `el.childNodes[ 0 ].data.length` instead of `el.innerText.length`. For `el.innerText.length` which
-		// contains spaces mixed with `&nbsp;` Edge browser returns incorrect length.
-		const innerTextLength = el.childNodes[ 0 ].data.length;
-
-		el.innerHTML = Array( innerTextLength + 1 ).join( '\u00A0 ' ).substr( 0, innerTextLength );
-	} );
-}

+ 39 - 0
packages/ckeditor5-paste-from-office/src/filters/space.js

@@ -0,0 +1,39 @@
+/**
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/**
+ * @module paste-from-office/filters/space
+ */
+
+/**
+ * Replaces last space preceding elements closing tag with `&nbsp;`. Such operation prevents spaces from being removed
+ * during further DOM/View processing (see especially {@link module:engine/view/domconverter~DomConverter#_processDataFromDomText}).
+ * This method also takes into account Word specific `<o:p></o:p>` empty tags.
+ *
+ * @param {String} htmlString HTML string in which spacing should be normalized.
+ * @returns {String} Input HTML with spaces normalized.
+ */
+export function normalizeEndTagsPrecedingSpace( htmlString ) {
+	return htmlString
+		.replace( / <\//g, '\u00A0</' )
+		.replace( / <o:p><\/o:p>/g, '\u00A0<o:p></o:p>' );
+}
+
+/**
+ * Normalizes spacing in special Word `spacerun spans` (`<span style='mso-spacerun:yes'>\s+</span>`) by replacing
+ * all spaces with `&nbsp; ` pairs. This prevents spaces from being removed during further DOM/View processing
+ * (see especially {@link module:engine/view/domconverter~DomConverter#_processDataFromDomText}).
+ *
+ * @param {Document} htmlDocument Native `Document` object in which spacing should be normalized.
+ */
+export function normalizeSpacerunSpans( htmlDocument ) {
+	htmlDocument.querySelectorAll( 'span[style*=spacerun]' ).forEach( el => {
+		// Use `el.childNodes[ 0 ].data.length` instead of `el.innerText.length`. For `el.innerText.length` which
+		// contains spaces mixed with `&nbsp;` Edge browser returns incorrect length.
+		const innerTextLength = el.childNodes[ 0 ].data.length;
+
+		el.innerHTML = Array( innerTextLength + 1 ).join( '\u00A0 ' ).substr( 0, innerTextLength );
+	} );
+}

+ 1 - 1
packages/ckeditor5-paste-from-office/src/pastefromoffice.js

@@ -10,7 +10,7 @@
 import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 import Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';
 
-import { parseHtml } from './filters/utils';
+import { parseHtml } from './filters/parse';
 import { transformListItemLikeElementsIntoLists } from './filters/list';
 
 /**

+ 96 - 0
packages/ckeditor5-paste-from-office/tests/filters/parse.js

@@ -0,0 +1,96 @@
+/**
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* globals CSSStyleSheet */
+
+import DocumentFragment from '@ckeditor/ckeditor5-engine/src/view/documentfragment';
+
+import { parseHtml } from '../../src/filters/parse';
+
+describe( 'Filters', () => {
+	describe( 'parse', () => {
+		describe( 'parseHtml', () => {
+			it( 'correctly parses HTML with body and one style tag', () => {
+				const html = '<head><style>p { color: red; } a { font-size: 12px; }</style></head><body><p>Foo Bar</p></body>';
+				const { body, bodyString, styles, stylesString } = parseHtml( html );
+
+				expect( body ).to.instanceof( DocumentFragment );
+				expect( body.childCount ).to.equal( 1, 'body.childCount' );
+
+				expect( bodyString ).to.equal( '<p>Foo Bar</p>' );
+
+				expect( styles.length ).to.equal( 1, 'styles.length' );
+				expect( styles[ 0 ] ).to.instanceof( CSSStyleSheet );
+				expect( styles[ 0 ].cssRules.length ).to.equal( 2 );
+				expect( styles[ 0 ].cssRules[ 0 ].style.color ).to.equal( 'red' );
+				expect( styles[ 0 ].cssRules[ 1 ].style[ 'font-size' ] ).to.equal( '12px' );
+
+				expect( stylesString ).to.equal( 'p { color: red; } a { font-size: 12px; }' );
+			} );
+
+			it( 'correctly parses HTML with body contents only', () => {
+				const html = '<p>Foo Bar</p>';
+				const { body, bodyString, styles, stylesString } = parseHtml( html );
+
+				expect( body ).to.instanceof( DocumentFragment );
+				expect( body.childCount ).to.equal( 1 );
+
+				expect( bodyString ).to.equal( '<p>Foo Bar</p>' );
+
+				expect( styles.length ).to.equal( 0 );
+
+				expect( stylesString ).to.equal( '' );
+			} );
+
+			it( 'correctly parses HTML with no body and multiple style tags', () => {
+				const html = '<html><head><style>p { color: blue; }</style><style>a { color: green; }</style></head></html>';
+				const { body, bodyString, styles, stylesString } = parseHtml( html );
+
+				expect( body ).to.instanceof( DocumentFragment );
+				expect( body.childCount ).to.equal( 0 );
+
+				expect( bodyString ).to.equal( '' );
+
+				expect( styles.length ).to.equal( 2 );
+				expect( styles[ 0 ] ).to.instanceof( CSSStyleSheet );
+				expect( styles[ 1 ] ).to.instanceof( CSSStyleSheet );
+				expect( styles[ 0 ].cssRules.length ).to.equal( 1 );
+				expect( styles[ 1 ].cssRules.length ).to.equal( 1 );
+				expect( styles[ 0 ].cssRules[ 0 ].style.color ).to.equal( 'blue' );
+				expect( styles[ 1 ].cssRules[ 0 ].style.color ).to.equal( 'green' );
+
+				expect( stylesString ).to.equal( 'p { color: blue; } a { color: green; }' );
+			} );
+
+			it( 'correctly parses HTML with no body and no style tags', () => {
+				const html = '<html><head><meta name="Foo" content="Bar"></head></html>';
+				const { body, bodyString, styles, stylesString } = parseHtml( html );
+
+				expect( body ).to.instanceof( DocumentFragment );
+				expect( body.childCount ).to.equal( 0 );
+
+				expect( bodyString ).to.equal( '' );
+
+				expect( styles.length ).to.equal( 0 );
+
+				expect( stylesString ).to.equal( '' );
+			} );
+
+			it( 'correctly parses HTML with body contents and empty style tag', () => {
+				const html = '<head><style></style></head><body><p>Foo Bar</p></body>';
+				const { body, bodyString, styles, stylesString } = parseHtml( html );
+
+				expect( body ).to.instanceof( DocumentFragment );
+				expect( body.childCount ).to.equal( 1 );
+
+				expect( bodyString ).to.equal( '<p>Foo Bar</p>' );
+
+				expect( styles.length ).to.equal( 0 );
+
+				expect( stylesString ).to.equal( '' );
+			} );
+		} );
+	} );
+} );

+ 50 - 0
packages/ckeditor5-paste-from-office/tests/filters/space.js

@@ -0,0 +1,50 @@
+/**
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* globals DOMParser */
+
+import normalizeHtml from '@ckeditor/ckeditor5-utils/tests/_utils/normalizehtml';
+
+import { normalizeEndTagsPrecedingSpace, normalizeSpacerunSpans } from '../../src/filters/space';
+
+describe( 'Filters', () => {
+	describe( 'space', () => {
+		describe( 'normalizeEndTagsPrecedingSpace', () => {
+			it( 'should replace last space before closing tag with NBSP', () => {
+				const input = '<p>Foo </p><p><span> Bar  </span> Baz </p>';
+				const expected = '<p>Foo\u00A0</p><p><span> Bar \u00A0</span> Baz\u00A0</p>';
+
+				expect( normalizeEndTagsPrecedingSpace( input ) ).to.equal( expected );
+			} );
+
+			it( 'should replace last space before special "o:p" tag with NBSP', () => {
+				const input = '<p>Foo  <o:p></o:p><span> <o:p></o:p> Bar</span></p>';
+				const expected = '<p>Foo \u00A0<o:p></o:p><span>\u00A0<o:p></o:p> Bar</span></p>';
+
+				expect( normalizeEndTagsPrecedingSpace( input ) ).to.equal( expected );
+			} );
+		} );
+
+		describe( 'normalizeSpacerunSpans', () => {
+			it( 'should normalize spaces inside special "span.spacerun" elements', () => {
+				const input = '<p> <span style=\'mso-spacerun:yes\'>   </span>Foo</p>' +
+					'<p> Baz <span style=\'mso-spacerun:yes\'>      </span></p>';
+
+				const expected = '<p> <span style="mso-spacerun:yes">&nbsp; &nbsp;</span>Foo</p>' +
+					'<p> Baz <span style="mso-spacerun:yes">&nbsp; &nbsp; &nbsp; </span></p>';
+
+				const domParser = new DOMParser();
+				const htmlDocument = domParser.parseFromString( input, 'text/html' );
+
+				expect( htmlDocument.body.innerHTML.replace( /'/g, '"' ).replace( /: /g, ':' ) ).to.not.equal( expected );
+
+				normalizeSpacerunSpans( htmlDocument );
+
+				expect( htmlDocument.body.innerHTML.replace( /'/g, '"' ).replace( /: /g, ':' ) ).to.equal( expected );
+			} );
+
+		} );
+	} );
+} );

+ 0 - 94
packages/ckeditor5-paste-from-office/tests/filters/utils.js

@@ -1,94 +0,0 @@
-/**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* globals CSSStyleSheet */
-
-import DocumentFragment from '@ckeditor/ckeditor5-engine/src/view/documentfragment';
-
-import { parseHtml } from '../../src/filters/utils';
-
-describe( 'Filters – utils', () => {
-	describe( 'parseHtml', () => {
-		it( 'correctly parses HTML with body and one style tag', () => {
-			const html = '<head><style>p { color: red; } a { font-size: 12px; }</style></head><body><p>Foo Bar</p></body>';
-			const { body, bodyString, styles, stylesString } = parseHtml( html );
-
-			expect( body ).to.instanceof( DocumentFragment );
-			expect( body.childCount ).to.equal( 1, 'body.childCount' );
-
-			expect( bodyString ).to.equal( '<p>Foo Bar</p>' );
-
-			expect( styles.length ).to.equal( 1, 'styles.length' );
-			expect( styles[ 0 ] ).to.instanceof( CSSStyleSheet );
-			expect( styles[ 0 ].cssRules.length ).to.equal( 2 );
-			expect( styles[ 0 ].cssRules[ 0 ].style.color ).to.equal( 'red' );
-			expect( styles[ 0 ].cssRules[ 1 ].style[ 'font-size' ] ).to.equal( '12px' );
-
-			expect( stylesString ).to.equal( 'p { color: red; } a { font-size: 12px; }' );
-		} );
-
-		it( 'correctly parses HTML with body contents only', () => {
-			const html = '<p>Foo Bar</p>';
-			const { body, bodyString, styles, stylesString } = parseHtml( html );
-
-			expect( body ).to.instanceof( DocumentFragment );
-			expect( body.childCount ).to.equal( 1 );
-
-			expect( bodyString ).to.equal( '<p>Foo Bar</p>' );
-
-			expect( styles.length ).to.equal( 0 );
-
-			expect( stylesString ).to.equal( '' );
-		} );
-
-		it( 'correctly parses HTML with no body and multiple style tags', () => {
-			const html = '<html><head><style>p { color: blue; }</style><style>a { color: green; }</style></head></html>';
-			const { body, bodyString, styles, stylesString } = parseHtml( html );
-
-			expect( body ).to.instanceof( DocumentFragment );
-			expect( body.childCount ).to.equal( 0 );
-
-			expect( bodyString ).to.equal( '' );
-
-			expect( styles.length ).to.equal( 2 );
-			expect( styles[ 0 ] ).to.instanceof( CSSStyleSheet );
-			expect( styles[ 1 ] ).to.instanceof( CSSStyleSheet );
-			expect( styles[ 0 ].cssRules.length ).to.equal( 1 );
-			expect( styles[ 1 ].cssRules.length ).to.equal( 1 );
-			expect( styles[ 0 ].cssRules[ 0 ].style.color ).to.equal( 'blue' );
-			expect( styles[ 1 ].cssRules[ 0 ].style.color ).to.equal( 'green' );
-
-			expect( stylesString ).to.equal( 'p { color: blue; } a { color: green; }' );
-		} );
-
-		it( 'correctly parses HTML with no body and no style tags', () => {
-			const html = '<html><head><meta name="Foo" content="Bar"></head></html>';
-			const { body, bodyString, styles, stylesString } = parseHtml( html );
-
-			expect( body ).to.instanceof( DocumentFragment );
-			expect( body.childCount ).to.equal( 0 );
-
-			expect( bodyString ).to.equal( '' );
-
-			expect( styles.length ).to.equal( 0 );
-
-			expect( stylesString ).to.equal( '' );
-		} );
-
-		it( 'correctly parses HTML with body contents and empty style tag', () => {
-			const html = '<head><style></style></head><body><p>Foo Bar</p></body>';
-			const { body, bodyString, styles, stylesString } = parseHtml( html );
-
-			expect( body ).to.instanceof( DocumentFragment );
-			expect( body.childCount ).to.equal( 1 );
-
-			expect( bodyString ).to.equal( '<p>Foo Bar</p>' );
-
-			expect( styles.length ).to.equal( 0 );
-
-			expect( stylesString ).to.equal( '' );
-		} );
-	} );
-} );