8
0
Pārlūkot izejas kodu

Merge pull request #33 from ckeditor/t/3

Fix: Remove any leftover content from after `body` closing tag. Closes #3.
Piotrek Koszuliński 7 gadi atpakaļ
vecāks
revīzija
eb2dc42036

+ 21 - 1
packages/ckeditor5-paste-from-office/src/filters/parse.js

@@ -29,8 +29,10 @@ import { normalizeSpacing, normalizeSpacerunSpans } from './space';
 export function parseHtml( htmlString ) {
 	const domParser = new DOMParser();
 
+	const normalizedHtml = normalizeSpacing( cleanContentAfterBody( htmlString ) );
+
 	// Parse htmlString as native Document object.
-	const htmlDocument = domParser.parseFromString( normalizeSpacing( htmlString ), 'text/html' );
+	const htmlDocument = domParser.parseFromString( normalizedHtml, 'text/html' );
 
 	normalizeSpacerunSpans( htmlDocument );
 
@@ -91,3 +93,21 @@ function extractStyles( htmlDocument ) {
 		stylesString: stylesString.join( ' ' )
 	};
 }
+
+// Removes leftover content from between closing </body> and closing </html> tag:
+//
+// 		<html><body><p>Foo Bar</p></body><span>Fo</span></html> -> <html><body><p>Foo Bar</p></body></html>
+//
+// This function is used as specific browsers (Edge) add some random content after `body` tag when pasting from Word.
+// @param {String} htmlString The HTML string to be cleaned.
+// @returns {String} The HTML string with leftover content removed.
+function cleanContentAfterBody( htmlString ) {
+	const regexp = /<\/body>(.*?)(<\/html>|$)/;
+	const match = htmlString.match( regexp );
+
+	if ( match && match[ 1 ] ) {
+		htmlString = htmlString.slice( 0, match.index ) + htmlString.slice( match.index ).replace( match[ 1 ], '' );
+	}
+
+	return htmlString;
+}

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

@@ -91,6 +91,76 @@ describe( 'Filters', () => {
 
 				expect( stylesString ).to.equal( '' );
 			} );
+
+			it( 'should remove any content after body closing tag - plain', () => {
+				const html = '<html><head></head><body><p>Foo Bar</p></body>Ba</html>';
+				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( 0 );
+
+				expect( stylesString ).to.equal( '' );
+			} );
+
+			it( 'should remove any content after body closing tag - inline', () => {
+				const html = '<html><head></head><body><p>Foo Bar</p></body><span>Fo</span></html>';
+				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( 0 );
+
+				expect( stylesString ).to.equal( '' );
+			} );
+
+			it( 'should remove any content after body closing tag - block', () => {
+				const html = '<html><head></head><body><p>Foo Bar</p></body><p>ar</p></html>';
+				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( 0 );
+
+				expect( stylesString ).to.equal( '' );
+			} );
+
+			it( 'should remove any content after body closing tag - no html tag', () => {
+				const html = '<head></head><body><p>Foo Bar</p></body>oo';
+				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( 0 );
+
+				expect( stylesString ).to.equal( '' );
+			} );
+
+			it( 'should not remove any content if no body tag', () => {
+				const html = '<p>Foo Bar</p>Baz';
+				const { body, bodyString, styles, stylesString } = parseHtml( html );
+
+				expect( body ).to.instanceof( DocumentFragment );
+				expect( body.childCount ).to.equal( 2, 'body.childCount' );
+
+				expect( bodyString ).to.equal( '<p>Foo Bar</p>Baz' );
+
+				expect( styles.length ).to.equal( 0 );
+
+				expect( stylesString ).to.equal( '' );
+			} );
 		} );
 	} );
 } );