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

Validate RegExp used for URL & emails.

Maciej Gołaszewski 5 лет назад
Родитель
Сommit
d6db7975ba
2 измененных файлов с 71 добавлено и 4 удалено
  1. 24 4
      packages/ckeditor5-link/src/autolink.js
  2. 47 0
      packages/ckeditor5-link/tests/autolink.js

+ 24 - 4
packages/ckeditor5-link/src/autolink.js

@@ -13,7 +13,25 @@ import getLastTextLine from '@ckeditor/ckeditor5-typing/src/utils/getlasttextlin
 
 
 const MIN_LINK_LENGTH_WITH_SPACE_AT_END = 4; // Ie: "t.co " (length 5).
 const MIN_LINK_LENGTH_WITH_SPACE_AT_END = 4; // Ie: "t.co " (length 5).
 
 
-const urlRegExp = /(https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&//=]*))$/;
+const urlRegExp = new RegExp(
+	// Group 1: Line start or after a space.
+	'(^|\\s)' + // Match .
+	// Group 2: Full detected URL.
+	'(' +
+		// Group 3 + 4: Protocol + domain.
+		'(([a-z]{3,9}:(?:\\/\\/)?)(?:[\\w]+)?[a-z0-9.-]+|(?:www\\.|[\\w]+)[a-z0-9.-]+)' +
+		// Group 5: Optional path + query string + location.
+		'((?:\\/[+~%/.\\w\\-_]*)?\\??(?:[-+=&;%@.\\w_]*)#?(?:[.!/\\\\\\w]*))?' +
+	')$', 'i' );
+
+// Simplified email test - should be run over previously found URL.
+const emailRegExp = /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$/i;
+
+const URL_POSITION_IN_MATCH = 2;
+
+function isEmail( linkHref ) {
+	return emailRegExp.exec( linkHref );
+}
 
 
 /**
 /**
  * The auto link plugin.
  * The auto link plugin.
@@ -57,7 +75,7 @@ export default class AutoLink extends Plugin {
 				return;
 				return;
 			}
 			}
 
 
-			this._applyAutoLink( match[ 1 ], range );
+			this._applyAutoLink( match[ URL_POSITION_IN_MATCH ], range );
 		} );
 		} );
 
 
 		// todo: watcher.bind();
 		// todo: watcher.bind();
@@ -112,7 +130,7 @@ export default class AutoLink extends Plugin {
 		const match = urlRegExp.exec( text );
 		const match = urlRegExp.exec( text );
 
 
 		if ( match ) {
 		if ( match ) {
-			this._applyAutoLink( match[ 1 ], range, 0 );
+			this._applyAutoLink( match[ URL_POSITION_IN_MATCH ], range, 0 );
 		}
 		}
 	}
 	}
 
 
@@ -124,7 +142,9 @@ export default class AutoLink extends Plugin {
 				range.end.getShiftedBy( -additionalOffset )
 				range.end.getShiftedBy( -additionalOffset )
 			);
 			);
 
 
-			writer.setAttribute( 'linkHref', linkHref, linkRange );
+			const linkHrefValue = isEmail( linkHref ) ? `mailto://${ linkHref }` : linkHref;
+
+			writer.setAttribute( 'linkHref', linkHrefValue, linkRange );
 		} );
 		} );
 	}
 	}
 }
 }

+ 47 - 0
packages/ckeditor5-link/tests/autolink.js

@@ -130,6 +130,53 @@ describe( 'AutoLink', () => {
 			);
 			);
 		} );
 		} );
 
 
+		it( 'adds "mailto://" to link of detected email addresses', () => {
+			simulateTyping( 'newsletter@cksource.com ' );
+
+			expect( getData( model ) ).to.equal(
+				'<paragraph><$text linkHref="mailto://newsletter@cksource.com">newsletter@cksource.com</$text> []</paragraph>'
+			);
+		} );
+
+		const supportedURLs = [
+			'http://cksource.com',
+			'https://cksource.com',
+			'http://www.cksource.com',
+			'hTtP://WwW.cKsOuRcE.cOm',
+			'http://foo.bar.cksource.com',
+			'http://www.cksource.com/some/path/index.html#abc',
+			'http://www.cksource.com/some/path/index.html?foo=bar',
+			'http://www.cksource.com/some/path/index.html?foo=bar#abc',
+			'http://localhost',
+			'ftp://cksource.com',
+			'mailto://cksource@cksource.com',
+			'www.cksource.com',
+			'cksource.com'
+		];
+
+		const unsupportedURLs = [
+			'http://www.cksource.com/some/path/index.html#abc?foo=bar', // Wrong #? sequence.
+			'http:/cksource.com'
+		];
+
+		for ( const supportedURL of supportedURLs ) {
+			it( `should detect "${ supportedURL }" as a valid URL`, () => {
+				simulateTyping( supportedURL + ' ' );
+
+				expect( getData( model ) ).to.equal(
+					`<paragraph><$text linkHref="${ supportedURL }">${ supportedURL }</$text> []</paragraph>` );
+			} );
+		}
+
+		for ( const unsupportedURL of unsupportedURLs ) {
+			it( `should not detect "${ unsupportedURL }" as a valid URL`, () => {
+				simulateTyping( unsupportedURL + ' ' );
+
+				expect( getData( model ) ).to.equal(
+					`<paragraph>${ unsupportedURL } []</paragraph>` );
+			} );
+		}
+
 		function simulateTyping( text ) {
 		function simulateTyping( text ) {
 			const letters = text.split( '' );
 			const letters = text.split( '' );