|
1 | 1 | /*!
|
2 | 2 | * Autolinker.js
|
3 |
| - * 0.12.3 |
| 3 | + * 0.12.4 |
4 | 4 | *
|
5 | 5 | * Copyright(c) 2014 Gregory Jacobs <greg@greg-jacobs.com>
|
6 | 6 | * MIT Licensed. http://www.opensource.org/licenses/mit-license.php
|
|
344 | 344 | * This method finds the text around any HTML elements in the input `textOrHtml`, which will be the text that is processed.
|
345 | 345 | * Any original HTML elements will be left as-is, as well as the text that is already wrapped in anchor (<a>) tags.
|
346 | 346 | *
|
347 |
| - * @param {String} textOrHtml The HTML or text to link URLs, email addresses, and Twitter handles within. |
| 347 | + * @param {String} textOrHtml The HTML or text to link URLs, email addresses, and Twitter handles within (depending on if |
| 348 | + * the {@link #urls}, {@link #email}, and {@link #twitter} options are enabled). |
348 | 349 | * @return {String} The HTML, with URLs/emails/Twitter handles automatically linked.
|
349 | 350 | */
|
350 | 351 | link : function( textOrHtml ) {
|
|
454 | 455 | * @return {String} The text with anchor tags auto-filled.
|
455 | 456 | */
|
456 | 457 | processTextNode : function( text ) {
|
457 |
| - var me = this, // for closure |
458 |
| - charBeforeProtocolRelMatchRegex = this.charBeforeProtocolRelMatchRegex; |
| 458 | + var me = this; // for closure |
459 | 459 |
|
460 | 460 | return text.replace( this.matcherRegex, function( matchStr, $1, $2, $3, $4, $5, $6, $7 ) {
|
461 |
| - var twitterMatch = $1, |
462 |
| - twitterHandlePrefixWhitespaceChar = $2, // The whitespace char before the @ sign in a Twitter handle match. This is needed because of no lookbehinds in JS regexes. |
463 |
| - twitterHandle = $3, // The actual twitterUser (i.e the word after the @ sign in a Twitter handle match) |
464 |
| - emailAddressMatch = $4, // For both determining if it is an email address, and stores the actual email address |
465 |
| - urlMatch = $5, // The matched URL string |
466 |
| - protocolRelativeMatch = $6 || $7, // The '//' for a protocol-relative match, with the character that comes before the '//' |
467 |
| - |
468 |
| - prefixStr = "", // A string to use to prefix the anchor tag that is created. This is needed for the Twitter handle match |
469 |
| - suffixStr = "", // A string to suffix the anchor tag that is created. This is used if there is a trailing parenthesis that should not be auto-linked. |
470 |
| - |
471 |
| - match; // Will be an Autolinker.match.Match object |
472 |
| - |
| 461 | + var matchDescObj = me.processCandidateMatch.apply( me, arguments ); // match description object |
473 | 462 |
|
474 | 463 | // Return out with no changes for match types that are disabled (url, email, twitter), or for matches that are
|
475 | 464 | // invalid (false positives from the matcherRegex, which can't use look-behinds since they are unavailable in JS).
|
476 |
| - if( !me.isValidMatch( twitterMatch, emailAddressMatch, urlMatch, protocolRelativeMatch ) ) { |
| 465 | + if( !matchDescObj ) { |
477 | 466 | return matchStr;
|
| 467 | + |
| 468 | + } else { |
| 469 | + // Generate the replacement text for the match |
| 470 | + var matchReturnVal = me.createMatchReturnVal( matchDescObj.match, matchDescObj.matchStr ); |
| 471 | + return matchDescObj.prefixStr + matchReturnVal + matchDescObj.suffixStr; |
478 | 472 | }
|
| 473 | + } ); |
| 474 | + }, |
| 475 | + |
| 476 | + |
| 477 | + /** |
| 478 | + * Processes a candidate match from the {@link #matcherRegex}. |
| 479 | + * |
| 480 | + * Not all matches found by the regex are actual URL/email/Twitter matches, as determined by {@link #isValidMatch}. In |
| 481 | + * this case, the method returns `null`. Otherwise, a valid Object with `prefixStr`, `match`, and `suffixStr` is returned. |
| 482 | + * |
| 483 | + * @private |
| 484 | + * @param {String} matchStr The full match that was found by the {@link #matcherRegex}. |
| 485 | + * @param {String} twitterMatch The matched text of a Twitter handle, if the match is a Twitter match. |
| 486 | + * @param {String} twitterHandlePrefixWhitespaceChar The whitespace char before the @ sign in a Twitter handle match. This |
| 487 | + * is needed because of no lookbehinds in JS regexes, and is need to re-include the character for the anchor tag replacement. |
| 488 | + * @param {String} twitterHandle The actual Twitter user (i.e the word after the @ sign in a Twitter match). |
| 489 | + * @param {String} emailAddressMatch The matched email address for an email address match. |
| 490 | + * @param {String} urlMatch The matched URL string for a URL match. |
| 491 | + * @param {String} wwwProtocolRelativeMatch The '//' for a protocol-relative match from a 'www' url, with the character that |
| 492 | + * comes before the '//'. |
| 493 | + * @param {String} tldProtocolRelativeMatch The '//' for a protocol-relative match from a TLD (top level domain) match, with |
| 494 | + * the character that comes before the '//'. |
| 495 | + * |
| 496 | + * @return {Object} A "match description object". This will be `null` if the match was invalid, or if a match type is disabled. |
| 497 | + * Otherwise, this will be an Object (map) with the following properties: |
| 498 | + * @return {String} return.prefixStr The char(s) that should be prepended to the replacement string. These are char(s) that |
| 499 | + * were needed to be included from the regex match that were ignored by processing code, and should be re-inserted into |
| 500 | + * the replacement stream. |
| 501 | + * @return {String} return.suffixStr The char(s) that should be appended to the replacement string. These are char(s) that |
| 502 | + * were needed to be included from the regex match that were ignored by processing code, and should be re-inserted into |
| 503 | + * the replacement stream. |
| 504 | + * @return {String} return.matchStr The `matchStr`, fixed up to remove characters that are no longer needed (which have been |
| 505 | + * added to `prefixStr` and `suffixStr`). |
| 506 | + * @return {Autolinker.match.Match} return.match The Match object that represents the match that was found. |
| 507 | + */ |
| 508 | + processCandidateMatch : function( |
| 509 | + matchStr, twitterMatch, twitterHandlePrefixWhitespaceChar, twitterHandle, |
| 510 | + emailAddressMatch, urlMatch, wwwProtocolRelativeMatch, tldProtocolRelativeMatch |
| 511 | + ) { |
| 512 | + var protocolRelativeMatch = wwwProtocolRelativeMatch || tldProtocolRelativeMatch, |
| 513 | + match, // Will be an Autolinker.match.Match object |
| 514 | + |
| 515 | + prefixStr = "", // A string to use to prefix the anchor tag that is created. This is needed for the Twitter handle match |
| 516 | + suffixStr = ""; // A string to suffix the anchor tag that is created. This is used if there is a trailing parenthesis that should not be auto-linked. |
| 517 | + |
| 518 | + |
| 519 | + // Return out with `null` for match types that are disabled (url, email, twitter), or for matches that are |
| 520 | + // invalid (false positives from the matcherRegex, which can't use look-behinds since they are unavailable in JS). |
| 521 | + if( !this.isValidMatch( twitterMatch, emailAddressMatch, urlMatch, protocolRelativeMatch ) ) { |
| 522 | + return null; |
| 523 | + } |
| 524 | + |
| 525 | + // Handle a closing parenthesis at the end of the match, and exclude it if there is not a matching open parenthesis |
| 526 | + // in the match itself. |
| 527 | + if( this.matchHasUnbalancedClosingParen( matchStr ) ) { |
| 528 | + matchStr = matchStr.substr( 0, matchStr.length - 1 ); // remove the trailing ")" |
| 529 | + suffixStr = ")"; // this will be added after the generated <a> tag |
| 530 | + } |
| 531 | + |
| 532 | + |
| 533 | + if( emailAddressMatch ) { |
| 534 | + match = new Autolinker.match.Email( { matchedText: matchStr, email: emailAddressMatch } ); |
479 | 535 |
|
480 |
| - // Handle a closing parenthesis at the end of the match, and exclude it if there is not a matching open parenthesis |
481 |
| - // in the match itself. |
482 |
| - if( me.matchHasUnbalancedClosingParen( matchStr ) ) { |
483 |
| - matchStr = matchStr.substr( 0, matchStr.length - 1 ); // remove the trailing ")" |
484 |
| - suffixStr = ")"; // this will be added after the generated <a> tag |
| 536 | + } else if( twitterMatch ) { |
| 537 | + // fix up the `matchStr` if there was a preceding whitespace char, which was needed to determine the match |
| 538 | + // itself (since there are no look-behinds in JS regexes) |
| 539 | + if( twitterHandlePrefixWhitespaceChar ) { |
| 540 | + prefixStr = twitterHandlePrefixWhitespaceChar; |
| 541 | + matchStr = matchStr.slice( 1 ); // remove the prefixed whitespace char from the match |
485 | 542 | }
|
| 543 | + match = new Autolinker.match.Twitter( { matchedText: matchStr, twitterHandle: twitterHandle } ); |
486 | 544 |
|
487 |
| - |
488 |
| - if( emailAddressMatch ) { |
489 |
| - match = new Autolinker.match.Email( { matchedText: matchStr, email: emailAddressMatch } ); |
| 545 | + } else { // url match |
| 546 | + // If it's a protocol-relative '//' match, remove the character before the '//' (which the matcherRegex needed |
| 547 | + // to match due to the lack of a negative look-behind in JavaScript regular expressions) |
| 548 | + if( protocolRelativeMatch ) { |
| 549 | + var charBeforeMatch = protocolRelativeMatch.match( this.charBeforeProtocolRelMatchRegex )[ 1 ] || ""; |
490 | 550 |
|
491 |
| - } else if( twitterMatch ) { |
492 |
| - // fix up the `matchStr` if there was a preceding whitespace char, which was needed to determine the match |
493 |
| - // itself (since there are no look-behinds in JS regexes) |
494 |
| - if( twitterHandlePrefixWhitespaceChar ) { |
495 |
| - prefixStr = twitterHandlePrefixWhitespaceChar; |
496 |
| - matchStr = matchStr.slice( 1 ); // remove the prefixed whitespace char from the match |
| 551 | + if( charBeforeMatch ) { // fix up the `matchStr` if there was a preceding char before a protocol-relative match, which was needed to determine the match itself (since there are no look-behinds in JS regexes) |
| 552 | + prefixStr = charBeforeMatch; |
| 553 | + matchStr = matchStr.slice( 1 ); // remove the prefixed char from the match |
497 | 554 | }
|
498 |
| - match = new Autolinker.match.Twitter( { matchedText: matchStr, twitterHandle: twitterHandle } ); |
499 |
| - |
500 |
| - } else { // url match |
501 |
| - // If it's a protocol-relative '//' match, remove the character before the '//' (which the matcherRegex needed |
502 |
| - // to match due to the lack of a negative look-behind in JavaScript regular expressions) |
503 |
| - if( protocolRelativeMatch ) { |
504 |
| - var charBeforeMatch = protocolRelativeMatch.match( charBeforeProtocolRelMatchRegex )[ 1 ] || ""; |
505 |
| - |
506 |
| - if( charBeforeMatch ) { // fix up the `matchStr` if there was a preceding char before a protocol-relative match, which was needed to determine the match itself (since there are no look-behinds in JS regexes) |
507 |
| - prefixStr = charBeforeMatch; |
508 |
| - matchStr = matchStr.slice( 1 ); // remove the prefixed char from the match |
509 |
| - } |
510 |
| - } |
511 |
| - |
512 |
| - match = new Autolinker.match.Url( { |
513 |
| - matchedText : matchStr, |
514 |
| - url : matchStr, |
515 |
| - protocolRelativeMatch : protocolRelativeMatch, |
516 |
| - stripPrefix : me.stripPrefix |
517 |
| - } ); |
518 | 555 | }
|
519 |
| - |
520 |
| - // Generate the replacement text for the match |
521 |
| - var matchReturnVal = me.createMatchReturnVal( match, matchStr ); |
522 |
| - return prefixStr + matchReturnVal + suffixStr; |
523 |
| - } ); |
| 556 | + |
| 557 | + match = new Autolinker.match.Url( { |
| 558 | + matchedText : matchStr, |
| 559 | + url : matchStr, |
| 560 | + protocolRelativeMatch : protocolRelativeMatch, |
| 561 | + stripPrefix : this.stripPrefix |
| 562 | + } ); |
| 563 | + } |
| 564 | + |
| 565 | + return { |
| 566 | + prefixStr : prefixStr, |
| 567 | + suffixStr : suffixStr, |
| 568 | + matchStr : matchStr, |
| 569 | + match : match |
| 570 | + }; |
524 | 571 | },
|
525 | 572 |
|
526 | 573 |
|
| 574 | + |
| 575 | + |
527 | 576 | /**
|
528 | 577 | * Determines if a given match found by {@link #processTextNode} is valid. Will return `false` for:
|
529 | 578 | *
|
|
647 | 696 | * // Produces: "Go to <a href="http://google.com">google.com</a>"
|
648 | 697 | *
|
649 | 698 | * @static
|
650 |
| - * @method link |
651 |
| - * @param {String} html The HTML text to link URLs within. |
| 699 | + * @param {String} textOrHtml The HTML or text to find URLs, email addresses, and Twitter handles within (depending on if |
| 700 | + * the {@link #urls}, {@link #email}, and {@link #twitter} options are enabled). |
652 | 701 | * @param {Object} [options] Any of the configuration options for the Autolinker class, specified in an Object (map).
|
653 | 702 | * See the class description for an example call.
|
654 | 703 | * @return {String} The HTML text, with URLs automatically linked
|
655 | 704 | */
|
656 |
| - Autolinker.link = function( text, options ) { |
| 705 | + Autolinker.link = function( textOrHtml, options ) { |
657 | 706 | var autolinker = new Autolinker( options );
|
658 |
| - return autolinker.link( text ); |
| 707 | + return autolinker.link( textOrHtml ); |
659 | 708 | };
|
660 | 709 |
|
661 | 710 |
|
|
0 commit comments