Skip to content

Commit af0bf26

Browse files
committed
Move processing function for processTextNode() to a new method, processCandidateMatch(), in preparation to add a parse() method
1 parent 10e4865 commit af0bf26

File tree

1 file changed

+108
-59
lines changed

1 file changed

+108
-59
lines changed

src/Autolinker.js

Lines changed: 108 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,8 @@ Autolinker.prototype = {
324324
* This method finds the text around any HTML elements in the input `textOrHtml`, which will be the text that is processed.
325325
* Any original HTML elements will be left as-is, as well as the text that is already wrapped in anchor (<a>) tags.
326326
*
327-
* @param {String} textOrHtml The HTML or text to link URLs, email addresses, and Twitter handles within.
327+
* @param {String} textOrHtml The HTML or text to link URLs, email addresses, and Twitter handles within (depending on if
328+
* the {@link #urls}, {@link #email}, and {@link #twitter} options are enabled).
328329
* @return {String} The HTML, with URLs/emails/Twitter handles automatically linked.
329330
*/
330331
link : function( textOrHtml ) {
@@ -434,76 +435,124 @@ Autolinker.prototype = {
434435
* @return {String} The text with anchor tags auto-filled.
435436
*/
436437
processTextNode : function( text ) {
437-
var me = this, // for closure
438-
charBeforeProtocolRelMatchRegex = this.charBeforeProtocolRelMatchRegex;
438+
var me = this; // for closure
439439

440440
return text.replace( this.matcherRegex, function( matchStr, $1, $2, $3, $4, $5, $6, $7 ) {
441-
var twitterMatch = $1,
442-
twitterHandlePrefixWhitespaceChar = $2, // The whitespace char before the @ sign in a Twitter handle match. This is needed because of no lookbehinds in JS regexes.
443-
twitterHandle = $3, // The actual twitterUser (i.e the word after the @ sign in a Twitter handle match)
444-
emailAddressMatch = $4, // For both determining if it is an email address, and stores the actual email address
445-
urlMatch = $5, // The matched URL string
446-
protocolRelativeMatch = $6 || $7, // The '//' for a protocol-relative match, with the character that comes before the '//'
447-
448-
prefixStr = "", // A string to use to prefix the anchor tag that is created. This is needed for the Twitter handle match
449-
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.
450-
451-
match; // Will be an Autolinker.match.Match object
452-
441+
var matchDescObj = me.processCandidateMatch.apply( me, arguments ); // match description object
453442

454443
// Return out with no changes for match types that are disabled (url, email, twitter), or for matches that are
455444
// invalid (false positives from the matcherRegex, which can't use look-behinds since they are unavailable in JS).
456-
if( !me.isValidMatch( twitterMatch, emailAddressMatch, urlMatch, protocolRelativeMatch ) ) {
445+
if( !matchDescObj ) {
457446
return matchStr;
447+
448+
} else {
449+
// Generate the replacement text for the match
450+
var matchReturnVal = me.createMatchReturnVal( matchDescObj.match, matchDescObj.matchStr );
451+
return matchDescObj.prefixStr + matchReturnVal + matchDescObj.suffixStr;
458452
}
453+
} );
454+
},
455+
456+
457+
/**
458+
* Processes a candidate match from the {@link #matcherRegex}.
459+
*
460+
* Not all matches found by the regex are actual URL/email/Twitter matches, as determined by {@link #isValidMatch}. In
461+
* this case, the method returns `null`. Otherwise, a valid Object with `prefixStr`, `match`, and `suffixStr` is returned.
462+
*
463+
* @private
464+
* @param {String} matchStr The full match that was found by the {@link #matcherRegex}.
465+
* @param {String} twitterMatch The matched text of a Twitter handle, if the match is a Twitter match.
466+
* @param {String} twitterHandlePrefixWhitespaceChar The whitespace char before the @ sign in a Twitter handle match. This
467+
* is needed because of no lookbehinds in JS regexes, and is need to re-include the character for the anchor tag replacement.
468+
* @param {String} twitterHandle The actual Twitter user (i.e the word after the @ sign in a Twitter match).
469+
* @param {String} emailAddressMatch The matched email address for an email address match.
470+
* @param {String} urlMatch The matched URL string for a URL match.
471+
* @param {String} wwwProtocolRelativeMatch The '//' for a protocol-relative match from a 'www' url, with the character that
472+
* comes before the '//'.
473+
* @param {String} tldProtocolRelativeMatch The '//' for a protocol-relative match from a TLD (top level domain) match, with
474+
* the character that comes before the '//'.
475+
*
476+
* @return {Object} A "match description object". This will be `null` if the match was invalid, or if a match type is disabled.
477+
* Otherwise, this will be an Object (map) with the following properties:
478+
* @return {String} return.prefixStr The char(s) that should be prepended to the replacement string. These are char(s) that
479+
* were needed to be included from the regex match that were ignored by processing code, and should be re-inserted into
480+
* the replacement stream.
481+
* @return {String} return.suffixStr The char(s) that should be appended to the replacement string. These are char(s) that
482+
* were needed to be included from the regex match that were ignored by processing code, and should be re-inserted into
483+
* the replacement stream.
484+
* @return {String} return.matchStr The `matchStr`, fixed up to remove characters that are no longer needed (which have been
485+
* added to `prefixStr` and `suffixStr`).
486+
* @return {Autolinker.match.Match} return.match The Match object that represents the match that was found.
487+
*/
488+
processCandidateMatch : function(
489+
matchStr, twitterMatch, twitterHandlePrefixWhitespaceChar, twitterHandle,
490+
emailAddressMatch, urlMatch, wwwProtocolRelativeMatch, tldProtocolRelativeMatch
491+
) {
492+
var protocolRelativeMatch = wwwProtocolRelativeMatch || tldProtocolRelativeMatch,
493+
match, // Will be an Autolinker.match.Match object
494+
495+
prefixStr = "", // A string to use to prefix the anchor tag that is created. This is needed for the Twitter handle match
496+
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.
497+
498+
499+
// Return out with `null` for match types that are disabled (url, email, twitter), or for matches that are
500+
// invalid (false positives from the matcherRegex, which can't use look-behinds since they are unavailable in JS).
501+
if( !this.isValidMatch( twitterMatch, emailAddressMatch, urlMatch, protocolRelativeMatch ) ) {
502+
return null;
503+
}
504+
505+
// Handle a closing parenthesis at the end of the match, and exclude it if there is not a matching open parenthesis
506+
// in the match itself.
507+
if( this.matchHasUnbalancedClosingParen( matchStr ) ) {
508+
matchStr = matchStr.substr( 0, matchStr.length - 1 ); // remove the trailing ")"
509+
suffixStr = ")"; // this will be added after the generated <a> tag
510+
}
511+
512+
513+
if( emailAddressMatch ) {
514+
match = new Autolinker.match.Email( { matchedText: matchStr, email: emailAddressMatch } );
459515

460-
// Handle a closing parenthesis at the end of the match, and exclude it if there is not a matching open parenthesis
461-
// in the match itself.
462-
if( me.matchHasUnbalancedClosingParen( matchStr ) ) {
463-
matchStr = matchStr.substr( 0, matchStr.length - 1 ); // remove the trailing ")"
464-
suffixStr = ")"; // this will be added after the generated <a> tag
516+
} else if( twitterMatch ) {
517+
// fix up the `matchStr` if there was a preceding whitespace char, which was needed to determine the match
518+
// itself (since there are no look-behinds in JS regexes)
519+
if( twitterHandlePrefixWhitespaceChar ) {
520+
prefixStr = twitterHandlePrefixWhitespaceChar;
521+
matchStr = matchStr.slice( 1 ); // remove the prefixed whitespace char from the match
465522
}
523+
match = new Autolinker.match.Twitter( { matchedText: matchStr, twitterHandle: twitterHandle } );
466524

467-
468-
if( emailAddressMatch ) {
469-
match = new Autolinker.match.Email( { matchedText: matchStr, email: emailAddressMatch } );
525+
} else { // url match
526+
// If it's a protocol-relative '//' match, remove the character before the '//' (which the matcherRegex needed
527+
// to match due to the lack of a negative look-behind in JavaScript regular expressions)
528+
if( protocolRelativeMatch ) {
529+
var charBeforeMatch = protocolRelativeMatch.match( this.charBeforeProtocolRelMatchRegex )[ 1 ] || "";
470530

471-
} else if( twitterMatch ) {
472-
// fix up the `matchStr` if there was a preceding whitespace char, which was needed to determine the match
473-
// itself (since there are no look-behinds in JS regexes)
474-
if( twitterHandlePrefixWhitespaceChar ) {
475-
prefixStr = twitterHandlePrefixWhitespaceChar;
476-
matchStr = matchStr.slice( 1 ); // remove the prefixed whitespace char from the match
531+
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)
532+
prefixStr = charBeforeMatch;
533+
matchStr = matchStr.slice( 1 ); // remove the prefixed char from the match
477534
}
478-
match = new Autolinker.match.Twitter( { matchedText: matchStr, twitterHandle: twitterHandle } );
479-
480-
} else { // url match
481-
// If it's a protocol-relative '//' match, remove the character before the '//' (which the matcherRegex needed
482-
// to match due to the lack of a negative look-behind in JavaScript regular expressions)
483-
if( protocolRelativeMatch ) {
484-
var charBeforeMatch = protocolRelativeMatch.match( charBeforeProtocolRelMatchRegex )[ 1 ] || "";
485-
486-
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)
487-
prefixStr = charBeforeMatch;
488-
matchStr = matchStr.slice( 1 ); // remove the prefixed char from the match
489-
}
490-
}
491-
492-
match = new Autolinker.match.Url( {
493-
matchedText : matchStr,
494-
url : matchStr,
495-
protocolRelativeMatch : protocolRelativeMatch,
496-
stripPrefix : me.stripPrefix
497-
} );
498535
}
499-
500-
// Generate the replacement text for the match
501-
var matchReturnVal = me.createMatchReturnVal( match, matchStr );
502-
return prefixStr + matchReturnVal + suffixStr;
503-
} );
536+
537+
match = new Autolinker.match.Url( {
538+
matchedText : matchStr,
539+
url : matchStr,
540+
protocolRelativeMatch : protocolRelativeMatch,
541+
stripPrefix : this.stripPrefix
542+
} );
543+
}
544+
545+
return {
546+
prefixStr : prefixStr,
547+
suffixStr : suffixStr,
548+
matchStr : matchStr,
549+
match : match
550+
};
504551
},
505552

506553

554+
555+
507556
/**
508557
* Determines if a given match found by {@link #processTextNode} is valid. Will return `false` for:
509558
*
@@ -627,15 +676,15 @@ Autolinker.prototype = {
627676
* // Produces: "Go to <a href="http://google.com">google.com</a>"
628677
*
629678
* @static
630-
* @method link
631-
* @param {String} html The HTML text to link URLs within.
679+
* @param {String} textOrHtml The HTML or text to find URLs, email addresses, and Twitter handles within (depending on if
680+
* the {@link #urls}, {@link #email}, and {@link #twitter} options are enabled).
632681
* @param {Object} [options] Any of the configuration options for the Autolinker class, specified in an Object (map).
633682
* See the class description for an example call.
634683
* @return {String} The HTML text, with URLs automatically linked
635684
*/
636-
Autolinker.link = function( text, options ) {
685+
Autolinker.link = function( textOrHtml, options ) {
637686
var autolinker = new Autolinker( options );
638-
return autolinker.link( text );
687+
return autolinker.link( textOrHtml );
639688
};
640689

641690

0 commit comments

Comments
 (0)