|
16 | 16 |
|
17 | 17 | /*!
|
18 | 18 | * Autolinker.js
|
19 |
| - * 0.13.1 |
| 19 | + * 0.14.0 |
20 | 20 | *
|
21 | 21 | * Copyright(c) 2014 Gregory Jacobs <[email protected]>
|
22 | 22 | * MIT Licensed. http://www.opensource.org/licenses/mit-license.php
|
|
243 | 243 |
|
244 | 244 | emailRegex = /(?:[\-;:&=\+\$,\w\.]+@)/, // something@ for email addresses (a.k.a. local-part)
|
245 | 245 |
|
246 |
| - protocolRegex = /(?:[A-Za-z]{3,9}:(?![A-Za-z]{3,9}:\/\/)(?:\/\/)?)/, // match protocol, allow in format "http://" or "mailto:". However, do not match the first part of something like 'link:http://www.google.com' (i.e. don't match "link:") |
| 246 | + protocolRegex = /(?:[A-Za-z][-.+A-Za-z0-9]+:(?![A-Za-z][-.+A-Za-z0-9]+:\/\/)(?!\d+\/?)(?:\/\/)?)/, // match protocol, allow in format "http://" or "mailto:". However, do not match the first part of something like 'link:http://www.google.com' (i.e. don't match "link:"). Also, make sure we don't interpret 'google.com:8000' as if 'google.com' was a protocol here (i.e. ignore a trailing port number in this regex) |
247 | 247 | wwwRegex = /(?:www\.)/, // starting with 'www.'
|
248 | 248 | domainNameRegex = /[A-Za-z0-9\.\-]*[A-Za-z0-9\-]/, // anything looking at all like a domain, non-unicode domains, not ending in a period
|
249 | 249 | tldRegex = /\.(?:international|construction|contractors|enterprises|photography|productions|foundation|immobilien|industries|management|properties|technology|christmas|community|directory|education|equipment|institute|marketing|solutions|vacations|bargains|boutique|builders|catering|cleaning|clothing|computer|democrat|diamonds|graphics|holdings|lighting|partners|plumbing|supplies|training|ventures|academy|careers|company|cruises|domains|exposed|flights|florist|gallery|guitars|holiday|kitchen|neustar|okinawa|recipes|rentals|reviews|shiksha|singles|support|systems|agency|berlin|camera|center|coffee|condos|dating|estate|events|expert|futbol|kaufen|luxury|maison|monash|museum|nagoya|photos|repair|report|social|supply|tattoo|tienda|travel|viajes|villas|vision|voting|voyage|actor|build|cards|cheap|codes|dance|email|glass|house|mango|ninja|parts|photo|shoes|solar|today|tokyo|tools|watch|works|aero|arpa|asia|best|bike|blue|buzz|camp|club|cool|coop|farm|fish|gift|guru|info|jobs|kiwi|kred|land|limo|link|menu|mobi|moda|name|pics|pink|post|qpon|rich|ruhr|sexy|tips|vote|voto|wang|wien|wiki|zone|bar|bid|biz|cab|cat|ceo|com|edu|gov|int|kim|mil|net|onl|org|pro|pub|red|tel|uno|wed|xxx|xyz|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cw|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw)\b/, // match our known top level domains (TLDs)
|
|
563 | 563 | match = new Autolinker.match.Url( {
|
564 | 564 | matchedText : matchStr,
|
565 | 565 | url : matchStr,
|
566 |
| - protocolRelativeMatch : protocolRelativeMatch, |
| 566 | + protocolUrlMatch : !!protocolUrlMatch, |
| 567 | + protocolRelativeMatch : !!protocolRelativeMatch, |
567 | 568 | stripPrefix : this.stripPrefix
|
568 | 569 | } );
|
569 | 570 | }
|
|
1318 | 1319 | * @private
|
1319 | 1320 | * @property {RegExp} hasFullProtocolRegex
|
1320 | 1321 | */
|
1321 |
| - hasFullProtocolRegex : /^[A-Za-z]{3,9}:\/\//, |
| 1322 | + hasFullProtocolRegex : /^[A-Za-z][-.+A-Za-z0-9]+:\/\//, |
1322 | 1323 |
|
1323 | 1324 | /**
|
1324 | 1325 | * Regex to test for a protocol prefix, such as 'mailto:'
|
1325 | 1326 | *
|
1326 | 1327 | * @private
|
1327 | 1328 | * @property {RegExp} hasProtocolPrefixRegex
|
1328 | 1329 | */
|
1329 |
| - hasProtocolPrefixRegex : /^[A-Za-z]{3,9}:/, |
| 1330 | + hasProtocolPrefixRegex : /^[A-Za-z][-.+A-Za-z0-9]+:/, |
1330 | 1331 |
|
1331 | 1332 | /**
|
1332 | 1333 | * Regex to determine if at least one word char exists after the protocol (i.e. after the ':')
|
1333 | 1334 | *
|
1334 | 1335 | * @private
|
1335 | 1336 | * @property {RegExp} hasWordCharAfterProtocolRegex
|
1336 | 1337 | */
|
1337 |
| - hasWordCharAfterProtocolRegex : /:.*?[A-Za-z]/, |
| 1338 | + hasWordCharAfterProtocolRegex : /:[^\s]*?[A-Za-z]/, |
1338 | 1339 |
|
1339 | 1340 |
|
1340 | 1341 | /**
|
|
1360 | 1361 | */
|
1361 | 1362 | isValidMatch : function( urlMatch, protocolUrlMatch, protocolRelativeMatch ) {
|
1362 | 1363 | if(
|
1363 |
| - this.urlMatchDoesNotHaveProtocolOrDot( urlMatch, protocolUrlMatch ) || // At least one period ('.') must exist in the URL match for us to consider it an actual URL, *unless* it was a full protocol match (like 'http://localhost') |
1364 |
| - this.urlMatchDoesNotHaveAtLeastOneWordChar( urlMatch ) || // At least one letter character must exist in the domain name after a protocol match. Ex: skip over something like "git:1.0" |
1365 |
| - this.isInvalidProtocolRelativeMatch( protocolRelativeMatch ) // A protocol-relative match which has a word character in front of it (so we can skip something like "abc//google.com") |
| 1364 | + this.urlMatchDoesNotHaveProtocolOrDot( urlMatch, protocolUrlMatch ) || // At least one period ('.') must exist in the URL match for us to consider it an actual URL, *unless* it was a full protocol match (like 'http://localhost') |
| 1365 | + this.urlMatchDoesNotHaveAtLeastOneWordChar( urlMatch, protocolUrlMatch ) || // At least one letter character must exist in the domain name after a protocol match. Ex: skip over something like "git:1.0" |
| 1366 | + this.isInvalidProtocolRelativeMatch( protocolRelativeMatch ) // A protocol-relative match which has a word character in front of it (so we can skip something like "abc//google.com") |
1366 | 1367 | ) {
|
1367 | 1368 | return false;
|
1368 | 1369 | }
|
|
1388 | 1389 | * match.
|
1389 | 1390 | */
|
1390 | 1391 | urlMatchDoesNotHaveProtocolOrDot : function( urlMatch, protocolUrlMatch ) {
|
1391 |
| - return ( urlMatch && ( !protocolUrlMatch || !this.hasFullProtocolRegex.test( protocolUrlMatch ) ) && urlMatch.indexOf( '.' ) === -1 ); |
| 1392 | + return ( !!urlMatch && ( !protocolUrlMatch || !this.hasFullProtocolRegex.test( protocolUrlMatch ) ) && urlMatch.indexOf( '.' ) === -1 ); |
1392 | 1393 | },
|
1393 | 1394 |
|
1394 | 1395 |
|
|
1400 | 1401 | *
|
1401 | 1402 | * @private
|
1402 | 1403 | * @param {String} urlMatch The matched URL, if there was one. Will be an empty string if the match is not a URL match.
|
| 1404 | + * @param {String} protocolUrlMatch The match URL string for a protocol match. Ex: 'http://yahoo.com'. This is used to |
| 1405 | + * know whether or not we have a protocol in the URL string, in order to check for a word character after the protocol |
| 1406 | + * separator (':'). |
1403 | 1407 | * @return {Boolean} `true` if the URL match does not have at least one word character in it after the protocol, `false`
|
1404 | 1408 | * otherwise.
|
1405 | 1409 | */
|
1406 |
| - urlMatchDoesNotHaveAtLeastOneWordChar : function( urlMatch ) { |
1407 |
| - return ( urlMatch && this.hasProtocolPrefixRegex.test( urlMatch ) && !this.hasWordCharAfterProtocolRegex.test( urlMatch ) ); |
| 1410 | + urlMatchDoesNotHaveAtLeastOneWordChar : function( urlMatch, protocolUrlMatch ) { |
| 1411 | + if( urlMatch && protocolUrlMatch ) { |
| 1412 | + return !this.hasWordCharAfterProtocolRegex.test( urlMatch ); |
| 1413 | + } else { |
| 1414 | + return false; |
| 1415 | + } |
1408 | 1416 | },
|
1409 | 1417 |
|
1410 | 1418 |
|
|
1420 | 1428 | * @return {Boolean} `true` if it is an invalid protocol-relative match, `false` otherwise.
|
1421 | 1429 | */
|
1422 | 1430 | isInvalidProtocolRelativeMatch : function( protocolRelativeMatch ) {
|
1423 |
| - return ( protocolRelativeMatch && this.invalidProtocolRelMatchRegex.test( protocolRelativeMatch ) ); |
| 1431 | + return ( !!protocolRelativeMatch && this.invalidProtocolRelMatchRegex.test( protocolRelativeMatch ) ); |
1424 | 1432 | }
|
1425 | 1433 |
|
1426 | 1434 | } );
|
|
1785 | 1793 | * The url that was matched.
|
1786 | 1794 | */
|
1787 | 1795 |
|
| 1796 | + /** |
| 1797 | + * @cfg {Boolean} protocolUrlMatch (required) |
| 1798 | + * |
| 1799 | + * `true` if the URL is a match which already has a protocol (i.e. 'http://'), `false` if the match was from a 'www' or |
| 1800 | + * known TLD match. |
| 1801 | + */ |
| 1802 | + |
1788 | 1803 | /**
|
1789 | 1804 | * @cfg {Boolean} protocolRelativeMatch (required)
|
1790 | 1805 | *
|
|
1816 | 1831 | protocolRelativeRegex : /^\/\//,
|
1817 | 1832 |
|
1818 | 1833 | /**
|
1819 |
| - * @protected |
1820 |
| - * @property {RegExp} checkForProtocolRegex |
| 1834 | + * @private |
| 1835 | + * @property {Boolean} protocolPrepended |
1821 | 1836 | *
|
1822 |
| - * A regular expression used to check if the {@link #url} is missing a protocol (in which case, 'http://' |
1823 |
| - * will be added). |
| 1837 | + * Will be set to `true` if the 'http://' protocol has been prepended to the {@link #url} (because the |
| 1838 | + * {@link #url} did not have a protocol) |
1824 | 1839 | */
|
1825 |
| - checkForProtocolRegex: /^[A-Za-z]{3,9}:/, |
| 1840 | + protocolPrepended : false, |
1826 | 1841 |
|
1827 | 1842 |
|
1828 | 1843 | /**
|
|
1836 | 1851 |
|
1837 | 1852 |
|
1838 | 1853 | /**
|
1839 |
| - * Returns the url that was matched, assuming the protocol to be 'http://' if the match |
1840 |
| - * was missing a protocol. |
| 1854 | + * Returns the url that was matched, assuming the protocol to be 'http://' if the original |
| 1855 | + * match was missing a protocol. |
1841 | 1856 | *
|
1842 | 1857 | * @return {String}
|
1843 | 1858 | */
|
1844 | 1859 | getUrl : function() {
|
1845 | 1860 | var url = this.url;
|
1846 | 1861 |
|
1847 |
| - // if the url string doesn't begin with a protocol, assume http:// |
1848 |
| - if( !this.protocolRelativeMatch && !this.checkForProtocolRegex.test( url ) ) { |
| 1862 | + // if the url string doesn't begin with a protocol, assume 'http://' |
| 1863 | + if( !this.protocolRelativeMatch && !this.protocolUrlMatch && !this.protocolPrepended ) { |
1849 | 1864 | url = this.url = 'http://' + url;
|
| 1865 | + |
| 1866 | + this.protocolPrepended = true; |
1850 | 1867 | }
|
1851 | 1868 |
|
1852 | 1869 | return url;
|
|
0 commit comments