Преглед изворни кода

Merge branch 'i/github-writer/93' into i/5988

fredck пре 5 година
родитељ
комит
db22d92e33

+ 35 - 4
packages/ckeditor5-markdown-gfm/src/html2markdown/html2markdown.js

@@ -13,12 +13,43 @@ import { gfm } from 'turndown-plugin-gfm';
 {
 	const originalEscape = TurndownService.prototype.escape;
 	TurndownService.prototype.escape = function( string ) {
-		string = originalEscape( string );
+		// Urls should not be escaped. Our strategy is using a regex to find them and escape everything
+		// which is out of the matches parts.
 
-		// Escape "<".
-		string = string.replace( /</g, '\\<' );
+		// eslint-disable-next-line max-len
+		const regex = /\b(?:https?:\/\/|www\.)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()[\]{};:'".,<>?«»“”‘’])/g;
 
-		return string;
+		let escaped = '';
+		let lastIndex = 0;
+		let m;
+		do {
+			m = regex.exec( string );
+
+			// The substring should to to the matched index or, if nothing found, the end of the string.
+			const index = m ? m.index : string.length;
+
+			// Append the substring between the last match and the current one (if anything).
+			if ( index > lastIndex ) {
+				escaped += escape( string.substring( lastIndex, index ) );
+			}
+
+			// Append the match itself now, if anything.
+			m && ( escaped += m[ 0 ] );
+
+			lastIndex = regex.lastIndex;
+		}
+		while ( m );
+
+		return escaped;
+
+		function escape( string ) {
+			string = originalEscape( string );
+
+			// Escape "<".
+			string = string.replace( /</g, '\\<' );
+
+			return string;
+		}
 	};
 }
 

+ 43 - 0
packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/text.js

@@ -0,0 +1,43 @@
+/**
+ * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+import { testDataProcessor } from '../_utils/utils';
+
+describe( 'GFMDataProcessor', () => {
+	describe( 'text', () => {
+		describe( 'urls', () => {
+			it( 'should not escape urls', () => {
+				testDataProcessor(
+					'escape\\_this https://test.com/do_[not]-escape escape\\_this',
+					'<p>escape_this https://test.com/do_[not]-escape escape_this</p>'
+				);
+			} );
+
+			it( 'should not escape urls (at start)', () => {
+				testDataProcessor(
+					'https://test.com/do_[not]-escape escape\\_this',
+					'<p>https://test.com/do_[not]-escape escape_this</p>'
+				);
+			} );
+
+			it( 'should not escape urls (at end)', () => {
+				testDataProcessor(
+					'escape\\_this https://test.com/do_[not]-escape',
+					'<p>escape_this https://test.com/do_[not]-escape</p>'
+				);
+			} );
+
+			[
+				'https://test.com/do_[not]-escape',
+				'http://test.com/do_[not]-escape',
+				'www.test.com/do_[not]-escape'
+			].forEach( url => {
+				it( `should not escape urls (${ url })`, () => {
+					testDataProcessor( url, `<p>${ url }</p>` );
+				} );
+			} );
+		} );
+	} );
+} );